From: Garrett Regier Date: Tue, 21 Sep 2021 22:13:34 +0000 (-0700) Subject: builder: Reduce memory usage in precompile X-Git-Tag: archive/raspbian/4.6.5+ds-1+rpi1~1^2~19^2~5^2~56^2~6 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4ce07f41ca9235f27bff6a83c082177067679aba;p=gtk4.git builder: Reduce memory usage in precompile Split the Element and Text nodes into separate structures. --- diff --git a/gtk/gtkbuilderprecompile.c b/gtk/gtkbuilderprecompile.c index 00f2a796ac..6c910d79be 100644 --- a/gtk/gtkbuilderprecompile.c +++ b/gtk/gtkbuilderprecompile.c @@ -30,7 +30,7 @@ typedef enum RECORD_TYPE_ELEMENT, RECORD_TYPE_END_ELEMENT, RECORD_TYPE_TEXT, -} RecordTreeType; +} RecordDataType; /* All strings are owned by the string chunk */ typedef struct { @@ -42,58 +42,110 @@ typedef struct { gboolean include_len; } RecordDataString; -typedef struct RecordDataTree RecordDataTree; +typedef struct { + RecordDataType type; + GList link; +} RecordDataNode; + +typedef struct RecordDataElement RecordDataElement; -struct RecordDataTree { - RecordDataTree *parent; - RecordTreeType type; +struct RecordDataElement { + RecordDataNode base; + + RecordDataElement *parent; int n_attributes; - RecordDataString *data; + RecordDataString *name; RecordDataString **attributes; - GList link; GQueue children; }; +typedef struct { + RecordDataNode base; + + RecordDataString *string; +} RecordDataText; + typedef struct { GHashTable *strings; GStringChunk *chunks; - RecordDataTree *root; - RecordDataTree *current; + RecordDataElement *root; + RecordDataElement *current; } RecordData; -static RecordDataTree * -record_data_tree_new (RecordDataTree *parent, - RecordTreeType type, - RecordDataString *data) +static gpointer +record_data_node_new (RecordDataElement *parent, + RecordDataType type, + gsize size) { - RecordDataTree *tree = g_slice_new0 (RecordDataTree); + RecordDataNode *node = g_slice_alloc0 (size); - tree->parent = parent; - tree->type = type; - tree->data = data; - tree->link.data = tree; + node->type = type; + node->link.data = node; if (parent) - g_queue_push_tail_link (&parent->children, &tree->link); + g_queue_push_tail_link (&parent->children, &node->link); + + return node; +} + +static RecordDataElement * +record_data_element_new (RecordDataElement *parent, + RecordDataString *name) +{ + RecordDataElement *element; + + element = record_data_node_new (parent, + RECORD_TYPE_ELEMENT, + sizeof (RecordDataElement)); + element->parent = parent; + element->name = name; + + return element; +} + +static void +record_data_element_append_text (RecordDataElement *parent, + RecordDataString *string) +{ + RecordDataText *text; - return tree; + text = record_data_node_new (parent, + RECORD_TYPE_TEXT, + sizeof (RecordDataText)); + text->string = string; } static void -record_data_tree_free (RecordDataTree *tree) +record_data_node_free (RecordDataNode *node) { GList *l, *next; + RecordDataText *text; + RecordDataElement *element; - l = tree->children.head; - while (l) + switch (node->type) { - next = l->next; - record_data_tree_free (l->data); - l = next; - } + case RECORD_TYPE_ELEMENT: + element = (RecordDataElement *)node; + + l = element->children.head; + while (l) + { + next = l->next; + record_data_node_free (l->data); + l = next; + } - g_free (tree->attributes); - g_slice_free (RecordDataTree, tree); + g_free (element->attributes); + g_slice_free (RecordDataElement, element); + break; + case RECORD_TYPE_TEXT: + text = (RecordDataText *)node; + g_slice_free (RecordDataText, text); + break; + case RECORD_TYPE_END_ELEMENT: + default: + g_assert_not_reached (); + } } static void @@ -180,12 +232,12 @@ record_start_element (GMarkupParseContext *context, { gsize n_attrs = g_strv_length ((char **)names); RecordData *data = user_data; - RecordDataTree *child; - RecordDataString **attr_names, **attr_values; + RecordDataElement *child; + RecordDataString *name, **attr_names, **attr_values; int i; - child = record_data_tree_new (data->current, RECORD_TYPE_ELEMENT, - record_data_string_lookup (data, element_name, -1)); + name = record_data_string_lookup (data, element_name, -1); + child = record_data_element_new (data->current, name); data->current = child; child->n_attributes = n_attrs; @@ -219,9 +271,10 @@ record_text (GMarkupParseContext *context, GError **error) { RecordData *data = user_data; + RecordDataString *string; - record_data_tree_new (data->current, RECORD_TYPE_TEXT, - record_data_string_lookup (data, text, text_len)); + string = record_data_string_lookup (data, text, text_len); + record_data_element_append_text (data->current, string); } static const GMarkupParser record_parser = @@ -301,42 +354,45 @@ marshal_uint32_len (guint32 v) static void marshal_tree (GString *marshaled, - RecordDataTree *tree) + RecordDataNode *node) { GList *l; int i; + RecordDataText *text; + RecordDataElement *element; RecordDataString **attr_names, **attr_values; - /* Special case the root */ - if (tree->parent == NULL) - { - for (l = tree->children.head; l != NULL; l = l->next) - marshal_tree (marshaled, l->data); - return; - } - - switch (tree->type) + switch (node->type) { case RECORD_TYPE_ELEMENT: - marshal_uint32 (marshaled, RECORD_TYPE_ELEMENT); - marshal_uint32 (marshaled, tree->data->offset); - marshal_uint32 (marshaled, tree->n_attributes); + element = (RecordDataElement *)node; - attr_names = &tree->attributes[0]; - attr_values = &tree->attributes[tree->n_attributes]; - for (i = 0; i < tree->n_attributes; i++) + /* Special case the root */ + if (element->parent != NULL) { - marshal_uint32 (marshaled, attr_names[i]->offset); - marshal_uint32 (marshaled, attr_values[i]->offset); + marshal_uint32 (marshaled, RECORD_TYPE_ELEMENT); + marshal_uint32 (marshaled, element->name->offset); + marshal_uint32 (marshaled, element->n_attributes); + + attr_names = &element->attributes[0]; + attr_values = &element->attributes[element->n_attributes]; + for (i = 0; i < element->n_attributes; i++) + { + marshal_uint32 (marshaled, attr_names[i]->offset); + marshal_uint32 (marshaled, attr_values[i]->offset); + } } - for (l = tree->children.head; l != NULL; l = l->next) + + for (l = element->children.head; l != NULL; l = l->next) marshal_tree (marshaled, l->data); - marshal_uint32 (marshaled, RECORD_TYPE_END_ELEMENT); + if (element->parent != NULL) + marshal_uint32 (marshaled, RECORD_TYPE_END_ELEMENT); break; case RECORD_TYPE_TEXT: + text = (RecordDataText *)node; marshal_uint32 (marshaled, RECORD_TYPE_TEXT); - marshal_uint32 (marshaled, tree->data->text_offset); + marshal_uint32 (marshaled, text->string->text_offset); break; case RECORD_TYPE_END_ELEMENT: default: @@ -369,7 +425,7 @@ _gtk_buildable_parser_precompile (const char *text, data.strings = g_hash_table_new_full (record_data_string_hash, record_data_string_equal, (GDestroyNotify)record_data_string_free, NULL); data.chunks = g_string_chunk_new (512); - data.root = record_data_tree_new (NULL, RECORD_TYPE_ELEMENT, NULL); + data.root = record_data_element_new (NULL, NULL); data.current = data.root; ctx = g_markup_parse_context_new (&record_parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &data, NULL); @@ -377,7 +433,7 @@ _gtk_buildable_parser_precompile (const char *text, if (!g_markup_parse_context_parse (ctx, text, text_len, error) || !g_markup_parse_context_end_parse (ctx, error)) { - record_data_tree_free (data.root); + record_data_node_free (&data.root->base); g_string_chunk_free (data.chunks); g_hash_table_destroy (data.strings); g_markup_parse_context_free (ctx); @@ -421,9 +477,9 @@ _gtk_buildable_parser_precompile (const char *text, g_list_free (string_table); - marshal_tree (marshaled, data.root); + marshal_tree (marshaled, &data.root->base); - record_data_tree_free (data.root); + record_data_node_free (&data.root->base); g_string_chunk_free (data.chunks); g_hash_table_destroy (data.strings);