Index: docs/reference/gobject/gobject-docs.sgml
===================================================================
--- docs/reference/gobject/gobject-docs.sgml	(revision 5826)
+++ docs/reference/gobject/gobject-docs.sgml	(working copy)
@@ -17,6 +17,7 @@
 <!ENTITY glib-mkenums SYSTEM "glib-mkenums.xml">
 <!ENTITY glib-genmarshal SYSTEM "glib-genmarshal.xml">
 <!ENTITY gobject-query SYSTEM "gobject-query.xml">
+<!ENTITY gobject-stats SYSTEM "gobject-stats.xml">
 <!ENTITY version SYSTEM "version.xml">
 
 <!ENTITY tutorial-Intro SYSTEM "tut_intro.xml">
@@ -109,6 +110,7 @@
     &glib-mkenums;
     &glib-genmarshal;
     &gobject-query;
+    &gobject-stats;
   </reference>
   <part label="IV">
     <title>Tutorial</title>
Index: docs/reference/gobject/gobject-stats.1
===================================================================
--- docs/reference/gobject/gobject-stats.1	(revision 0)
+++ docs/reference/gobject/gobject-stats.1	(revision 0)
@@ -0,0 +1,57 @@
+.\"     Title: gobject-stats
+.\"    Author: 
+.\" Generator: DocBook XSL Stylesheets v1.73.2 <http://docbook.sf.net/>
+.\"      Date: 11/09/2007
+.\"    Manual: 
+.\"    Source: 
+.\"
+.TH "GOBJECT\-STATS" "1" "11/09/2007" "" ""
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+gobject-stats - Generate a nicely formatted report of GType usage
+.SH "SYNOPSIS"
+.HP 14
+\fBgobject\-stats\fR [options...] [files...]
+.SH "DESCRIPTION"
+.PP
+\fBgobject\-stats\fR
+generates a nicely formatted report from the debugging messages triggered by setting GObject\'s G_TYPE_DEBUG_TYPES debug flag\. See the GTypeDebugFlags section fo the GObject Reference Manual to learn how to set this flag\.
+.SH "INVOCATION"
+.PP
+\fBgobject\-stats\fR
+takes a list of GObject\-generated statistics on GType usage as input\. The statistics are either read from standard input or from files passed as additional arguments on the command line\.
+.SS "Options"
+.PP
+\fB\-s\fR \fIcol\fR, \fB\-\-sort\-ascending\fR \fIcol\fR
+.RS 4
+Sort column
+\fIcol\fR
+in ascending order, where
+\fIcol\fR
+is one of "type", "population", "created", or "destroyed"
+.RE
+.PP
+\fB\-S\fR \fIcol\fR \fB\-\-sort\-descending\fR \fIcol\fR
+.RS 4
+Sort column
+\fIcol\fR
+in descending order, where
+\fIcol\fR
+is one of "type", "population", "created", or "destroyed"
+.RE
+.PP
+\fB\-\-help\fR
+.RS 4
+Print brief help and exit\.
+.RE
+.SH "BUGS"
+.PP
+None known yet\.
+.SH "AUTHOR"
+.PP
+\fBgobject\-stats\fR
+was written by Matthew Barnes
+<mbarnes@redhat\.com>
Index: docs/reference/gobject/gobject-stats.xml
===================================================================
--- docs/reference/gobject/gobject-stats.xml	(revision 0)
+++ docs/reference/gobject/gobject-stats.xml	(revision 0)
@@ -0,0 +1,82 @@
+<refentry id="gobject-stats">
+
+<refmeta>
+<refentrytitle>gobject-stats</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname>gobject-stats</refname>
+<refpurpose>Generate a nicely formatted report of GType usage</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>gobject-stats</command>
+<arg choice="opt" rep="repeat">options</arg>
+<arg choice="opt" rep="repeat">files</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><command>gobject-stats</command> generates a nicely formatted
+report from the debugging messages triggered by setting GObject's
+G_TYPE_DEBUG_TYPES debug flag. See the GTypeDebugFlags section fo the
+GObject Reference Manual to learn how to set this flag.
+</para>
+</refsect1>
+
+<refsect1><title>Invocation</title>
+<para><command>gobject-stats</command> takes a list of GObject-generated
+statistics on GType usage as input. The statistics are either read from
+standard input or from files passed as additional arguments on the command
+line.
+</para>
+
+<refsect2><title>Options</title>
+<variablelist>
+
+<varlistentry>
+<term><option>-s</option> <replaceable>col</replaceable>,
+<option>--sort-ascending</option> <replaceable>col</replaceable></term>
+<listitem><para>
+Sort column <replaceable>col</replaceable> in ascending order, where
+<replaceable>col</replaceable> is one of "type", "population", "created",
+or "destroyed"
+</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><option>-S</option> <replaceable>col</replaceable>
+<option>--sort-descending</option> <replaceable>col</replaceable></term>
+<listitem><para>
+Sort column <replaceable>col</replaceable> in descending order, where
+<replaceable>col</replaceable> is one of "type", "population", "created",
+or "destroyed"
+</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><option>--help</option></term>
+<listitem><para>
+Print brief help and exit.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+</refsect2>
+</refsect1>
+
+<refsect1><title>Bugs</title>
+<para>
+None known yet.
+</para>
+</refsect1>
+
+<refsect1><title>Author</title>
+<para><command>gobject-stats</command> was written by Matthew Barnes
+<email>mbarnes@redhat.com</email>
+</para>
+</refsect1>
+
+</refentry>
Index: docs/reference/gobject/Makefile.am
===================================================================
--- docs/reference/gobject/Makefile.am	(revision 5826)
+++ docs/reference/gobject/Makefile.am	(working copy)
@@ -38,6 +38,7 @@ MKDB_OPTIONS=
 content_files = version.xml 		\
 		glib-mkenums.xml 	\
 		glib-genmarshal.xml	\
