Index: configure.in
===================================================================
RCS file: /cvs/gnome/glib/configure.in,v
retrieving revision 1.508
diff -u -p -d -r1.508 configure.in
--- configure.in	15 May 2006 17:40:38 -0000	1.508
+++ configure.in	19 May 2006 04:00:59 -0000
@@ -2796,6 +2796,7 @@ build/win32/vs8/Makefile
 glib/Makefile
 glib/libcharset/Makefile
 glib/gnulib/Makefile
+glib/contrib/Makefile
 gmodule/Makefile
 gmodule/gmoduleconf.h
 gobject/Makefile
Index: docs/reference/glib/Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/Makefile.am,v
retrieving revision 1.49
diff -u -p -d -r1.49 Makefile.am
--- docs/reference/glib/Makefile.am	19 Dec 2005 21:22:29 -0000	1.49
+++ docs/reference/glib/Makefile.am	19 May 2006 04:00:59 -0000
@@ -20,6 +20,7 @@ CFILE_GLOB=$(top_srcdir)/glib/*.c $(top_
 # Headers to ignore
 IGNORE_HFILES=			\
 	build			\
+	contrib			\
 	gobject 		\
 	config.h 		\
 	gdatasetprivate.h	\
Index: docs/reference/glib/glib-sections.txt
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/glib-sections.txt,v
retrieving revision 1.147
diff -u -p -d -r1.147 glib-sections.txt
--- docs/reference/glib/glib-sections.txt	16 May 2006 05:49:46 -0000	1.147
+++ docs/reference/glib/glib-sections.txt	19 May 2006 04:00:59 -0000
@@ -789,7 +789,6 @@ g_try_realloc
 
 <SUBSECTION>
 g_free
-g_mem_gc_friendly
 
 <SUBSECTION>
 g_alloca
@@ -803,6 +802,10 @@ g_memdup
 GMemVTable
 g_mem_set_vtable
 g_mem_is_system_malloc
+
+<SUBSECTION>
+g_mem_gc_friendly
+g_mem_checker_running
 
 <SUBSECTION>
 glib_mem_profiler_table
Index: docs/reference/glib/running.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/running.sgml,v
retrieving revision 1.12
diff -u -p -d -r1.12 running.sgml
--- docs/reference/glib/running.sgml	26 Jan 2006 19:28:32 -0000	1.12
+++ docs/reference/glib/running.sgml	19 May 2006 04:00:59 -0000
@@ -57,38 +57,62 @@ variables like <envar>LANG</envar>, <env
 <formalpara id="G_DEBUG">
   <title><envar>G_DEBUG</envar></title>
   <para>
-    If GLib has been configured with <option>--enable-debug=yes</option>,
-    this variable can be set to a list of debug options, which cause GLib
-    to print out different types of debugging information.
+    This variable can be set to a list of debug options.
     <variablelist>
       <varlistentry>
-        <term>fatal_warnings</term>
+        <term>fatal-warnings</term>
         <listitem><para>Causes GLib to abort the program at the first call
            to <link linkend="g-warning">g_warning</link>() or
-	   <link linkend="g-critical">g_critical</link>(). This option is 
-           special in that it doesn't require GLib to be configured with 
-           debugging support.</para>
+	   <link linkend="g-critical">g_critical</link>(). </para>
         </listitem>
       </varlistentry>
       <varlistentry>
-        <term>fatal_criticals</term>
+        <term>fatal-criticals</term>
         <listitem><para>Causes GLib to abort the program at the first call
-           to <link linkend="g-critical">g_critical</link>(). This option is 
-           special in that it doesn't require GLib to be configured with 
-           debugging support.</para>
+           to <link linkend="g-critical">g_critical</link>().</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term>gc-friendly</term>
 	<listitem>
-		<para>
-		  Newly allocated memory that isn't directly initialized, as well
-		  as memory being freed will be reset to 0. The point here is to
-		  allow memory checkers and similar programs that use bohem GC alike
-		  algorithms to produce more accurate results.
-		  This option is special in that it doesn't require GLib to be
-		  configured with debugging support.
-		</para>
+	  <para>
+	    Newly allocated memory that isn't directly initialized, as well
+	    as memory being freed will be reset to 0. The point here is to
+	    allow memory checkers and similar programs that use bohem GC alike
+	    algorithms to produce more accurate results.
+	  </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>no-gc-friendly</term>
+	<listitem>
+	  <para>
+	    If <literal>gc-friendly</literal> has been enabled at compile time, this
+	    can be used to turn it off.
+	  </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>checker-running</term>
+	<listitem>
+	  <para>
+	    Makes GLib think it is running on top a memory debugger.  See
+	    <link linkend="g_mem_checker_running">g_mem_checker_running</link>
+	    for more details.  This is not normally useful
+	    as GLib detects certain memory checker automatically.
+	  </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>no-checker-running</term>
+	<listitem>
+	  <para>
+	    Hints GLib to not enabled extra measures for memory debuggers,
+	    even if one is detected.
+	    See
+	    <link linkend="g_mem_checker_running">g_mem_checker_running</link>
+	    for more details.
+	  </para>
         </listitem>
       </varlistentry>
     </variablelist>
@@ -98,21 +122,23 @@ variables like <envar>LANG</envar>, <env
 <formalpara id="G_SLICE">
 	<title><envar>G_SLICE</envar></title>
 	<para>
-	  This environment variable allows reconfiguration of the #GSlice
-	  memory allocator.
+	  This environment variable allows reconfiguration of the <link
+	  linkend="GSlice">GSlice</link> memory allocator.
 	  <variablelist>
 	    <varlistentry>
 	      <term>always-malloc</term>
 	      <listitem>
 		<para>
-		  This will cause all slices allocated through g_slice_alloc() and
-		  released by g_slice_free1() to be actually allocated via direct
-		  calls to g_malloc() and g_free().
+		  This will cause all slices allocated through 
+		  <link linkend="g_slice_alloc">g_slice_alloc</link>() and released by
+		  <link linkend="g_slice_free1">g_slice_free1</link>()
+		  to be actually allocated via direct calls to g_malloc() and g_free().
 		  This is most useful for memory checkers and similar programs that
 		  use bohem GC alike algorithms to produce more accurate results.
-		  It can also be in conjunction with debugging features of the system's
+		  It can also be used in conjunction with debugging features of the system's
 		  malloc implementation such as glibc's MALLOC_CHECK_=2 to debug
-		  erroneous slice allocation code.
+		  erroneous slice allocation code, although GLib has support
+		  for valgrind hints, so this is not necessary for valgrind.
 		</para>
 	      </listitem>
 	    </varlistentry>
Index: docs/reference/glib/tmpl/glib-unused.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/glib-unused.sgml,v
retrieving revision 1.39
diff -u -p -d -r1.39 glib-unused.sgml
--- docs/reference/glib/tmpl/glib-unused.sgml	5 May 2005 14:57:27 -0000	1.39
+++ docs/reference/glib/tmpl/glib-unused.sgml	19 May 2006 04:00:59 -0000
@@ -203,6 +203,15 @@ error domains.
 </para>
 
 
+<!-- ##### MACRO G_HAVE_GNUC_VISIBILITY ##### -->
+<para>
+This macro is defined as 1 if the the compiler supports ELF visibility 
+attributes (currently only <command>gcc</command>).
+</para>
+
+Since: 2.6
+
+
 <!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
 <para>
 
Index: docs/reference/glib/tmpl/macros_misc.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/macros_misc.sgml,v
retrieving revision 1.57
diff -u -p -d -r1.57 macros_misc.sgml
--- docs/reference/glib/tmpl/macros_misc.sgml	9 Dec 2005 18:05:21 -0000	1.57
+++ docs/reference/glib/tmpl/macros_misc.sgml	19 May 2006 04:00:59 -0000
@@ -297,16 +297,6 @@ See the GNU C documentation for details.
 
 
 
-<!-- ##### MACRO G_HAVE_GNUC_VISIBILITY ##### -->
-<para>
-This macro is defined as 1 if the the compiler supports ELF visibility 
-attributes (currently only <command>gcc</command>).
-</para>
-
-Since: 2.6
-
-
-
 <!-- ##### MACRO G_GNUC_INTERNAL ##### -->
 <para>
 Expands to the GNU C <literal>visibility(hidden)</literal> attribute if the 
Index: docs/reference/glib/tmpl/memory.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/memory.sgml,v
retrieving revision 1.24
diff -u -p -d -r1.24 memory.sgml
--- docs/reference/glib/tmpl/memory.sgml	11 Feb 2006 14:05:56 -0000	1.24
+++ docs/reference/glib/tmpl/memory.sgml	19 May 2006 04:00:59 -0000
@@ -189,13 +189,6 @@ If @mem is %NULL it simply returns.
 @mem: the memory to free.
 
 
-<!-- ##### VARIABLE g_mem_gc_friendly ##### -->
-<para>
-This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
-includes the key <link linkend="G_DEBUG">gc-friendly</link>.  
-</para>
-
-
 <!-- ##### MACRO g_alloca ##### -->
 <para>
 Allocates @size bytes on the stack; these bytes will be freed when the current
@@ -301,6 +294,29 @@ function has been called.
 </para>
 
 @Returns: 
+
+
+<!-- ##### VARIABLE g_mem_gc_friendly ##### -->
+<para>
+This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
+includes the key <link linkend="G_DEBUG">gc-friendly</link>.  This makes
+the memory management facilities internal to GLib to take extra steps
+clearing memory that is being freed, in the hope to not confuse garbage
+collectors that scan memory for pointers.
+</para>
+
+
+<!-- ##### VARIABLE g_mem_checker_running ##### -->
+<para>
+This variable is %TRUE if the <envar>G_DEBUG</envar> environment variable
+includes the key <link linkend="G_DEBUG">checker-running</link>, or if the
+application is running on top of a memory debugger.  The only supported
+memory debugger is 
+<ulink url="http://valgrind.org/">valgrind</ulink> so far.
+This makes the memory management facilities internal to GLib to take extra
+steps sending hints to the memory debugger about their allocations, such that
+the debugger can find and report more memory access problems or leaks.
+</para>
 
 
 <!-- ##### VARIABLE glib_mem_profiler_table ##### -->
Index: docs/reference/glib/tmpl/memory_slices.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/memory_slices.sgml,v
retrieving revision 1.8
diff -u -p -d -r1.8 memory_slices.sgml
--- docs/reference/glib/tmpl/memory_slices.sgml	30 Mar 2006 19:58:01 -0000	1.8
+++ docs/reference/glib/tmpl/memory_slices.sgml	19 May 2006 04:00:59 -0000
@@ -5,7 +5,7 @@ Memory Slices
 efficient way to allocate groups of equal-sized chunks of memory.
 
 <!-- ##### SECTION Long_Description ##### -->
-<para>
+<para id="GSlice">
 Memory slices provide a space-efficient and multi-processing scalable
 way to allocate equal-sized pieces of memory, just like the original
 #GMemChunks (from GLib &lt;= 2.8), while avoiding their excessive
Index: docs/reference/glib/tmpl/string_utils.sgml
===================================================================
RCS file: /cvs/gnome/glib/docs/reference/glib/tmpl/string_utils.sgml,v
retrieving revision 1.42
diff -u -p -d -r1.42 string_utils.sgml
--- docs/reference/glib/tmpl/string_utils.sgml	3 May 2006 02:04:54 -0000	1.42
+++ docs/reference/glib/tmpl/string_utils.sgml	19 May 2006 04:01:00 -0000
@@ -644,6 +644,17 @@ For that purpose, use g_utf8_strreverse(
 @Returns: the same pointer passed in as @string.
 
 
+<!-- ##### FUNCTION g_ascii_strtoll ##### -->
+<para>
+
+</para>
+
+@nptr: 
+@endptr: 
+@base: 
+@Returns: 
+
+
 <!-- ##### FUNCTION g_ascii_strtoull ##### -->
 <para>
 
Index: glib/Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/glib/Makefile.am,v
retrieving revision 1.142
diff -u -p -d -r1.142 Makefile.am
--- glib/Makefile.am	10 May 2006 00:44:49 -0000	1.142
+++ glib/Makefile.am	19 May 2006 04:01:00 -0000
@@ -6,9 +6,9 @@ PRINTF_SUBDIR = gnulib
 printf_la = gnulib/libgnulib.la
 endif 
 
-SUBDIRS = libcharset $(PRINTF_SUBDIR)
+SUBDIRS = libcharset $(PRINTF_SUBDIR) contrib
 
-DIST_SUBDIRS = libcharset gnulib
+DIST_SUBDIRS = libcharset gnulib contrib
 
 INCLUDES = -I$(top_srcdir) -DG_LOG_DOMAIN=\"GLib\" \
 	$(GLIB_DEBUG_FLAGS) -DG_DISABLE_DEPRECATED -DGLIB_COMPILATION 
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	19 May 2006 04:01:00 -0000
@@ -42,6 +42,7 @@
 
 #include "galias.h"
 
+#include "contrib/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,20 @@ 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);
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
+
       g_array_zero_terminate(array);
     }
 
@@ -129,7 +146,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 +165,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 +187,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 +209,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 +239,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 +261,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 +284,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,24 +334,64 @@ 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 curr_alloc = array->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);
+      array->alloc = want_alloc;
 
       if (G_UNLIKELY (g_mem_gc_friendly))
-        memset (array->data + array->alloc, 0, want_alloc - array->alloc);
+        memset (array->data + curr_alloc, 0, want_alloc - curr_alloc);
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
+    }
+
+  if (G_UNLIKELY (g_mem_checker_running))
+    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);
+
+  if (G_UNLIKELY (g_mem_checker_running))
+    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);
       array->alloc = want_alloc;
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->data + want_len, want_alloc - want_len);
     }
+
+  array->len -= len;
 }
 
 /* Pointer Array
@@ -357,8 +406,10 @@ struct _GRealPtrArray
   guint     alloc;
 };
 
-static void g_ptr_array_maybe_expand (GRealPtrArray *array,
-				      gint           len);
+static void g_ptr_array_expand_prepare (GRealPtrArray *array,
+					gint           len);
+static void g_ptr_array_shrink (GRealPtrArray *array,
+				gint           len);
 
 GPtrArray*
 g_ptr_array_new (void)
@@ -376,7 +427,21 @@ g_ptr_array_sized_new (guint reserved_si
   array->alloc = 0;
 
   if (reserved_size != 0)
-    g_ptr_array_maybe_expand (array, reserved_size);
+    {
+      guint want_alloc;
+
+      want_alloc = g_nearest_pow (reserved_size);
+      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE / sizeof (gpointer));
+
+      array->pdata = g_malloc (want_alloc * sizeof (gpointer));
+      array->alloc = want_alloc;
+
+      if (G_UNLIKELY (g_mem_gc_friendly))
+        memset (array->pdata, 0, want_alloc * sizeof (gpointer));
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->pdata, want_alloc * sizeof (gpointer));
+    }
 
   return (GPtrArray*) array;  
 }
@@ -403,19 +468,60 @@ g_ptr_array_free (GPtrArray   *array,
 }
 
 static void
-g_ptr_array_maybe_expand (GRealPtrArray *array,
-			  gint        len)
+g_ptr_array_expand_prepare (GRealPtrArray *array,
+			    gint           len)
 {
-  if ((array->len + len) > array->alloc)
+  guint curr_len = array->len;
+  guint want_len = array->len + len;
+
+  if (want_len > array->alloc)
     {
-      guint old_alloc = array->alloc;
-      array->alloc = g_nearest_pow (array->len + len);
-      array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
-      array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc);
+      guint curr_alloc = array->alloc;
+      guint want_alloc;
+      
+      want_alloc = g_nearest_pow (want_len);
+      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE / sizeof (gpointer));
+
+      array->pdata = g_realloc (array->pdata, want_alloc * sizeof (gpointer));
+      array->alloc = want_alloc;
+
       if (G_UNLIKELY (g_mem_gc_friendly))
-        for ( ; old_alloc < array->alloc; old_alloc++)
-          array->pdata [old_alloc] = NULL;
+        memset (array->pdata + curr_alloc, 0, (want_alloc - curr_alloc) * sizeof (gpointer));
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->pdata + want_len, (want_alloc - want_len) * sizeof (gpointer));
+    }
+  if (G_UNLIKELY (g_mem_checker_running))
+    VALGRIND_MAKE_WRITABLE(array->pdata + curr_len, (want_len - curr_len) * sizeof (gpointer));
+}
+
+static void
+g_ptr_array_shrink (GRealPtrArray *array,
+		    gint           len)
+{
+  guint curr_len = array->len;
+  guint want_len = array->len - len;
+
+  if (G_UNLIKELY (g_mem_gc_friendly))
+    memset (array->pdata + want_len, 0, (curr_len - want_len) * sizeof (gpointer));
+
+  if (G_UNLIKELY (g_mem_checker_running))
+    VALGRIND_MAKE_NOACCESS(array->pdata + want_len, (curr_len - want_len) * sizeof (gpointer));
+
+  if (want_len <= array->alloc >> 2)
+    {
+      guint want_alloc = array->alloc >> 1;
+
+      want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE / sizeof (gpointer));
+
+      array->pdata = g_realloc (array->pdata, want_alloc * sizeof (gpointer));
+      array->alloc = want_alloc;
+
+      if (G_UNLIKELY (g_mem_checker_running))
+	VALGRIND_MAKE_NOACCESS(array->pdata + want_len, (want_alloc - want_len) * sizeof (gpointer));
     }
+
+  array->len -= len;
 }
 
 void
@@ -428,23 +534,11 @@ g_ptr_array_set_size  (GPtrArray   *farr
 
   if (length > array->len)
     {
-      int i;
-      g_ptr_array_maybe_expand (array, (length - array->len));
-      /* This is not 
-       *     memset (array->pdata + array->len, 0,
-       *            sizeof (gpointer) * (length - array->len));
-       * to make it really portable. Remember (void*)NULL needn't be
-       * bitwise zero. It of course is silly not to use memset (..,0,..).
-       */
-      for (i = array->len; i < length; i++)
-	array->pdata[i] = NULL;
-    }
-  if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
-    {
-      int i;
-      for (i = length; i < array->len; i++)
-	array->pdata[i] = NULL;
+      g_ptr_array_expand_prepare (array, (length - array->len));
+      memset (array->pdata + array->len, 0, (length - array->len) * sizeof (gpointer));
     }
