[script] Add a finish method to the interpreter

When using fonts circular references are established between the holdover
font caches and the interpreter which need manual intervention via
cairo_script_interpreter_finish() to break.
This commit is contained in:
Chris Wilson 2009-06-06 12:59:39 +01:00
parent 098822d7ee
commit 867c88ae90
5 changed files with 70 additions and 25 deletions

View file

@ -232,6 +232,7 @@ execute (cairo_perf_t *perf,
cairo_perf_timer_stop ();
times[i] = cairo_perf_timer_elapsed ();
cairo_script_interpreter_finish (csi);
cairo_script_interpreter_destroy (csi);
if (perf->raw) {
@ -426,12 +427,10 @@ cairo_perf_fini (cairo_perf_t *perf)
{
cairo_boilerplate_free_targets (perf->targets);
free (perf->times);
#if 0 /* XXX */
cairo_debug_reset_static_data ();
#if HAVE_FCFINI
FcFini ();
#endif
#endif
}
static cairo_bool_t

View file

@ -116,6 +116,9 @@ _csi_perm_alloc (csi_t *ctx, int size)
void *
_csi_slab_alloc (csi_t *ctx, int size)
{
#if CSI_DEBUG_MALLOC
return malloc (size);
#else
int chunk_size;
csi_chunk_t *chunk;
void *ptr;
@ -150,6 +153,7 @@ _csi_slab_alloc (csi_t *ctx, int size)
chunk->rem--;
return ptr;
#endif
}
void
@ -161,12 +165,16 @@ _csi_slab_free (csi_t *ctx, void *ptr, int size)
if (_csi_unlikely (ptr == NULL))
return;
#if CSI_DEBUG_MALLOC
free (ptr);
#else
chunk_size = 2 * sizeof (void *);
chunk_size = (size + chunk_size - 1) / chunk_size;
free_list = ptr;
*free_list = ctx->slabs[chunk_size].free_list;
ctx->slabs[chunk_size].free_list = ptr;
#endif
}
static void
@ -396,16 +404,6 @@ _csi_fini (csi_t *ctx)
_csi_scanner_fini (ctx, &ctx->scanner);
_csi_hash_table_fini (&ctx->strings);
if (ctx->free_array != NULL)
csi_array_free (ctx, ctx->free_array);
if (ctx->free_dictionary != NULL)
csi_dictionary_free (ctx, ctx->free_dictionary);
if (ctx->free_string != NULL)
csi_string_free (ctx, ctx->free_string);
_csi_slab_fini (ctx);
_csi_perm_fini (ctx);
}
csi_status_t
@ -530,6 +528,8 @@ cairo_script_interpreter_run (csi_t *ctx, const char *filename)
if (ctx->status)
return ctx->status;
if (ctx->finished)
return ctx->status = CSI_STATUS_INTERPRETER_FINISHED;
ctx->status = csi_file_new (ctx, &file, filename, "r");
if (ctx->status)
@ -550,6 +550,8 @@ cairo_script_interpreter_feed_string (csi_t *ctx, const char *line, int len)
if (ctx->status)
return ctx->status;
if (ctx->finished)
return ctx->status = CSI_STATUS_INTERPRETER_FINISHED;
if (len < 0)
len = strlen (line);
@ -573,6 +575,22 @@ cairo_script_interpreter_reference (csi_t *ctx)
}
slim_hidden_def (cairo_script_interpreter_reference);
cairo_status_t
cairo_script_interpreter_finish (csi_t *ctx)
{
csi_status_t status;
status = ctx->status;
if (! ctx->finished) {
_csi_fini (ctx);
ctx->finished = 1;
} else if (status == CAIRO_STATUS_SUCCESS) {
status = ctx->status = CSI_STATUS_INTERPRETER_FINISHED;
}
return status;
}
cairo_status_t
cairo_script_interpreter_destroy (csi_t *ctx)
{
@ -582,7 +600,18 @@ cairo_script_interpreter_destroy (csi_t *ctx)
if (--ctx->ref_count)
return status;
_csi_fini (ctx);
if (! ctx->finished)
_csi_fini (ctx);
if (ctx->free_array != NULL)
csi_array_free (ctx, ctx->free_array);
if (ctx->free_dictionary != NULL)
csi_dictionary_free (ctx, ctx->free_dictionary);
if (ctx->free_string != NULL)
csi_string_free (ctx, ctx->free_string);
_csi_slab_fini (ctx);
_csi_perm_fini (ctx);
free (ctx);
return status;

View file

@ -91,6 +91,9 @@ cairo_script_interpreter_feed_string (cairo_script_interpreter_t *ctx,
cairo_public cairo_script_interpreter_t *
cairo_script_interpreter_reference (cairo_script_interpreter_t *ctx);
cairo_public cairo_status_t
cairo_script_interpreter_finish (cairo_script_interpreter_t *ctx);
cairo_public cairo_status_t
cairo_script_interpreter_destroy (cairo_script_interpreter_t *ctx);

View file

@ -157,6 +157,16 @@ _csi_array_execute (csi_t *ctx, csi_array_t *array)
void
csi_array_free (csi_t *ctx, csi_array_t *array)
{
#if CSI_DEBUG_MALLOC
_csi_stack_fini (ctx, &array->stack);
_csi_slab_free (ctx, array, sizeof (csi_array_t));
#else
csi_integer_t n;
for (n = 0; n < array->stack.len; n++)
csi_object_free (ctx, &array->stack.objects[n]);
array->stack.len = 0;
if (ctx->free_array != NULL) {
if (array->stack.size > ctx->free_array->stack.size) {
csi_array_t *tmp = ctx->free_array;
@ -166,18 +176,9 @@ csi_array_free (csi_t *ctx, csi_array_t *array)
_csi_stack_fini (ctx, &array->stack);
_csi_slab_free (ctx, array, sizeof (csi_array_t));
} else {
csi_integer_t n;
for (n = 0; n < array->stack.len; n++)
csi_object_free (ctx, &array->stack.objects[n]);
array->stack.len = 0;
if (ctx->free_array == NULL)
ctx->free_array = array;
else
csi_array_free (ctx, array);
}
} else
ctx->free_array = array;
#endif
}
csi_status_t
@ -262,11 +263,16 @@ csi_dictionary_free (csi_t *ctx,
_dictionary_entry_pluck,
&data);
#if CSI_DEBUG_MALLOC
_csi_hash_table_fini (&dict->hash_table);
_csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
#else
if (ctx->free_dictionary != NULL) {
_csi_hash_table_fini (&dict->hash_table);
_csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
} else
ctx->free_dictionary = dict;
#endif
}
csi_status_t
@ -575,6 +581,10 @@ _csi_string_execute (csi_t *ctx, csi_string_t *string)
void
csi_string_free (csi_t *ctx, csi_string_t *string)
{
#if CSI_DEBUG_MALLOC
_csi_free (ctx, string->string);
_csi_slab_free (ctx, string, sizeof (csi_string_t));
#else
if (ctx->free_string != NULL) {
if (string->len > ctx->free_string->len) {
csi_string_t *tmp = ctx->free_string;
@ -586,6 +596,7 @@ csi_string_free (csi_t *ctx, csi_string_t *string)
_csi_slab_free (ctx, string, sizeof (csi_string_t));
} else
ctx->free_string = string;
#endif
}
csi_status_t

View file

@ -219,6 +219,7 @@ typedef enum _csi_status {
CSI_STATUS_SCRIPT_INVALID_TYPE,
CSI_STATUS_SCRIPT_INVALID_INDEX,
CSI_STATUS_SCRIPT_UNDEFINED_NAME,
CSI_STATUS_INTERPRETER_FINISHED,
_CSI_STATUS_SCRIPT_LAST_ERROR,
CSI_INT_STATUS_UNSUPPORTED
@ -453,6 +454,8 @@ struct _cairo_script_interpreter {
int ref_count;
csi_status_t status;
unsigned int finished : 1;
csi_hooks_t hooks;
csi_hash_table_t strings;