+		gobject-stats.xml \
 		gobject-query.xml \
 		tut_gobject.xml \
 		tut_gsignal.xml \
@@ -62,7 +63,7 @@ EXTRA_DIST += 		\
 
 ########################################################################
 
-man_MANS = glib-mkenums.1 glib-genmarshal.1 gobject-query.1
+man_MANS = glib-mkenums.1 glib-genmarshal.1 gobject-query.1 gobject-stats.1
 
 if ENABLE_MAN
 
Index: docs/reference/gobject/tmpl/gtype.sgml
===================================================================
--- docs/reference/gobject/tmpl/gtype.sgml	(revision 5826)
+++ docs/reference/gobject/tmpl/gtype.sgml	(working copy)
@@ -628,13 +628,14 @@ The <type>GTypeDebugFlags</type> enumera
 g_type_init_with_debug_flags() to trigger debugging messages during runtime.
 Note that the messages can also be triggered by setting the
 <envar>GOBJECT_DEBUG</envar> environment variable to a ':'-separated list of 
-"objects" and "signals".
+"objects", "signals" and "types".
 
 </para>
 
 @G_TYPE_DEBUG_NONE: Print no messages.
-@G_TYPE_DEBUG_OBJECTS: Print messages about object bookkeeping.
+@G_TYPE_DEBUG_OBJECTS: Print messages about stale GObjects.
 @G_TYPE_DEBUG_SIGNALS: Print messages about signal emissions.
+@G_TYPE_DEBUG_TYPES: Print messages about instance bookkeeping.
 @G_TYPE_DEBUG_MASK: Mask covering all debug flags.
 
 <!-- ##### FUNCTION g_type_init_with_debug_flags ##### -->
Index: gobject/gtype.c
===================================================================
--- gobject/gtype.c	(revision 5826)
+++ gobject/gtype.c	(working copy)
@@ -306,6 +306,50 @@ static GQuark          static_quark_ifac
 static GQuark          static_quark_dependants_array = 0;
 GTypeDebugFlags	       _g_type_debug_flags = 0;
 
+#ifdef G_ENABLE_DEBUG
+#define IF_DEBUG(debug_type)    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
+G_LOCK_DEFINE_STATIC (debug_types);
+static GTree *debug_types_tree = NULL;
+
+typedef struct {
+  guint num_created;
+  guint num_destroyed;
+  guint max_population;
+} DebugTypeStats;
+
+static gint
+debug_types_compare (gconstpointer a, gconstpointer b)
+{
+  return strcmp (g_type_name (GPOINTER_TO_SIZE (a)),
+                 g_type_name (GPOINTER_TO_SIZE (b)));
+}
+
+static gboolean
+debug_types_foreach (gpointer key,
+                     gpointer value,
+                     gpointer user_data)
+{
+  GType type = GPOINTER_TO_SIZE (key);
+  DebugTypeStats *stats = value;
+
+  g_message ("%s | created %u | destroyed %u | max-population %u",
+             g_type_name (type), stats->num_created, stats->num_destroyed,
+             stats->max_population);
+  return FALSE;
+}
+
+static void
+debug_types_atexit (void)
+{
+  IF_DEBUG (TYPES)
+    {
+      G_LOCK (debug_types);
+      g_tree_foreach (debug_types_tree, debug_types_foreach, NULL);
+      G_UNLOCK (debug_types);
+    }
+}
+#endif /* G_ENABLE_DEBUG */
+
 
 /* --- type nodes --- */
 static GHashTable       *static_type_nodes_ht = NULL;