+  else if (length < array->len)
+    g_ptr_array_shrink (array, (array->len - length));
 
   array->len = length;
 }
@@ -466,10 +560,7 @@ g_ptr_array_remove_index (GPtrArray* far
     g_memmove (array->pdata + index, array->pdata + index + 1, 
 	       sizeof (gpointer) * (array->len - index - 1));
   
-  array->len -= 1;
-
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    array->pdata[array->len] = NULL;
+  g_ptr_array_shrink (array, 1);
 
   return result;
 }
@@ -490,10 +581,7 @@ g_ptr_array_remove_index_fast (GPtrArray
   if (index != array->len - 1)
     array->pdata[index] = array->pdata[array->len - 1];
 
-  array->len -= 1;
-
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    array->pdata[array->len] = NULL;
+  g_ptr_array_shrink (array, 1);
 
   return result;
 }
@@ -514,13 +602,7 @@ g_ptr_array_remove_range (GPtrArray* far
                &array->pdata[index_ + length], 
                (array->len - (index_ + length)) * sizeof (gpointer));
 
-  array->len -= length;
-  if (G_UNLIKELY (g_mem_gc_friendly))
-    {
-      guint i;
-      for (i = 0; i < length; i++)
-        array->pdata[array->len + i] = NULL;
-    }
+  g_ptr_array_shrink (array, length);
 }
 
 gboolean
