Index: glib/garray.c
===================================================================
RCS file: /cvs/gnome/glib/glib/garray.c,v
retrieving revision 1.37
diff -u -p -d -r1.37 garray.c
--- glib/garray.c	25 Jan 2006 15:51:43 -0000	1.37
+++ glib/garray.c	21 Apr 2006 11:23:04 -0000
@@ -42,6 +42,7 @@
 
 #include "galias.h"
 
+#include "valgrind/memcheck.h"
 
 #define MIN_ARRAY_SIZE  16
 
@@ -67,8 +68,11 @@ struct _GRealArray
 }G_STMT_END
 
 static gint g_nearest_pow        (gint        num) G_GNUC_CONST;
-static void g_array_maybe_expand (GRealArray *array,
-				  gint        len);
+
+static void g_array_expand_prepare (GRealArray *array,
+				    gint        len);
+static void g_array_shrink (GRealArray *array,
+			    gint        len);
 
 GArray*
 g_array_new (gboolean zero_terminated,
@@ -94,7 +98,19 @@ GArray* g_array_sized_new (gboolean zero
 
   if (array->zero_terminated || reserved_size != 0)
     {
-      g_array_maybe_expand (array, reserved_size);
+      guint want_alloc = g_nearest_pow (g_array_elt_len (array, zero_terminated+reserved_size));
+      guint want_len = zero_terminated ? elt_size : 0;
+
+      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
+
+      array->data = g_malloc (want_alloc);
+      array->alloc = want_alloc;
+
+      if (G_UNLIKELY (g_mem_gc_friendly))
+        memset (array->data, 0, want_alloc);
+
+      VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
+
       g_array_zero_terminate(array);
     }
 
@@ -129,7 +145,7 @@ g_array_append_vals (GArray       *farra
 {
   GRealArray *array = (GRealArray*) farray;
 
-  g_array_maybe_expand (array, len);
+  g_array_expand_prepare (array, len);
 
   memcpy (g_array_elt_pos (array, array->len), data, 
 	  g_array_elt_len (array, len));
@@ -148,7 +164,7 @@ g_array_prepend_vals (GArray        *far
 {
   GRealArray *array = (GRealArray*) farray;
 
-  g_array_maybe_expand (array, len);
+  g_array_expand_prepare (array, len);
 
   g_memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0), 
 	     g_array_elt_len (array, array->len));
@@ -170,7 +186,7 @@ g_array_insert_vals (GArray        *farr
 {
   GRealArray *array = (GRealArray*) farray;
 
-  g_array_maybe_expand (array, len);
+  g_array_expand_prepare (array, len);
 
   g_memmove (g_array_elt_pos (array, len + index), 
 	     g_array_elt_pos (array, index), 
@@ -192,13 +208,13 @@ g_array_set_size (GArray *farray,
   GRealArray *array = (GRealArray*) farray;
   if (length > array->len)
     {
-      g_array_maybe_expand (array, length - array->len);
+      g_array_expand_prepare (array, length - array->len);
       
       if (array->clear)
 	g_array_elt_zero (array, array->len, length - array->len);
     }
-  else if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
-    g_array_elt_zero (array, length, array->len - length);
+  else if (length < array->len)
+    g_array_shrink (array, array->len - length);
   
   array->len = length;
   
@@ -222,12 +238,9 @@ g_array_remove_index (GArray* farray,
 	       g_array_elt_pos (array, index + 1),
 	       g_array_elt_len (array, array->len - index - 1));
   
-  array->len -= 1;
+  g_array_shrink (array, 1);
 
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    g_array_elt_zero (array, array->len, 1);
-  else
-    g_array_zero_terminate (array);
+  g_array_zero_terminate (array);
 
   return farray;
 }
@@ -247,12 +260,9 @@ g_array_remove_index_fast (GArray* farra
 	    g_array_elt_pos (array, array->len - 1),
 	    g_array_elt_len (array, 1));
   
-  array->len -= 1;
+  g_array_shrink (array, 1);
 
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    g_array_elt_zero (array, array->len, 1);
-  else
-    g_array_zero_terminate (array);
+  g_array_zero_terminate (array);
 
   return farray;
 }
@@ -273,11 +283,9 @@ g_array_remove_range (GArray       *farr
                g_array_elt_pos (array, index_ + length), 
                (array->len - (index_ + length)) * array->elt_size);
 
-  array->len -= length;
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    g_array_elt_zero (array, array->len, length);
-  else
-    g_array_zero_terminate (array);
+  g_array_shrink (array, length);
+
+  g_array_zero_terminate (array);
 
   return farray;
 }
@@ -325,15 +333,18 @@ g_nearest_pow (gint num)
 }
 
 static void
-g_array_maybe_expand (GRealArray *array,
-		      gint        len)
+g_array_expand_prepare (GRealArray *array,
+		        gint        len)
 {
-  guint want_alloc = g_array_elt_len (array, array->len + len + 
-				      array->zero_terminated);
+  guint curr_len = g_array_elt_len (array, array->len +
+				    array->zero_terminated);
+  guint want_len = g_array_elt_len (array, array->len + len + 
+				    array->zero_terminated);
 
-  if (want_alloc > array->alloc)
+  if (want_len > array->alloc)
     {
-      want_alloc = g_nearest_pow (want_alloc);
+      guint want_alloc = g_nearest_pow (want_len);
+
       want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
 
       array->data = g_realloc (array->data, want_alloc);
@@ -341,8 +352,42 @@ g_array_maybe_expand (GRealArray *array,
       if (G_UNLIKELY (g_mem_gc_friendly))
         memset (array->data + array->alloc, 0, want_alloc - array->alloc);
 
+      VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
+
+      array->alloc = want_alloc;
+    }
+
+  VALGRIND_MAKE_WRITABLE(array->data + curr_len, want_len - curr_len);
+}
+
+static void
+g_array_shrink (GRealArray *array,
+		      gint        len)
+{
+  guint curr_len = g_array_elt_len (array, array->len +
+				    array->zero_terminated);
+  guint want_len = g_array_elt_len (array, array->len - len + 
+				    array->zero_terminated);
+
+  if (G_UNLIKELY (g_mem_gc_friendly))
+    memset (array->data + want_len, 0, curr_len - want_len);
+
+  VALGRIND_MAKE_NOACCESS(array->data + want_len, curr_len - want_len);
+
+  if (want_len <= array->alloc >> 2)
+    {
+      guint want_alloc = array->alloc >> 1;
+
+      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
+
+      array->data = g_realloc (array->data, want_alloc);
+
+      VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
+
       array->alloc = want_alloc;
     }
+
+  array->len -= len;
 }
 
 /* Pointer Array
