From 983a03d5f85f4e10f5392df2fd2de0c0bf670f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Wilmet?= Date: Fri, 11 Apr 2014 17:45:50 +0200 Subject: [PATCH] GtkTextView: use GSlice to allocate GtkTextLineSegment's Use GSlice to allocate all types of segments: - char - toggle - mark - pixbuf - child widget Char segments are a bit more complicated because the length of the text is determined at run time and stored in the 'byte_count' field. If the text is long, GSlice will call the system malloc() anyway, so it's better to always use GSlice for GtkTextLineSegment. Toggle segments are also freed in gtktextbtree.c, hence the function _gtk_toggle_segment_free() (for a later commit it would be nice to rename those functions with the _gtk_text prefix). https://bugzilla.gnome.org/show_bug.cgi?id=727908 --- gtk/gtktextbtree.c | 7 ++++--- gtk/gtktextchild.c | 22 +++++++++++----------- gtk/gtktextmark.c | 17 +++++++---------- gtk/gtktextsegment.c | 43 +++++++++++++++++++++++++++++++++---------- gtk/gtktextsegment.h | 1 + 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index a7c86c5120..825eb95693 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -65,6 +65,7 @@ #include "gtktextiterprivate.h" #include "gtkdebug.h" #include "gtktextmarkprivate.h" +#include "gtktextsegment.h" /* * Types @@ -901,9 +902,9 @@ _gtk_text_btree_delete (GtkTextIter *start, * cleanup_line() below. See bug 317125. */ next2 = prev_seg->next->next; - g_free ((char *)prev_seg->next); + _gtk_toggle_segment_free (prev_seg->next); prev_seg->next = next2; - g_free ((char *)seg); + _gtk_toggle_segment_free (seg); seg = NULL; } else @@ -1952,7 +1953,7 @@ _gtk_text_btree_tag (const GtkTextIter *start_orig, seg->body.toggle.inNodeCounts = FALSE; } - g_free (seg); + _gtk_toggle_segment_free (seg); /* We only clean up lines when we're done with them, saves some gratuitous line-segment-traversals */ diff --git a/gtk/gtktextchild.c b/gtk/gtktextchild.c index de609d49e9..96e7ffd225 100644 --- a/gtk/gtktextchild.c +++ b/gtk/gtktextchild.c @@ -73,6 +73,12 @@ } \ } G_STMT_END +#define PIXBUF_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ + + sizeof (GtkTextPixbuf))) + +#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ + + sizeof (GtkTextChildBody))) + static GtkTextLineSegment * pixbuf_segment_cleanup_func (GtkTextLineSegment *seg, GtkTextLine *line) @@ -89,7 +95,7 @@ pixbuf_segment_delete_func (GtkTextLineSegment *seg, if (seg->body.pixbuf.pixbuf) g_object_unref (seg->body.pixbuf.pixbuf); - g_free (seg); + g_slice_free1 (PIXBUF_SEG_SIZE, seg); return 0; } @@ -120,15 +126,12 @@ const GtkTextLineSegmentClass gtk_text_pixbuf_type = { }; -#define PIXBUF_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ - + sizeof (GtkTextPixbuf))) - GtkTextLineSegment * _gtk_pixbuf_segment_new (GdkPixbuf *pixbuf) { GtkTextLineSegment *seg; - seg = g_malloc (PIXBUF_SEG_SIZE); + seg = g_slice_alloc (PIXBUF_SEG_SIZE); seg->type = >k_text_pixbuf_type; @@ -218,15 +221,12 @@ const GtkTextLineSegmentClass gtk_text_child_type = { child_segment_check_func /* checkFunc */ }; -#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ - + sizeof (GtkTextChildBody))) - GtkTextLineSegment * _gtk_widget_segment_new (GtkTextChildAnchor *anchor) { GtkTextLineSegment *seg; - seg = g_malloc (WIDGET_SEG_SIZE); + seg = g_slice_alloc (WIDGET_SEG_SIZE); seg->type = >k_text_child_type; @@ -370,8 +370,8 @@ gtk_text_child_anchor_finalize (GObject *obj) } g_slist_free (seg->body.child.widgets); - - g_free (seg); + + g_slice_free1 (WIDGET_SEG_SIZE, seg); } anchor->segment = NULL; diff --git a/gtk/gtktextmark.c b/gtk/gtktextmark.c index 7a1b7e3334..d79e5322b6 100644 --- a/gtk/gtktextmark.c +++ b/gtk/gtktextmark.c @@ -90,6 +90,11 @@ * Marks are typically created using the gtk_text_buffer_create_mark() function. */ +/* + * Macro that determines the size of a mark segment: + */ +#define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ + + sizeof (GtkTextMarkBody))) static void gtk_text_mark_set_property (GObject *object, guint prop_id, @@ -161,7 +166,7 @@ gtk_text_mark_finalize (GObject *obj) "impending"); g_free (seg->body.mark.name); - g_free (seg); + g_slice_free1 (MSEG_SIZE, seg); mark->segment = NULL; } @@ -358,20 +363,12 @@ gtk_text_mark_get_left_gravity (GtkTextMark *mark) return seg->type == >k_text_left_mark_type; } -/* - * Macro that determines the size of a mark segment: - */ - -#define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \ - + sizeof (GtkTextMarkBody))) - - static GtkTextLineSegment * gtk_mark_segment_new (GtkTextMark *mark_obj) { GtkTextLineSegment *mark; - mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE); + mark = g_slice_alloc0 (MSEG_SIZE); mark->body.mark.name = NULL; mark->type = >k_text_right_mark_type; diff --git a/gtk/gtktextsegment.c b/gtk/gtktextsegment.c index c815262cf3..beb92cf1bc 100644 --- a/gtk/gtktextsegment.c +++ b/gtk/gtktextsegment.c @@ -194,7 +194,7 @@ _gtk_char_segment_new (const gchar *text, guint len) g_assert (gtk_text_byte_begins_utf8_char (text)); - seg = g_malloc (CSEG_SIZE (len)); + seg = g_slice_alloc (CSEG_SIZE (len)); seg->type = (GtkTextLineSegmentClass *)>k_text_char_type; seg->next = NULL; seg->byte_count = len; @@ -222,7 +222,7 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1, g_assert (gtk_text_byte_begins_utf8_char (text1)); g_assert (gtk_text_byte_begins_utf8_char (text2)); - seg = g_malloc (CSEG_SIZE (len1+len2)); + seg = g_slice_alloc (CSEG_SIZE (len1+len2)); seg->type = >k_text_char_type; seg->next = NULL; seg->byte_count = len1 + len2; @@ -238,6 +238,17 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1, return seg; } +static void +_gtk_char_segment_free (GtkTextLineSegment *seg) +{ + if (seg == NULL) + return; + + g_assert (seg->type == >k_text_char_type); + + g_slice_free1 (CSEG_SIZE (seg->byte_count), seg); +} + /* *-------------------------------------------------------------- * @@ -285,7 +296,7 @@ char_segment_split_func (GtkTextLineSegment *seg, int index) char_segment_self_check (new2); } - g_free (seg); + _gtk_char_segment_free (seg); return new1; } @@ -340,8 +351,8 @@ char_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line) if (gtk_get_debug_flags () & GTK_DEBUG_TEXT) char_segment_self_check (newPtr); - g_free (segPtr); - g_free (segPtr2); + _gtk_char_segment_free (segPtr); + _gtk_char_segment_free (segPtr2); return newPtr; } @@ -371,7 +382,7 @@ char_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line) static int char_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone) { - g_free ((char*) segPtr); + _gtk_char_segment_free (segPtr); return 0; } @@ -417,7 +428,7 @@ _gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on) { GtkTextLineSegment *seg; - seg = g_malloc (TSEG_SIZE); + seg = g_slice_alloc (TSEG_SIZE); seg->type = on ? >k_text_toggle_on_type : >k_text_toggle_off_type; @@ -432,6 +443,18 @@ _gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on) return seg; } +void +_gtk_toggle_segment_free (GtkTextLineSegment *seg) +{ + if (seg == NULL) + return; + + g_assert (seg->type == >k_text_toggle_on_type || + seg->type == >k_text_toggle_off_type); + + g_slice_free1 (TSEG_SIZE, seg); +} + /* *-------------------------------------------------------------- * @@ -462,7 +485,7 @@ toggle_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int t { if (treeGone) { - g_free ((char *) segPtr); + _gtk_toggle_segment_free (segPtr); return 0; } @@ -545,9 +568,9 @@ toggle_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line) segPtr->body.toggle.info, -counts); } prevPtr->next = segPtr2->next; - g_free ((char *) segPtr2); + _gtk_toggle_segment_free (segPtr2); segPtr2 = segPtr->next; - g_free ((char *) segPtr); + _gtk_toggle_segment_free (segPtr); return segPtr2; } } diff --git a/gtk/gtktextsegment.h b/gtk/gtktextsegment.h index ea5f90423c..5621bdee84 100644 --- a/gtk/gtktextsegment.h +++ b/gtk/gtktextsegment.h @@ -164,6 +164,7 @@ GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar *text GtkTextLineSegment *_gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on); +void _gtk_toggle_segment_free (GtkTextLineSegment *seg); G_END_DECLS