@@ -573,7 +655,7 @@ g_ptr_array_add (GPtrArray* farray,
 
   g_return_if_fail (array);
 
-  g_ptr_array_maybe_expand (array, 1);
+  g_ptr_array_expand_prepare (array, 1);
 
   array->pdata[array->len++] = data;
 }
Index: glib/gmem.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gmem.c,v
retrieving revision 1.57
diff -u -p -d -r1.57 gmem.c
--- glib/gmem.c	10 May 2006 00:44:49 -0000	1.57
+++ glib/gmem.c	19 May 2006 04:01:00 -0000
@@ -38,6 +38,8 @@
 #include "gthreadprivate.h"
 #include "galias.h"
 
+#include "contrib/valgrind.h"
+
 #define MEM_PROFILE_TABLE_SIZE 4096
 
 
@@ -684,24 +686,53 @@ gboolean g_mem_gc_friendly = TRUE;
 gboolean g_mem_gc_friendly = FALSE;
 #endif
 
+gboolean g_mem_checker_running = FALSE;
+
 static void
 g_mem_init_nomessage (void)
 {
   gchar buffer[1024];
   const gchar *val;
+  enum {
+    gc_friendly        = 0x01,
+    no_gc_friendly     = 0x02,
+    checker_running    = 0x04,
+    no_checker_running = 0x08
+  };
   static const GDebugKey keys[] = {
-    { "gc-friendly", 1 },
+    { "gc-friendly",        gc_friendly },
+    { "no-gc-friendly",     no_gc_friendly },
+    { "checker-running",    checker_running },
+    { "no-checker-running", no_checker_running }
   };
   gint flags;
   if (g_mem_initialized)
     return;
+
+  /* Add checks for other memory checkers here */
+  if (G_UNLIKELY (RUNNING_ON_VALGRIND))
+    g_mem_checker_running = TRUE;
+
   /* don't use g_malloc/g_message here */
   val = _g_getenv_nomalloc ("G_DEBUG", buffer);
   flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
-  if (flags & 1)        /* gc-friendly */
+
+  if (G_UNLIKELY (flags))
     {
-      g_mem_gc_friendly = TRUE;
+      if (flags & no_gc_friendly)
+	g_mem_gc_friendly = FALSE;
+      else if (flags & gc_friendly)
+	g_mem_gc_friendly = TRUE;
+
+      if (flags & no_checker_running)
+	g_mem_checker_running = FALSE;
+      else if (flags & checker_running)
+	g_mem_checker_running = TRUE;
     }
+
+  if (G_UNLIKELY (g_mem_checker_running))
+    VALGRIND_PRINTF ("GLib valgrind hints enabled");
+
   g_mem_initialized = TRUE;
 }
 
Index: glib/gmem.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gmem.h,v
retrieving revision 1.18
diff -u -p -d -r1.18 gmem.h
--- glib/gmem.h	25 Jan 2006 15:51:43 -0000	1.18
+++ glib/gmem.h	19 May 2006 04:01:00 -0000
@@ -93,6 +93,7 @@ void	 g_mem_set_vtable (GMemVTable	*vtab
 gboolean g_mem_is_system_malloc (void);
 
 GLIB_VAR gboolean g_mem_gc_friendly;
+GLIB_VAR gboolean g_mem_checker_running;
 
 /* Memory profiler and checker, has to be enabled via g_mem_set_vtable()
  */
Index: glib/gslice.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gslice.c,v
retrieving revision 1.19
diff -u -p -d -r1.19 gslice.c
--- glib/gslice.c	10 May 2006 00:44:49 -0000	1.19
+++ glib/gslice.c	19 May 2006 04:01:00 -0000
@@ -42,6 +42,9 @@
 #include <process.h>
 #endif
 
+#include "contrib/valgrind.h"
+#include "contrib/memcheck.h"
+
 
 /* the GSlice allocator is split up into 4 layers, roughly modelled after the slab
  * allocator and magazine extensions as outlined in:
@@ -126,6 +129,57 @@
 static void mem_error (const char *format, ...) G_GNUC_PRINTF (1,2);
 #define mem_assert(cond)    do { if (G_LIKELY (cond)) ; else mem_error ("assertion failed: %s", #cond); } while (0)
 
+/* helpers for valgrind hints */
+#define _G_SLICE_IF_CHECKER(_cond, _code)	\
+	G_STMT_START { if (G_UNLIKELY (g_mem_checker_running && (_cond))) { _code } } G_STMT_END
+
+/* quick wrappers */
+#define _G_SLICE_VALGRIND_MAKE_NOACCESS(_mem, _mem_size) _G_SLICE_IF_CHECKER (_mem, \
+		 VALGRIND_MAKE_NOACCESS(_mem, _mem_size);)
+#define _G_SLICE_VALGRIND_MAKE_WRITABLE(_mem, _mem_size) _G_SLICE_IF_CHECKER (_mem, \
+		 VALGRIND_MAKE_WRITABLE(_mem, _mem_size);)
+#define _G_SLICE_VALGRIND_MAKE_READABLE(_mem, _mem_size) _G_SLICE_IF_CHECKER (_mem, \
+		 VALGRIND_MAKE_READABLE(_mem, _mem_size);)
+
+/* ChunkLink handling */
+#define MAKE_CHUNK_LINK_NOACCESS(_mem) _G_SLICE_VALGRIND_MAKE_NOACCESS (_mem, sizeof (ChunkLink))
+#define MAKE_CHUNK_LINK_WRITABLE(_mem) _G_SLICE_VALGRIND_MAKE_WRITABLE (_mem, sizeof (ChunkLink))
+#define MAKE_CHUNK_LINK_READABLE(_mem) _G_SLICE_VALGRIND_MAKE_READABLE (_mem, sizeof (ChunkLink))
+
+/* SlabInfo handling */
+#define MAKE_SLAB_INFO_NOACCESS(_mem) _G_SLICE_VALGRIND_MAKE_NOACCESS (_mem, sizeof (SlabInfo))
+#define MAKE_SLAB_INFO_WRITABLE(_mem) _G_SLICE_VALGRIND_MAKE_WRITABLE (_mem, sizeof (SlabInfo))
+#define MAKE_SLAB_INFO_READABLE(_mem) _G_SLICE_VALGRIND_MAKE_READABLE (_mem, sizeof (SlabInfo))
+
+/* malloc/free-like operations*/
+/* valgrind only supports redzones before memory allocations, so we cannot
+ * mark the leftover at the end of chunks as redzone easily.  if we don't mark
+ * it as redzone, it still catches errors, as we make the entire block
+ * unaccessible.  but having redzones allocated here has the beauty that the
+ * errors will have the backtrace for this slice allocation.
+ *
+ * what we do is that we make an allocation without redzone followed (in
+ * address space) by another one that consists of only redzone area (possibly
+ * leaving a single byte at the end unused.)
+ */
+
+#define _G_SLICE_VALGRIND_MALLOCLIKE_BLOCK(_mem, _mem_size, _chunk_size, _zeroed) _G_SLICE_IF_CHECKER (_mem, \
+	  VALGRIND_MALLOCLIKE_BLOCK(_mem, _mem_size, 0, _zeroed); \
+	  if ((_mem_size) + 2 <= (_chunk_size)) \
+	    VALGRIND_MALLOCLIKE_BLOCK( \
+		  (guint8*)(_mem) + (_mem_size) + (((_chunk_size) - (_mem_size)) >> 1), \
+		  0 /* allocation size */, \
+		  (((_chunk_size) - (_mem_size)) >> 1), \
+		  0 /* zeroed */); \
+	)
+#define _G_SLICE_VALGRIND_FREELIKE_BLOCK(_mem, _mem_size, _chunk_size) _G_SLICE_IF_CHECKER (_mem, \
+	  VALGRIND_FREELIKE_BLOCK(_mem, 0); \
+	  if ((_mem_size) + 1 < (_chunk_size)) \
+	    VALGRIND_FREELIKE_BLOCK( \
+		  (guint8*)(_mem) + (_mem_size) + (((_chunk_size) - (_mem_size)) >> 1), \
+		  (((_chunk_size) - (_mem_size)) >> 1)); \
+	)
+
 /* --- structures --- */
 typedef struct _ChunkLink      ChunkLink;
 typedef struct _SlabInfo       SlabInfo;