@@ -1567,6 +1611,30 @@ g_type_create_instance (GType type)
   instance->g_class = class;
   if (node->data->instance.instance_init)
     node->data->instance.instance_init (instance, class);
+
+#ifdef G_ENABLE_DEBUG
+  IF_DEBUG (TYPES)
+    {
+      DebugTypeStats *stats;
+      gpointer key = GSIZE_TO_POINTER (type);
+
+      G_LOCK (debug_types);
+      stats = g_tree_lookup (debug_types_tree, key);
+      if (stats)
+        {
+          guint cur_population;
+          cur_population = ++stats->num_created - stats->num_destroyed;
+          stats->max_population = MAX (cur_population, stats->max_population);
+        }
+      else
+        {
+          stats = g_new0 (DebugTypeStats, 1);
+          stats->max_population = stats->num_created = 1;
+          g_tree_insert (debug_types_tree, key, stats);
+        }
+      G_UNLOCK (debug_types);
+    }
+#endif
   
   return instance;
 }
@@ -1598,6 +1666,18 @@ g_type_free_instance (GTypeInstance *ins
   instance->g_class = NULL;
 #ifdef G_ENABLE_DEBUG  
   memset (instance, 0xaa, type_total_instance_size_I (node));
+
+  IF_DEBUG (TYPES)
+    {
+      DebugTypeStats *stats;
+      gpointer key = GSIZE_TO_POINTER (class->g_type);
+
+      G_LOCK (debug_types);
+      stats = g_tree_lookup (debug_types_tree, key);
+      if (stats)
+        stats->num_destroyed++;
+      G_UNLOCK (debug_types);
+    }
 #endif
   g_slice_free1 (type_total_instance_size_I (node), instance);
 
@@ -3392,6 +3472,7 @@ g_type_init_with_debug_flags (GTypeDebug
       static GDebugKey debug_keys[] = {
 	{ "objects", G_TYPE_DEBUG_OBJECTS },
 	{ "signals", G_TYPE_DEBUG_SIGNALS },
+	{ "types",   G_TYPE_DEBUG_TYPES }
       };
       
       _g_type_debug_flags |= g_parse_debug_string (env_string,
@@ -3465,6 +3546,14 @@ g_type_init_with_debug_flags (GTypeDebug
   /* Signal system
    */
   g_signal_init ();
+
+#ifdef G_ENABLE_DEBUG
+  IF_DEBUG (TYPES)
+    {
+      debug_types_tree = g_tree_new (debug_types_compare);
+      g_atexit (debug_types_atexit);
+    }
+#endif
   
   G_UNLOCK (type_init_lock);
 }
Index: gobject/Makefile.am
===================================================================
--- gobject/Makefile.am	(revision 5826)
+++ gobject/Makefile.am	(working copy)
@@ -203,7 +203,7 @@ libgobject_2_0_la_SOURCES = $(gobject_ta
 # programs to compile and install
 #
 bin_PROGRAMS = gobject-query glib-genmarshal
-bin_SCRIPTS = glib-mkenums
+bin_SCRIPTS = glib-mkenums gobject-stats
 noinst_PROGRAMS = testgobject
 # source files
 gobject_query_SOURCES = gobject-query.c
Index: gobject/gtype.h
===================================================================
--- gobject/gtype.h	(revision 5826)
+++ gobject/gtype.h	(working copy)
@@ -159,7 +159,8 @@ typedef enum	/*< skip >*/
   G_TYPE_DEBUG_NONE	= 0,
   G_TYPE_DEBUG_OBJECTS	= 1 << 0,
   G_TYPE_DEBUG_SIGNALS	= 1 << 1,
-  G_TYPE_DEBUG_MASK	= 0x03
+  G_TYPE_DEBUG_TYPES	= 1 << 2,
+  G_TYPE_DEBUG_MASK	= 0x07
 } GTypeDebugFlags;
 
 