@@ -420,17 +474,23 @@ magazine_chain_pop_head (ChunkLink **mag
    * linked via ChunkLink->next. ChunkLink->data of the subchains just
    * contains uninitialized junk.
    */
-  ChunkLink *chunk = (*magazine_chunks)->data;
+  ChunkLink *chunk;
+  
+  MAKE_CHUNK_LINK_READABLE (*magazine_chunks);
+  chunk = (*magazine_chunks)->data;
   if (G_UNLIKELY (chunk))
     {
       /* allocating from freed list */
+      MAKE_CHUNK_LINK_READABLE (chunk);
       (*magazine_chunks)->data = chunk->next;
+      MAKE_CHUNK_LINK_NOACCESS (*magazine_chunks);
     }
   else
     {
       chunk = *magazine_chunks;
       *magazine_chunks = chunk->next;
     }
+  /* returns chunk with readable chunk link */
   return chunk;
 }
 
@@ -529,7 +589,7 @@ magazine_cache_trim (Allocator *allocato
   /* trim magazine cache from tail */
   ChunkLink *current = magazine_chain_prev (allocator->magazines[ix]);
   ChunkLink *trash = NULL;
-  while (ABS (stamp - magazine_chain_uint_stamp (current)) >= allocator->config.working_set_msecs)
+  while (ABS ((gint)stamp - (gint)magazine_chain_uint_stamp (current)) >= allocator->config.working_set_msecs)
     {
       /* unlink */
       ChunkLink *prev = magazine_chain_prev (current);
@@ -612,15 +672,18 @@ magazine_cache_pop_magazine (guint  ix,
       g_mutex_unlock (allocator->magazine_mutex);
       g_mutex_lock (allocator->slab_mutex);
       head = slab_allocator_alloc_chunk (chunk_size);
-      head->data = NULL;
       chunk = head;
       for (i = 1; i < magazine_threshold; i++)
         {
-          chunk->next = slab_allocator_alloc_chunk (chunk_size);
-          chunk = chunk->next;
-          chunk->data = NULL;
+	  ChunkLink *next = slab_allocator_alloc_chunk (chunk_size);
+	  chunk->data = NULL;
+          chunk->next = next;
+	  MAKE_CHUNK_LINK_NOACCESS (chunk);
+          chunk = next;
         }
+      chunk->data = NULL;
       chunk->next = NULL;
+      MAKE_CHUNK_LINK_NOACCESS (chunk);
       g_mutex_unlock (allocator->slab_mutex);
       *countp = i;
       return head;
@@ -740,8 +803,10 @@ thread_memory_magazine2_free (ThreadMemo
 {
   Magazine *mag = &tmem->magazine2[ix];
   ChunkLink *chunk = mem;
+  MAKE_CHUNK_LINK_WRITABLE (chunk);
   chunk->data = NULL;
   chunk->next = mag->chunks;
+  MAKE_CHUNK_LINK_NOACCESS (chunk);
   mag->chunks = chunk;
   mag->count++;
 }
@@ -766,12 +831,14 @@ g_slice_alloc (gsize mem_size)
             thread_memory_magazine1_reload (tmem, ix);
         }
       mem = thread_memory_magazine1_alloc (tmem, ix);
+      _G_SLICE_VALGRIND_MALLOCLIKE_BLOCK (mem, mem_size, chunk_size, FALSE);
     }
   else if (acat == 2)           /* allocate through slab allocator */
     {
       g_mutex_lock (allocator->slab_mutex);
       mem = slab_allocator_alloc_chunk (chunk_size);
       g_mutex_unlock (allocator->slab_mutex);
+      _G_SLICE_VALGRIND_MALLOCLIKE_BLOCK (mem, mem_size, chunk_size, FALSE);
     }
   else                          /* delegate to system malloc */
     mem = g_malloc (mem_size);
@@ -782,7 +849,7 @@ gpointer
 g_slice_alloc0 (gsize mem_size)
 {
   gpointer mem = g_slice_alloc (mem_size);
-  if (mem)
+  if (G_LIKELY (mem))
     memset (mem, 0, mem_size);
   return mem;
 }
@@ -808,6 +875,7 @@ g_slice_free1 (gsize    mem_size,
       if (G_UNLIKELY (g_mem_gc_friendly))
         memset (mem_block, 0, chunk_size);
       thread_memory_magazine2_free (tmem, ix, mem_block);
+      _G_SLICE_VALGRIND_FREELIKE_BLOCK (mem_block, mem_size, chunk_size);
     }
   else if (acat == 2)                   /* allocate through slab allocator */
     {
@@ -816,6 +884,7 @@ g_slice_free1 (gsize    mem_size,
       g_mutex_lock (allocator->slab_mutex);
       slab_allocator_free_chunk (chunk_size, mem_block);
       g_mutex_unlock (allocator->slab_mutex);
+      _G_SLICE_VALGRIND_FREELIKE_BLOCK (mem_block, mem_size, chunk_size);
     }
   else                                  /* delegate to system malloc */
     {
@@ -865,6 +934,7 @@ g_slice_free_chain_with_offset (gsize   
           if (G_UNLIKELY (g_mem_gc_friendly))
             memset (current, 0, chunk_size);
           thread_memory_magazine2_free (tmem, ix, current);
+	  _G_SLICE_VALGRIND_FREELIKE_BLOCK (current, mem_size, chunk_size);
         }
     }
   else if (acat == 2)                   /* allocate through slab allocator */
@@ -877,6 +947,7 @@ g_slice_free_chain_with_offset (gsize   
           if (G_UNLIKELY (g_mem_gc_friendly))
             memset (current, 0, chunk_size);
           slab_allocator_free_chunk (chunk_size, current);
+	  _G_SLICE_VALGRIND_FREELIKE_BLOCK (current, mem_size, chunk_size);
         }
       g_mutex_unlock (allocator->slab_mutex);
     }
@@ -950,19 +1021,19 @@ allocator_add_slab (Allocator *allocator
   /* assert alignment */
   mem_assert (aligned_memory == (gpointer) addr);
   /* basic slab info setup */
-  sinfo = (SlabInfo*) (mem + page_size - SLAB_INFO_SIZE);
+  sinfo = (SlabInfo*) (mem);
   sinfo->n_allocated = 0;
   sinfo->chunks = NULL;
   /* figure cache colorization */
-  n_chunks = ((guint8*) sinfo - mem) / chunk_size;
-  padding = ((guint8*) sinfo - mem) - n_chunks * chunk_size;
+  n_chunks = (page_size - SLAB_INFO_SIZE) / chunk_size;
+  padding = (page_size - SLAB_INFO_SIZE) - n_chunks * chunk_size;
   if (padding)
     {
       color = (allocator->color_accu * P2ALIGNMENT) % padding;
       allocator->color_accu += allocator->config.color_increment;
     }
   /* add chunks to free list */
-  chunk = (ChunkLink*) (mem + color);
+  chunk = (ChunkLink*) (mem + P2ALIGN (sizeof (SlabInfo)) + color);
   sinfo->chunks = chunk;
   for (i = 0; i < n_chunks - 1; i++)
     {
@@ -972,6 +1043,8 @@ allocator_add_slab (Allocator *allocator
   chunk->next = NULL;   /* last chunk */
   /* add slab to slab ring */
   allocator_slab_stack_push (allocator, ix, sinfo);
+  _G_SLICE_VALGRIND_MAKE_NOACCESS(aligned_memory, page_size);
+  MAKE_SLAB_INFO_READABLE (sinfo);
 }
 
 static gpointer
@@ -984,11 +1057,14 @@ slab_allocator_alloc_chunk (gsize chunk_
     allocator_add_slab (allocator, ix, chunk_size);
   /* allocate chunk */
   chunk = allocator->slab_stack[ix]->chunks;
+  MAKE_CHUNK_LINK_READABLE (chunk);
   allocator->slab_stack[ix]->chunks = chunk->next;
   allocator->slab_stack[ix]->n_allocated++;
   /* rotate empty slabs */
   if (!allocator->slab_stack[ix]->chunks)
     allocator->slab_stack[ix] = allocator->slab_stack[ix]->next;
+
+  /* returns chunk with a readable chunk link */
   return chunk;
 }
 
@@ -1003,13 +1079,15 @@ slab_allocator_free_chunk (gsize    chun
   gsize addr = ((gsize) mem / page_size) * page_size;
   /* mask page adress */
   guint8 *page = (guint8*) addr;
-  SlabInfo *sinfo = (SlabInfo*) (page + page_size - SLAB_INFO_SIZE);
+  SlabInfo *sinfo = (SlabInfo*) page;
   /* assert valid chunk count */
   mem_assert (sinfo->n_allocated > 0);
   /* add chunk to free list */
   was_empty = sinfo->chunks == NULL;
   chunk = (ChunkLink*) mem;
+  MAKE_CHUNK_LINK_READABLE (chunk);
   chunk->next = sinfo->chunks;
+  MAKE_CHUNK_LINK_NOACCESS (chunk);
   sinfo->chunks = chunk;
   sinfo->n_allocated--;
   /* keep slab ring partially sorted, empty slabs at end */
@@ -1092,7 +1170,7 @@ allocator_memalign (gsize alignment,
     }
   aligned_memory = g_trash_stack_pop (&compat_valloc_trash);
 #endif
-  if (!aligned_memory)
+  if (G_UNLIKELY (!aligned_memory))
     errno = err;
   return aligned_memory;
 }
Index: glib/gutils.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gutils.c,v
retrieving revision 1.191
diff -u -p -d -r1.191 gutils.c
--- glib/gutils.c	10 May 2006 00:44:49 -0000	1.191
+++ glib/gutils.c	19 May 2006 04:01:00 -0000
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <locale.h>
 #include <string.h>
+#include <ctype.h>		/* For tolower() */
 #include <errno.h>
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -552,16 +553,33 @@ g_find_program_in_path (const gchar *pro
   return NULL;
 }
 
+static gboolean
+debug_key_matches (const gchar *key,
+		   const gchar *token,
+		   guint        length)
+{
+  for (; length; length--, key++, token++)
+    {
+      char k = (*key   == '_') ? '-' : tolower (*key  );
+      char t = (*token == '_') ? '-' : tolower (*token);
+
+      if (k != t)
+        return FALSE;
+    }
+
+  return *key == '\0';
+}
+
 /**
  * g_parse_debug_string:
- * @string: a list of debug options separated by ':' or "all" 
- *     to set all flags.
+ * @string: a list of debug options separated by colons, spaces, or
+ * commas; or the string "all" to set all flags.
  * @keys: pointer to an array of #GDebugKey which associate 
  *     strings with bit flags.
  * @nkeys: the number of #GDebugKey<!-- -->s in the array.
  *
- * Parses a string containing debugging options separated 
- * by ':' into a %guint containing bit flags. This is used 
+ * Parses a string containing debugging options
+ * into a %guint containing bit flags. This is used 
  * within GDK and GTK+ to parse the debug options passed on the
  * command line or through environment variables.
  *
@@ -594,17 +612,16 @@ g_parse_debug_string  (const gchar     *
       
       while (*p)
 	{
-	  q = strchr (p, ':');
+	  q = strpbrk (p, ":, ");
 	  if (!q)
 	    q = p + strlen(p);
 	  
 	  for (i = 0; i < nkeys; i++)
-	    if (g_ascii_strncasecmp (keys[i].key, p, q - p) == 0 &&
-		keys[i].key[q - p] == '\0')
+	    if (debug_key_matches (keys[i].key, p, q - p))
 	      result |= keys[i].value;
 	  
 	  p = q;
-	  if (*p == ':')
+	  if (*p)
 	    p++;
 	}
     }
Index: glib/contrib/.cvsignore
===================================================================
RCS file: glib/contrib/.cvsignore
diff -N glib/contrib/.cvsignore
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ glib/contrib/.cvsignore	19 May 2006 04:01:00 -0000
@@ -0,0 +1,2 @@
+Makefile.in
+Makefile
Index: glib/contrib/Makefile.am
===================================================================
RCS file: glib/contrib/Makefile.am
diff -N glib/contrib/Makefile.am
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ glib/contrib/Makefile.am	19 May 2006 04:01:00 -0000
@@ -0,0 +1 @@
+EXTRA_DIST = valgrind.h memcheck.h
Index: glib/contrib/memcheck.h
===================================================================
RCS file: glib/contrib/memcheck.h
diff -N glib/contrib/memcheck.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ glib/contrib/memcheck.h	19 May 2006 04:01:00 -0000
@@ -0,0 +1,255 @@
+
+/*
+   ----------------------------------------------------------------
+
+   Notice that the following BSD-style license applies to this one
+   file (memcheck.h) only.  The entire rest of Valgrind is licensed
+   under the terms of the GNU General Public License, version 2.  See
+   the COPYING file in the source distribution for details.
+
+   ----------------------------------------------------------------
+
+   This file is part of MemCheck, a heavyweight Valgrind tool for
+   detecting memory errors.
+
+   Copyright (C) 2000-2005 Julian Seward.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. The origin of this software must not be misrepresented; you must 
+      not claim that you wrote the original software.  If you use this 
+      software in a product, an acknowledgment in the product 
+      documentation would be appreciated but is not required.
+
+   3. Altered source versions must be plainly marked as such, and must
+      not be misrepresented as being the original software.
+
+   4. The name of the author may not be used to endorse or promote 
+      products derived from this software without specific prior written 
+      permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------
+
+   Notice that the above BSD-style license applies to this one file
+   (memcheck.h) only.  The entire rest of Valgrind is licensed under
+   the terms of the GNU General Public License, version 2.  See the
+   COPYING file in the source distribution for details.
+
+   ---------------------------------------------------------------- 
+*/
+
+
+#ifndef __MEMCHECK_H
+#define __MEMCHECK_H
+
+
+/* This file is for inclusion into client (your!) code.
+
+   You can use these macros to manipulate and query memory permissions
+   inside your own programs.
+
+   See comment near the top of valgrind.h on how to use them.
+*/
+
+#include "valgrind.h"
+
+typedef
+   enum { 
+      VG_USERREQ__MAKE_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'),
+      VG_USERREQ__MAKE_WRITABLE,
+      VG_USERREQ__MAKE_READABLE,
+      VG_USERREQ__DISCARD,
+      VG_USERREQ__CHECK_WRITABLE,
+      VG_USERREQ__CHECK_READABLE,
+      VG_USERREQ__DO_LEAK_CHECK,
+      VG_USERREQ__COUNT_LEAKS,
+
+      VG_USERREQ__GET_VBITS,
+      VG_USERREQ__SET_VBITS,
+
+      VG_USERREQ__CREATE_BLOCK,
+
+      /* This is just for memcheck's internal use - don't use it */
+      _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR 
+         = VG_USERREQ_TOOL_BASE('M','C') + 256
+   } Vg_MemCheckClientRequest;
+
+
+
+/* Client-code macros to manipulate the state of memory. */
+
+/* Mark memory at _qzz_addr as unaddressible and undefined for
+   _qzz_len bytes.   */
+#define VALGRIND_MAKE_NOACCESS(_qzz_addr,_qzz_len)               \
+   (__extension__({unsigned int _qzz_res;                        \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* default return */,    \
+                            VG_USERREQ__MAKE_NOACCESS,           \
+                            _qzz_addr, _qzz_len, 0, 0);          \
+    _qzz_res;                                                    \
+   }))
+      
+/* Similarly, mark memory at _qzz_addr as addressible but undefined
+   for _qzz_len bytes. */
+#define VALGRIND_MAKE_WRITABLE(_qzz_addr,_qzz_len)               \
+   (__extension__({unsigned int _qzz_res;                        \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* default return */,    \
+                            VG_USERREQ__MAKE_WRITABLE,           \
+                            _qzz_addr, _qzz_len, 0, 0);          \
+    _qzz_res;                                                    \
+   }))
+
+/* Similarly, mark memory at _qzz_addr as addressible and defined
+   for _qzz_len bytes. */
+#define VALGRIND_MAKE_READABLE(_qzz_addr,_qzz_len)               \
+   (__extension__({unsigned int _qzz_res;                        \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* default return */,    \
+                            VG_USERREQ__MAKE_READABLE,           \
+                            _qzz_addr, _qzz_len, 0, 0);          \
+    _qzz_res;                                                    \
+   }))
+
+/* Create a block-description handle.  The description is an ascii
+   string which is included in any messages pertaining to addresses
+   within the specified memory range.  Has no other effect on the
+   properties of the memory range. */
+#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc)	\
+	(__extension__({unsigned int _qzz_res;			\
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* default return */,	\
+                            VG_USERREQ__CREATE_BLOCK,           \
+                            _qzz_addr, _qzz_len, _qzz_desc, 0);	\
+    _qzz_res;							\
+   }))
+
+/* Discard a block-description-handle. Returns 1 for an
+   invalid handle, 0 for a valid handle. */
+#define VALGRIND_DISCARD(_qzz_blkindex)                          \
+   (__extension__ ({unsigned int _qzz_res;                       \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* default return */,    \
+                            VG_USERREQ__DISCARD,                 \
+                            0, _qzz_blkindex, 0, 0);             \
+    _qzz_res;                                                    \
+   }))
+
+
+/* Client-code macros to check the state of memory. */
+
+/* Check that memory at _qzz_addr is addressible for _qzz_len bytes.
+   If suitable addressibility is not established, Valgrind prints an
+   error message and returns the address of the first offending byte.
+   Otherwise it returns zero. */
+#define VALGRIND_CHECK_WRITABLE(_qzz_addr,_qzz_len)                \
+   (__extension__({unsigned int _qzz_res;                          \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__CHECK_WRITABLE,            \
+                            _qzz_addr, _qzz_len, 0, 0);            \
+    _qzz_res;                                                      \
+   }))
+
+/* Check that memory at _qzz_addr is addressible and defined for
+   _qzz_len bytes.  If suitable addressibility and definedness are not
+   established, Valgrind prints an error message and returns the
+   address of the first offending byte.  Otherwise it returns zero. */
+#define VALGRIND_CHECK_READABLE(_qzz_addr,_qzz_len)                \
+   (__extension__({unsigned int _qzz_res;                          \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__CHECK_READABLE,            \
+                            _qzz_addr, _qzz_len, 0, 0);            \
+    _qzz_res;                                                      \
+   }))
+
+/* Use this macro to force the definedness and addressibility of a
+   value to be checked.  If suitable addressibility and definedness
+   are not established, Valgrind prints an error message and returns
+   the address of the first offending byte.  Otherwise it returns
+   zero. */
+#define VALGRIND_CHECK_DEFINED(__lvalue)                           \
+   VALGRIND_CHECK_READABLE(                                        \
+      (volatile unsigned char *)&(__lvalue),                       \
+                      (unsigned int)(sizeof (__lvalue)))
+
+/* Do a memory leak check mid-execution.  */
+#define VALGRIND_DO_LEAK_CHECK                                     \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__DO_LEAK_CHECK,             \
+                            0, 0, 0, 0);                           \
+   }
+
+/* Just display summaries of leaked memory, rather than all the
+   details */
+#define VALGRIND_DO_QUICK_LEAK_CHECK				   \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__DO_LEAK_CHECK,             \
+                            1, 0, 0, 0);                           \
+   }
+
+/* Return number of leaked, dubious, reachable and suppressed bytes found by
+   all previous leak checks.  They must be lvalues. */
+#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed)    \
+   {unsigned int _qzz_res;                                              \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                                \
+                            VG_USERREQ__COUNT_LEAKS,                    \
+                            &leaked, &dubious, &reachable, &suppressed);\
+   }
+
+
+/* Get in zzvbits the validity data for the zznbytes starting at
+   zzsrc.  Return values:
+      0   if not running on valgrind
+      1   success
+      2   if zzsrc/zzvbits arrays are not aligned 0 % 4, or
+          zznbytes is not 0 % 4.
+      3   if any parts of zzsrc/zzvbits are not addressible.
+   The metadata is not copied in cases 0, 2 or 3 so it should be
+   impossible to segfault your system by using this call.
+*/
+#define VALGRIND_GET_VBITS(zzsrc,zzvbits,zznbytes)               \
+   (__extension__({unsigned int _qzz_res;                        \
+    char* czzsrc   = (char*)zzsrc;                               \
+    char* czzvbits = (char*)zzvbits;                             \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                         \
+                            VG_USERREQ__GET_VBITS,               \
+                            czzsrc, czzvbits, zznbytes,0 );      \
+    _qzz_res;                                                    \
+   }))
+
+/* Apply the validity data in zzvbits to the zznbytes starting at
+   zzdst.  Return values:
+      0   if not running on valgrind
+      1   success
+      2   if zzdst/zzvbits arrays are not aligned 0 % 4, or
+          zznbytes is not 0 % 4.
+      3   if any parts of zzdst/zzvbits are not addressible.
+   The metadata is not copied in cases 0, 2 or 3 so it should be
+   impossible to segfault your system by using this call.
+*/
+#define VALGRIND_SET_VBITS(zzdst,zzvbits,zznbytes)               \
+   (__extension__({unsigned int _qzz_res;                        \
+    char* czzdst   = (char*)zzdst;                               \
+    char* czzvbits = (char*)zzvbits;                             \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                         \
+                            VG_USERREQ__SET_VBITS,               \
+                            czzdst, czzvbits, zznbytes,0 );      \
+    _qzz_res;                                                    \
+   }))
+
+#endif
+
Index: glib/contrib/valgrind.h
===================================================================
RCS file: glib/contrib/valgrind.h
diff -N glib/contrib/valgrind.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ glib/contrib/valgrind.h	19 May 2006 04:01:00 -0000
@@ -0,0 +1,469 @@
+/* -*- c -*-
+   ----------------------------------------------------------------
+
+   Notice that the following BSD-style license applies to this one
+   file (valgrind.h) only.  The entire rest of Valgrind is licensed
+   under the terms of the GNU General Public License, version 2.  See
+   the COPYING file in the source distribution for details.
+
+   ----------------------------------------------------------------
+
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Julian Seward.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. The origin of this software must not be misrepresented; you must 
+      not claim that you wrote the original software.  If you use this 
+      software in a product, an acknowledgment in the product 
+      documentation would be appreciated but is not required.
+
+   3. Altered source versions must be plainly marked as such, and must
+      not be misrepresented as being the original software.
+
+   4. The name of the author may not be used to endorse or promote 
+      products derived from this software without specific prior written 
+      permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------
+
+   Notice that the above BSD-style license applies to this one file
+   (valgrind.h) only.  The entire rest of Valgrind is licensed under
+   the terms of the GNU General Public License, version 2.  See the
+   COPYING file in the source distribution for details.
+
+   ---------------------------------------------------------------- 
+*/
+
+
+/* This file is for inclusion into client (your!) code.
+
+   You can use these macros to manipulate and query Valgrind's 
+   execution inside your own programs.
+
+   The resulting executables will still run without Valgrind, just a
+   little bit more slowly than they otherwise would, but otherwise
+   unchanged.  When not running on valgrind, each client request
+   consumes very few (eg. < 10) instructions, so the resulting performance
+   loss is negligible unless you plan to execute client requests
+   millions of times per second.  Nevertheless, if that is still a
+   problem, you can compile with the NVALGRIND symbol defined (gcc
+   -DNVALGRIND) so that client requests are not even compiled in.  */
+
+#ifndef __VALGRIND_H
+#define __VALGRIND_H
+
+#include <stdarg.h>
+
+/* Nb: this file might be included in a file compiled with -ansi.  So
+   we can't use C++ style "//" comments nor the "asm" keyword (instead
+   use "__asm__"). */
+
+/* If we're not compiling for our target architecture, don't generate
+   any inline asms.  Note that in this file we're using the compiler's
+   CPP symbols for identifying architectures, which are different to
+   the ones we use within the rest of Valgrind. */
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__)
+#  ifndef NVALGRIND
+#    define NVALGRIND	1
+#  endif  /* NVALGRIND */
+#endif
+
+/* ------------------------------------------------------------------ */
+/* The architecture-specific part                                     */
+/* ------------------------------------------------------------------ */
+
+#ifdef NVALGRIND
+
+/* Define NVALGRIND to completely remove the Valgrind magic sequence
+   from the compiled code (analogous to NDEBUG's effects on assert()) */
+#define VALGRIND_MAGIC_SEQUENCE(					\
+        _zzq_rlval, _zzq_default, _zzq_request,                         \
+        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)                     \
+   {									\
+      (_zzq_rlval) = (_zzq_default);					\
+   }
+
+#else  /* NVALGRIND */
+
+/* The following defines the magic code sequences which the JITter spots and
+   handles magically.  Don't look too closely at them; they will rot
+   your brain.  We must ensure that the default value gets put in the return
+   slot, so that everything works when this is executed not under Valgrind.
+   Args are passed in a memory block, and so there's no intrinsic limit to
+   the number that could be passed, but it's currently four.
+   
+   The macro args are: 
+      _zzq_rlval    result lvalue
+      _zzq_default  default value (result returned when running on real CPU)
+      _zzq_request  request code
+      _zzq_arg1..4  request params
+
+   Nb: we put the assembly code sequences for all architectures in this one
+   file.  This is because this file must be stand-alone, and we don't want
+   to have multiple files.
+*/
+
+#ifdef __x86_64__
+#define VALGRIND_MAGIC_SEQUENCE(                                \
+        _zzq_rlval, _zzq_default, _zzq_request,                 \
+        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)             \
+                                                                \
+  { volatile unsigned long long _zzq_args[5];                   \
+    _zzq_args[0] = (volatile unsigned long long)(_zzq_request); \
+    _zzq_args[1] = (volatile unsigned long long)(_zzq_arg1);    \
+    _zzq_args[2] = (volatile unsigned long long)(_zzq_arg2);    \
+    _zzq_args[3] = (volatile unsigned long long)(_zzq_arg3);    \
+    _zzq_args[4] = (volatile unsigned long long)(_zzq_arg4);    \
+    __asm__ volatile("roll $29, %%eax ; roll $3, %%eax\n\t"	\
+                     "rorl $27, %%eax ; rorl $5, %%eax\n\t"	\
+                     "roll $13, %%eax ; roll $19, %%eax"		\
+                     : "=d" (_zzq_rlval)				\
+                     : "a" (&_zzq_args[0]), "0" (_zzq_default)	\
+                     : "cc", "memory"				\
+                    );						\
+  }
+#endif  /* __x86_64__ */
+
+#ifdef __i386__
+#define VALGRIND_MAGIC_SEQUENCE(				\
+        _zzq_rlval, _zzq_default, _zzq_request,			\
+        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)		\
+								\
+  { unsigned int _zzq_args[5];					\
+    _zzq_args[0] = (unsigned int)(_zzq_request);		\
+    _zzq_args[1] = (unsigned int)(_zzq_arg1);			\
+    _zzq_args[2] = (unsigned int)(_zzq_arg2);			\
+    _zzq_args[3] = (unsigned int)(_zzq_arg3);			\
+    _zzq_args[4] = (unsigned int)(_zzq_arg4);			\
+    __asm__ volatile("roll $29, %%eax ; roll $3, %%eax\n\t"	\
+                     "rorl $27, %%eax ; rorl $5, %%eax\n\t"	\
+                     "roll $13, %%eax ; roll $19, %%eax"	\
+                     : "=d" (_zzq_rlval)			\
+                     : "a" (&_zzq_args[0]), "0" (_zzq_default)	\
+                     : "cc", "memory"				\
+                    );						\
+  }
+#endif  /* __i386__ */
+
+#ifdef __powerpc__
+#define VALGRIND_MAGIC_SEQUENCE(                                        \
+        _zzq_rlval, _zzq_default, _zzq_request,                         \
+        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4)                     \
+                                                                        \
+  { volatile unsigned int _zzq_args[5];                                 \
+    register unsigned int _zzq_tmp __asm__("r3");                       \
+    register volatile unsigned int *_zzq_ptr __asm__("r4");             \
+    _zzq_args[0] = (volatile unsigned int)(_zzq_request);               \
+    _zzq_args[1] = (volatile unsigned int)(_zzq_arg1);                  \
+    _zzq_args[2] = (volatile unsigned int)(_zzq_arg2);                  \
+    _zzq_args[3] = (volatile unsigned int)(_zzq_arg3);                  \
+    _zzq_args[4] = (volatile unsigned int)(_zzq_arg4);                  \
+    _zzq_ptr = _zzq_args;                                               \
+    __asm__ volatile("tw 0,3,27\n\t"                                    \
+                     "rlwinm 0,0,29,0,0\n\t"                            \
+                     "rlwinm 0,0,3,0,0\n\t"                             \
+                     "rlwinm 0,0,13,0,0\n\t"                            \
+                     "rlwinm 0,0,19,0,0\n\t"                            \
+                     "nop\n\t"                                          \
+                     : "=r" (_zzq_tmp)                                  \
+                     : "0" (_zzq_default), "r" (_zzq_ptr)               \
+                     : "memory");                                       \
+    _zzq_rlval = (__typeof__(_zzq_rlval)) _zzq_tmp;                     \
+  }
+#endif   /* __powerpc__ */
+
+/* Insert assembly code for other architectures here... */
+
+#endif /* NVALGRIND */
+
+
+/* ------------------------------------------------------------------ */
+/* The architecture-independent part                                  */
+/* ------------------------------------------------------------------ */
+
+/* Some request codes.  There are many more of these, but most are not
+   exposed to end-user view.  These are the public ones, all of the
+   form 0x1000 + small_number.
+
+   Core ones are in the range 0x00000000--0x0000ffff.  The non-public ones
+   start at 0x2000.
+*/
+
+/* These macros are used by tools -- they must be public, but don't embed them
+ * into other programs. */
+#define VG_USERREQ_TOOL_BASE(a,b) \
+   ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
+#define VG_IS_TOOL_USERREQ(a, b, v) \
+   (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
+
+typedef
+   enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
+          VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
+
+          /* These allow any function to be called from the
+             simulated CPU but run on the real CPU.
+             Nb: the first arg passed to the function is always the ThreadId of
+             the running thread!  So CLIENT_CALL0 actually requires a 1 arg
+             function, etc. */
+          VG_USERREQ__CLIENT_CALL0 = 0x1101,
+          VG_USERREQ__CLIENT_CALL1 = 0x1102,
+          VG_USERREQ__CLIENT_CALL2 = 0x1103,
+          VG_USERREQ__CLIENT_CALL3 = 0x1104,
+
+          /* Can be useful in regression testing suites -- eg. can send
+             Valgrind's output to /dev/null and still count errors. */
+          VG_USERREQ__COUNT_ERRORS = 0x1201,
+
+          /* These are useful and can be interpreted by any tool that tracks
+             malloc() et al, by using vg_replace_malloc.c. */
+          VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+          VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
+          /* Memory pool support. */
+          VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
+          VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
+          VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
+          VG_USERREQ__MEMPOOL_FREE     = 0x1306,
+
+          /* Allow printfs to valgrind log. */
+          VG_USERREQ__PRINTF           = 0x1401,
+          VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
+
+          /* Stack support. */
+          VG_USERREQ__STACK_REGISTER   = 0x1501,
+          VG_USERREQ__STACK_DEREGISTER = 0x1502,
+          VG_USERREQ__STACK_CHANGE     = 0x1503,
+   } Vg_ClientRequest;
+
+#ifndef __GNUC__
+#define __extension__
+#endif
+
+/* Returns the number of Valgrinds this code is running under.  That is,
+   0 if running natively, 1 if running under Valgrind, 2 if running under
+   Valgrind which is running under another Valgrind, etc. */
+#define RUNNING_ON_VALGRIND  __extension__                         \
+   ({unsigned int _qzz_res;                                        \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* returned if not */,     \
+                            VG_USERREQ__RUNNING_ON_VALGRIND,       \
+                            0, 0, 0, 0);                           \
+    _qzz_res;                                                      \
+   })
+
+
+/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
+   _qzz_len - 1].  Useful if you are debugging a JITter or some such,
+   since it provides a way to make sure valgrind will retranslate the
+   invalidated area.  Returns no value. */
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)          \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__DISCARD_TRANSLATIONS,      \
+                            _qzz_addr, _qzz_len, 0, 0);            \
+   }
+
+#ifdef NVALGRIND
+
+#define VALGRIND_PRINTF(...)
+#define VALGRIND_PRINTF_BACKTRACE(...)
+
+#else /* NVALGRIND */
+
+/* Modern GCC will optimize the static routine out if unused,
+   and unused attribute will shut down warnings about it.  */
+static int VALGRIND_PRINTF(const char *format, ...)
+   __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF(const char *format, ...)
+{
+   unsigned long _qzz_res;
+   va_list vargs;
+   va_start(vargs, format);
+   VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__PRINTF,
+                           (unsigned long)format, (unsigned long)vargs, 0, 0);
+   va_end(vargs);
+   return (int)_qzz_res;
+}
+
+static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+   __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+{
+   unsigned long _qzz_res;
+   va_list vargs;
+   va_start(vargs, format);
+   VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
+                           (unsigned long)format, (unsigned long)vargs, 0, 0);
+   va_end(vargs);
+   return (int)_qzz_res;
+}
+
+#endif /* NVALGRIND */
+
+/* These requests allow control to move from the simulated CPU to the
+   real CPU, calling an arbitary function */
+#define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                       \
+   ({unsigned long _qyy_res;                                   \
+    VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */,  \
+                            VG_USERREQ__CLIENT_CALL0,          \
+                            _qyy_fn,                           \
+                            0, 0, 0);                          \
+    _qyy_res;                                                  \
+   })
+
+#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)            \
+   ({unsigned long _qyy_res;                                   \
+    VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */,  \
+                            VG_USERREQ__CLIENT_CALL1,          \
+                            _qyy_fn,                           \
+                            _qyy_arg1, 0, 0);                  \
+    _qyy_res;                                                  \
+   })
+
+#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
+   ({unsigned long _qyy_res;                                   \
+    VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */,  \
+                            VG_USERREQ__CLIENT_CALL2,          \
+                            _qyy_fn,                           \
+                            _qyy_arg1, _qyy_arg2, 0);          \
+    _qyy_res;                                                  \
+   })
+
+#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3)  \
+   ({unsigned long _qyy_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */,        \
+                            VG_USERREQ__CLIENT_CALL3,                \
+                            _qyy_fn,                                 \
+                            _qyy_arg1, _qyy_arg2, _qyy_arg3);        \
+    _qyy_res;                                                        \
+   })
+
+
+/* Counts the number of errors that have been recorded by a tool.  Nb:
+   the tool must record the errors with VG_(maybe_record_error)() or
+   VG_(unique_error)() for them to be counted. */
+#define VALGRIND_COUNT_ERRORS                                           \
+   ({unsigned int _qyy_res;                                             \
+    VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */,           \
+                            VG_USERREQ__COUNT_ERRORS,                   \
+                            0, 0, 0, 0);                                \
+    _qyy_res;                                                           \
+   })
+
+/* Mark a block of memory as having been allocated by a malloc()-like
+   function.  `addr' is the start of the usable block (ie. after any
+   redzone) `rzB' is redzone size if the allocator can apply redzones;
+   use '0' if not.  Adding redzones makes it more likely Valgrind will spot
+   block overruns.  `is_zeroed' indicates if the memory is zeroed, as it is
+   for calloc().  Put it immediately after the point where a block is
+   allocated. 
+   
+   If you're allocating memory via superblocks, and then handing out small
+   chunks of each superblock, if you don't have redzones on your small
+   blocks, it's worth marking the superblock with VALGRIND_MAKE_NOACCESS
+   when it's created, so that block overruns are detected.  But if you can
+   put redzones on, it's probably better to not do this, so that messages
+   for small overruns are described in terms of the small block rather than
+   the superblock (but if you have a big overrun that skips over a redzone,
+   you could miss an error this way).  See memcheck/tests/custom_alloc.c
+   for an example.
+
+   Nb: block must be freed via a free()-like function specified
+   with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)     \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__MALLOCLIKE_BLOCK,          \
+                            addr, sizeB, rzB, is_zeroed);          \
+   }
+
+/* Mark a block of memory as having been freed by a free()-like function.
+   `rzB' is redzone size;  it must match that given to
+   VALGRIND_MALLOCLIKE_BLOCK.  Memory not freed will be detected by the leak
+   checker.  Put it immediately after the point where the block is freed. */
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB)                         \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__FREELIKE_BLOCK,            \
+                            addr, rzB, 0, 0);                      \
+   }
+
+/* Create a memory pool. */
+#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)              \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__CREATE_MEMPOOL,            \
+                            pool, rzB, is_zeroed, 0);              \
+   }
+
+/* Destroy a memory pool. */
+#define VALGRIND_DESTROY_MEMPOOL(pool)                             \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__DESTROY_MEMPOOL,           \
+                            pool, 0, 0, 0);                        \
+   }
+
+/* Associate a piece of memory with a memory pool. */
+#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                   \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__MEMPOOL_ALLOC,             \
+                            pool, addr, size, 0);                  \
+   }
+
+/* Disassociate a piece of memory from a memory pool. */
+#define VALGRIND_MEMPOOL_FREE(pool, addr)                          \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__MEMPOOL_FREE,              \
+                            pool, addr, 0, 0);                     \
+   }
+
+/* Mark a piece of memory as being a stack. Returns a stack id. */
+#define VALGRIND_STACK_REGISTER(start, end)                        \
+   ({unsigned int _qzz_res;                                        \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__STACK_REGISTER,            \
+                            start, end, 0, 0);                     \
+    _qzz_res;                                                      \
+   })
+
+/* Unmark the piece of memory associated with a stack id as being a
+   stack. */
+#define VALGRIND_STACK_DEREGISTER(id)                              \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__STACK_DEREGISTER,          \
+                            id, 0, 0, 0);                          \
+   }
+
+/* Change the start and end address of the stack id. */
+#define VALGRIND_STACK_CHANGE(id, start, end)                      \
+   {unsigned int _qzz_res;                                         \
+    VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0,                           \
+                            VG_USERREQ__STACK_CHANGE,              \
+                            id, start, end, 0);                    \
+   }
+
+#endif   /* __VALGRIND_H */
Index: tests/array-test.c
===================================================================
RCS file: /cvs/gnome/glib/tests/array-test.c,v
retrieving revision 1.6
diff -u -p -d -r1.6 array-test.c
--- tests/array-test.c	14 Mar 2005 06:01:51 -0000	1.6
+++ tests/array-test.c	19 May 2006 04:01:00 -0000
@@ -83,6 +83,23 @@ main (int   argc,
   g_ptr_array_foreach (gparray, sum_up, &sum);
   g_assert (sum == 49995000);
 
+  g_ptr_array_remove (gparray, GINT_TO_POINTER (13));
+
+  sum = 0;
+  g_ptr_array_foreach (gparray, sum_up, &sum);
+  g_assert (sum == 49995000 - 13);
+
+  g_ptr_array_index (gparray, 9998)++;
+
+  g_ptr_array_foreach (gparray, sum_up, &sum);
+  g_assert (sum == (49995000 - 13) * 2 + 1);
+
+  /*
+   * uncommenting the following line should make
+   * valgrind err about invalid access.
+   */
+  /* g_ptr_array_index (gparray, 9999)++; */
+
   g_ptr_array_free (gparray, TRUE);
 
   /* byte arrays */
Index: tests/slice-test.c
===================================================================
RCS file: /cvs/gnome/glib/tests/slice-test.c,v
retrieving revision 1.6
diff -u -p -d -r1.6 slice-test.c
--- tests/slice-test.c	5 Apr 2006 05:56:47 -0000	1.6
+++ tests/slice-test.c	19 May 2006 04:01:00 -0000
@@ -26,7 +26,7 @@
 static guint    prime_size = 1021; // 769; // 509
 static gboolean clean_memchunks = FALSE;
 static guint    number_of_blocks = 10000;          /* total number of blocks allocated */
-static guint    number_of_repetitions = 10000;     /* number of alloc+free repetitions */
+static guint    number_of_repetitions = 1000;     /* number of alloc+free repetitions */
 
 /* --- old memchunk prototypes (memchunks.c) --- */
 void            old_mem_chunks_init     (void);
@@ -135,7 +135,12 @@ test_memchunk_thread (gpointer data)
 static gpointer
 test_sliced_mem_thread (gpointer data)
 {
+  guint i, j;
+  guint8 **ps;
+  guint   *ss;
+
   guint32 rand_accu = 2147483563;
+
   /* initialize random numbers */
   if (data)
     rand_accu = *(guint32*) data;
@@ -146,9 +151,8 @@ test_sliced_mem_thread (gpointer data)
       rand_accu = rand_tv.tv_usec + (rand_tv.tv_sec << 16);
     }
 
-  guint i, j;
-  guint8 **ps = g_new (guint8*, number_of_blocks);
-  guint   *ss = g_new (guint, number_of_blocks);
+  ps = g_new (guint8*, number_of_blocks);
+  ss = g_new (guint, number_of_blocks);
   /* create number_of_blocks random sizes */
   for (i = 0; i < number_of_blocks; i++)
     ss[i] = quick_rand32() % prime_size;
@@ -169,7 +173,18 @@ test_sliced_mem_thread (gpointer data)
     }
   /* free number_of_blocks blocks */
   for (i = 0; i < number_of_blocks; i++)
-    g_slice_free1 (ss[i], ps[i]);
+    {
+      g_slice_free1 (ss[i], ps[i]);
+      /*
+       * uncomment the following lines to get
+       * valgrind issue an error if glib valgrind
+       * hints are enabled.
+       */
+      /*
+      if (i == 0)
+        ps[i][0]++;
+       */
+    }
   /* alloc and free many equally sized chunks in a row */
   for (i = 0; i < number_of_repetitions; i++)
     {
@@ -189,7 +204,7 @@ test_sliced_mem_thread (gpointer data)
 static void
 usage (void)
 {
-  g_print ("Usage: slice-test [n_threads] [G|S|M|O][f][c] [maxblocksize] [seed]\n");
+  g_print ("Usage: slice-test [n_threads] [G|S|M|O][f][c] [repetitions] [maxblocksize] [seed]\n");
 }
 
 int
@@ -197,8 +212,11 @@ main (int   argc,
       char *argv[])
 {
   guint seed32, *seedp = NULL;
+  gchar strseed[64] = "<random>";
   gboolean ccounters = FALSE, use_memchunks = FALSE;
   guint n_threads = 1;
+  GThread **threads;
+  guint i;
   const gchar *mode = "slab allocator + magazine cache", *emode = " ";
   if (argc > 1)
     n_threads = g_ascii_strtoull (argv[1], NULL, 10);
@@ -240,10 +258,12 @@ main (int   argc,
           }
     }
   if (argc > 3)
-    prime_size = g_ascii_strtoull (argv[3], NULL, 10);
+    number_of_repetitions = g_ascii_strtoull (argv[3], NULL, 10);
   if (argc > 4)
+    prime_size = g_ascii_strtoull (argv[4], NULL, 10);
+  if (argc > 5)
     {
-      seed32 = g_ascii_strtoull (argv[4], NULL, 10);
+      seed32 = g_ascii_strtoull (argv[5], NULL, 10);
       seedp = &seed32;
     }
 
@@ -252,13 +272,11 @@ main (int   argc,
   if (argc <= 1)
     usage();
 
-  gchar strseed[64] = "<random>";
   if (seedp)
     g_snprintf (strseed, 64, "%u", *seedp);
-  g_print ("Starting %d threads allocating random blocks <= %u bytes with seed=%s using %s%s\n", n_threads, prime_size, strseed, mode, emode);
+  g_print ("Starting %d threads allocating random blocks <= %u bytes %u times, with seed=%s using %s%s\n", n_threads, prime_size, number_of_repetitions, strseed, mode, emode);
   
-  GThread *threads[n_threads];
-  guint i;
+  threads = g_new (GThread *, n_threads);
   if (!use_memchunks)
     for (i = 0; i < n_threads; i++)
       threads[i] = g_thread_create_full (test_sliced_mem_thread, seedp, 0, TRUE, FALSE, 0, NULL);
@@ -270,6 +288,7 @@ main (int   argc,
     }
   for (i = 0; i < n_threads; i++)
     g_thread_join (threads[i]);
+  g_free (threads);
   
   if (ccounters)
     {
