hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gobject / gtype.c
index 412e9cc..dc58524 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
 
 #include "config.h"
 
+#include "../glib/valgrind.h"
 #include <string.h>
 
 #include "gtype.h"
+#include "gtype-private.h"
 #include "gtypeplugin.h"
 #include "gvaluecollector.h"
-#include "gbsearcharray.h"
-#include "gobjectalias.h"
 #include "gatomicarray.h"
+#include "gobject_trace.h"
 
+#include "gconstructor.h"
+
+#ifdef G_ENABLE_DEBUG
+#define        IF_DEBUG(debug_type)    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
+#endif
 
 /**
  * SECTION:gtype
  *
  * The GType API is the foundation of the GObject system.  It provides the
  * facilities for registering and managing all fundamental data types,
- * user-defined object and interface types.  Before using any GType
- * or GObject functions, g_type_init() must be called to initialize the
- * type system.
+ * user-defined object and interface types.
  *
  * For type creation and registration purposes, all types fall into one of
  * two categories: static or dynamic.  Static types are never loaded or
  * unloaded at run-time as dynamic types may be.  Static types are created
  * with g_type_register_static() that gets type specific information passed
  * in via a #GTypeInfo structure.
+ *
  * Dynamic types are created with g_type_register_dynamic() which takes a
  * #GTypePlugin structure instead. The remaining type information (the
  * #GTypeInfo structure) is retrieved during runtime through #GTypePlugin
  * and the g_type_plugin_*() API.
+ *
  * These registration functions are usually called only once from a
  * function whose only purpose is to return the type identifier for a
  * specific class.  Once the type (or class or interface) is registered,
  * it may be instantiated, inherited, or implemented depending on exactly
  * what sort of type it is.
+ *
  * There is also a third registration function for registering fundamental
  * types called g_type_register_fundamental() which requires both a #GTypeInfo
  * structure and a #GTypeFundamentalInfo structure but it is seldom used
  * since most fundamental types are predefined rather than user-defined.
  *
- * A final word about type names.
- * Such an identifier needs to be at least three characters long. There is no
- * upper length limit. The first character needs to be a letter (a-z or A-Z)
- * or an underscore '_'. Subsequent characters can be letters, numbers or
- * any of '-_+'.
+ * Type instance and class structs are limited to a total of 64 KiB,
+ * including all parent types. Similarly, type instances' private data
+ * (as created by g_type_class_add_private()) are limited to a total of
+ * 64 KiB. If a type instance needs a large static buffer, allocate it
+ * separately (typically by using #GArray or #GPtrArray) and put a pointer
+ * to the buffer in the structure.
+ *
+ * A final word about type names: Such an identifier needs to be at least
+ * three characters long. There is no upper length limit. The first character
+ * needs to be a letter (a-z or A-Z) or an underscore '_'. Subsequent
+ * characters can be letters, numbers or any of '-_+'.
  */
 
 
  * not ->supers[]), as all those memory portions can get realloc()ed during
  * callback invocation.
  *
- * TODO:
- * - g_type_from_name() should do an ordered array lookup after fetching the
- *   the quark, instead of a second hashtable lookup.
- *
  * LOCKING:
  * lock handling issues when calling static functions are indicated by
  * uppercase letter postfixes, all static functions have to have
  */
 
 #ifdef LOCK_DEBUG
-#define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
-#define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
-#define G_WRITE_LOCK(rw_lock)   do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
-#define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
+#define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_rw_lock_reader_lock (rw_lock); } while (0)
+#define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_rw_lock_reader_unlock (rw_lock); } while (0)
+#define G_WRITE_LOCK(rw_lock)   do { g_printerr (G_STRLOC ": writeL++\n"); g_rw_lock_writer_lock (rw_lock); } while (0)
+#define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_rw_lock_writer_unlock (rw_lock); } while (0)
 #else
-#define G_READ_LOCK(rw_lock)    g_static_rw_lock_reader_lock (rw_lock)
-#define G_READ_UNLOCK(rw_lock)  g_static_rw_lock_reader_unlock (rw_lock)
-#define G_WRITE_LOCK(rw_lock)   g_static_rw_lock_writer_lock (rw_lock)
-#define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
+#define G_READ_LOCK(rw_lock)    g_rw_lock_reader_lock (rw_lock)
+#define G_READ_UNLOCK(rw_lock)  g_rw_lock_reader_unlock (rw_lock)
+#define G_WRITE_LOCK(rw_lock)   g_rw_lock_writer_lock (rw_lock)
+#define G_WRITE_UNLOCK(rw_lock) g_rw_lock_writer_unlock (rw_lock)
 #endif
 #define        INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
     static const gchar _action[] = " invalidly modified type ";  \
     gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
     if (_arg) \
-      g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
+      g_error ("%s(%p)%s'%s'", _fname, _arg, _action, _tname); \
     else \
-      g_error ("%s()%s`%s'", _fname, _action, _tname); \
-}G_STMT_END
-#define        g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{     \
-  if (!(condition))                                                                            \
-    {                                                                                          \
-      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,                                               \
-            "%s: initialization assertion failed, use %s() prior to this function",            \
-            G_STRLOC, G_STRINGIFY (init_function));                                            \
-      return (return_value);                                                                   \
-    }                                                                                          \
+      g_error ("%s()%s'%s'", _fname, _action, _tname); \
 }G_STMT_END
+#define g_assert_type_system_initialized() \
+  g_assert (static_quark_type_flags)
 
 #ifdef  G_ENABLE_DEBUG
 #define DEBUG_CODE(debug_type, code_block)  G_STMT_START {    \
 /* --- typedefs --- */
 typedef struct _TypeNode        TypeNode;
 typedef struct _CommonData      CommonData;
+typedef struct _BoxedData       BoxedData;
 typedef struct _IFaceData       IFaceData;
 typedef struct _ClassData       ClassData;
 typedef struct _InstanceData    InstanceData;
@@ -225,10 +226,13 @@ typedef enum
 struct _TypeNode
 {
   guint volatile ref_count;
+#ifdef G_ENABLE_DEBUG
+  guint volatile instance_count;
+#endif
   GTypePlugin *plugin;
   guint        n_children; /* writable with lock */
   guint        n_supers : 8;
-  guint        _prot_n_prerequisites : 9;
+  guint        n_prerequisites : 9;
   guint        is_classed : 1;
   guint        is_instantiatable : 1;
   guint        mutatable_check_cache : 1;      /* combines some common path checks */
@@ -238,8 +242,9 @@ struct _TypeNode
   GData       *global_gdata;
   union {
     GAtomicArray iface_entries;                /* for !iface types */
-    GType       *prerequisistes;
+    GAtomicArray offsets;
   } _prot;
+  GType       *prerequisites;
   GType        supers[1]; /* flexible array */
 };
 
@@ -253,11 +258,12 @@ struct _TypeNode
 #define NODE_FUNDAMENTAL_TYPE(node)            (node->supers[node->n_supers])
 #define NODE_NAME(node)                                (g_quark_to_string (node->qname))
 #define NODE_REFCOUNT(node)                     ((guint) g_atomic_int_get ((int *) &(node)->ref_count))
+#define        NODE_IS_BOXED(node)                     (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_BOXED)
 #define        NODE_IS_IFACE(node)                     (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
 #define        CLASSED_NODE_IFACES_ENTRIES(node)       (&(node)->_prot.iface_entries)
 #define        CLASSED_NODE_IFACES_ENTRIES_LOCKED(node)(G_ATOMIC_ARRAY_GET_LOCKED(CLASSED_NODE_IFACES_ENTRIES((node)), IFaceEntries))
-#define        IFACE_NODE_N_PREREQUISITES(node)        ((node)->_prot_n_prerequisites)
-#define        IFACE_NODE_PREREQUISITES(node)          ((node)->_prot.prerequisistes)
+#define        IFACE_NODE_N_PREREQUISITES(node)        ((node)->n_prerequisites)
+#define        IFACE_NODE_PREREQUISITES(node)          ((node)->prerequisites)
 #define        iface_node_get_holders_L(node)          ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
 #define        iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
 #define        iface_node_get_dependants_array_L(n)    ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
@@ -296,6 +302,13 @@ struct _CommonData
   GTypeValueTable  *value_table;
 };
 
+struct _BoxedData
+{
+  CommonData         data;
+  GBoxedCopyFunc     copy_func;
+  GBoxedFreeFunc     free_func;
+};
+
 struct _IFaceData
 {
   CommonData         common;
@@ -306,13 +319,13 @@ struct _IFaceData
   GClassFinalizeFunc dflt_finalize;
   gconstpointer      dflt_data;
   gpointer           dflt_vtable;
-  GAtomicArray       offsets;
 };
 
 struct _ClassData
 {
   CommonData         common;
   guint16            class_size;
+  guint16            class_private_size;
   int volatile       init_state; /* atomic - g_type_class_ref reads it unlocked */
   GBaseInitFunc      class_init_base;
   GBaseFinalizeFunc  class_finalize_base;
@@ -326,6 +339,7 @@ struct _InstanceData
 {
   CommonData         common;
   guint16            class_size;
+  guint16            class_private_size;
   int volatile       init_state; /* atomic - g_type_class_ref reads it unlocked */
   GBaseInitFunc      class_init_base;
   GBaseFinalizeFunc  class_finalize_base;
@@ -342,6 +356,7 @@ struct _InstanceData
 union _TypeData
 {
   CommonData         common;
+  BoxedData          boxed;
   IFaceData          iface;
   ClassData          class;
   InstanceData       instance;
@@ -359,8 +374,8 @@ typedef struct {
 
 
 /* --- variables --- */
-static GStaticRWLock   type_rw_lock = G_STATIC_RW_LOCK_INIT;
-static GStaticRecMutex class_init_rec_mutex = G_STATIC_REC_MUTEX_INIT;
+static GRWLock         type_rw_lock;
+static GRecMutex       class_init_rec_mutex;
 static guint           static_n_class_cache_funcs = 0;
 static ClassCacheFunc *static_class_cache_funcs = NULL;
 static guint           static_n_iface_check_funcs = 0;
@@ -368,6 +383,7 @@ static IFaceCheckFunc *static_iface_check_funcs = NULL;
 static GQuark          static_quark_type_flags = 0;
 static GQuark          static_quark_iface_holder = 0;
 static GQuark          static_quark_dependants_array = 0;
+static guint           type_registration_serial = 0;
 GTypeDebugFlags               _g_type_debug_flags = 0;
 
 /* --- type nodes --- */
@@ -376,7 +392,7 @@ static TypeNode             *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYP
 static GType            static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
 
 static inline TypeNode*
-lookup_type_node_I (register GType utype)
+lookup_type_node_I (GType utype)
 {
   if (utype > G_TYPE_FUNDAMENTAL_MAX)
     return (TypeNode*) (utype & ~TYPE_ID_MASK);
@@ -384,6 +400,25 @@ lookup_type_node_I (register GType utype)
     return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
 }
 
+/**
+ * g_type_get_type_registration_serial:
+ *
+ * Returns an opaque serial number that represents the state of the set
+ * of registered types. Any time a type is registered this serial changes,
+ * which means you can cache information based on type lookups (such as
+ * g_type_from_name()) and know if the cache is still valid at a later
+ * time by comparing the current serial with the one at the type lookup.
+ *
+ * Since: 2.36
+ *
+ * Returns: An unsigned int, representing the state of type registrations
+ */
+guint
+g_type_get_type_registration_serial (void)
+{
+  return (guint)g_atomic_int_get ((gint *)&type_registration_serial);
+}
+
 static TypeNode*
 type_node_any_new_W (TypeNode             *pnode,
                     GType                 ftype,
@@ -468,17 +503,21 @@ type_node_any_new_W (TypeNode             *pnode,
       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
       pnode->children[i] = type;
     }
-  
+
+  TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type));
+
   node->plugin = plugin;
   node->n_children = 0;
   node->children = NULL;
   node->data = NULL;
   node->qname = g_quark_from_string (name);
   node->global_gdata = NULL;
-  
   g_hash_table_insert (static_type_nodes_ht,
-                      GUINT_TO_POINTER (node->qname),
+                      (gpointer) g_quark_to_string (node->qname),
                       (gpointer) type);
+
+  g_atomic_int_inc ((gint *)&type_registration_serial);
+
   return node;
 }
 
@@ -544,7 +583,7 @@ lookup_iface_entry_I (volatile IFaceEntries *entries,
     return NULL;
 
   G_ATOMIC_ARRAY_DO_TRANSACTION
-    (&iface_node->data->iface.offsets, guint8,
+    (&iface_node->_prot.offsets, guint8,
 
      entry = NULL;
      offsets = transaction_data;
@@ -671,25 +710,25 @@ check_plugin_U (GTypePlugin *plugin,
    */
   if (!plugin)
     {
-      g_warning ("plugin handle for type `%s' is NULL",
+      g_warning ("plugin handle for type '%s' is NULL",
                 type_name);
       return FALSE;
     }
   if (!G_IS_TYPE_PLUGIN (plugin))
     {
-      g_warning ("plugin pointer (%p) for type `%s' is invalid",
+      g_warning ("plugin pointer (%p) for type '%s' is invalid",
                 plugin, type_name);
       return FALSE;
     }
   if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
     {
-      g_warning ("plugin for type `%s' has no complete_type_info() implementation",
+      g_warning ("plugin for type '%s' has no complete_type_info() implementation",
                 type_name);
       return FALSE;
     }
   if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
     {
-      g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
+      g_warning ("plugin for type '%s' has no complete_interface_info() implementation",
                 type_name);
       return FALSE;
     }
@@ -705,7 +744,7 @@ check_type_name_I (const gchar *type_name)
   
   if (!type_name[0] || !type_name[1] || !type_name[2])
     {
-      g_warning ("type name `%s' is too short", type_name);
+      g_warning ("type name '%s' is too short", type_name);
       return FALSE;
     }
   /* check the first letter */
@@ -717,12 +756,12 @@ check_type_name_I (const gchar *type_name)
                   strchr (extra_chars, p[0]));
   if (!name_valid)
     {
-      g_warning ("type name `%s' contains invalid characters", type_name);
+      g_warning ("type name '%s' contains invalid characters", type_name);
       return FALSE;
     }
   if (g_type_from_name (type_name))
     {
-      g_warning ("cannot register existing type `%s'", type_name);
+      g_warning ("cannot register existing type '%s'", type_name);
       return FALSE;
     }
   
@@ -739,7 +778,7 @@ check_derivation_I (GType        parent_type,
   pnode = lookup_type_node_I (parent_type);
   if (!pnode)
     {
-      g_warning ("cannot derive type `%s' from invalid parent type `%s'",
+      g_warning ("cannot derive type '%s' from invalid parent type '%s'",
                 type_name,
                 type_descriptive_name_I (parent_type));
       return FALSE;
@@ -748,7 +787,7 @@ check_derivation_I (GType        parent_type,
   /* ensure flat derivability */
   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
     {
-      g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
+      g_warning ("cannot derive '%s' from non-derivable parent type '%s'",
                 type_name,
                 NODE_NAME (pnode));
       return FALSE;
@@ -757,7 +796,7 @@ check_derivation_I (GType        parent_type,
   if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
     {
-      g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
+      g_warning ("cannot derive '%s' from non-fundamental parent type '%s'",
                 type_name,
                 NODE_NAME (pnode));
       return FALSE;
@@ -792,7 +831,7 @@ check_value_table_I (const gchar           *type_name,
          value_table->value_peek_pointer ||
          value_table->collect_format || value_table->collect_value ||
          value_table->lcopy_format || value_table->lcopy_value)
-       g_warning ("cannot handle uninitializable values of type `%s'",
+       g_warning ("cannot handle uninitializable values of type '%s'",
                   type_name);
       return FALSE;
     }
@@ -801,25 +840,25 @@ check_value_table_I (const gchar           *type_name,
       if (!value_table->value_free)
        {
          /* +++ optional +++
-          * g_warning ("missing `value_free()' for type `%s'", type_name);
+          * g_warning ("missing 'value_free()' for type '%s'", type_name);
           * return FALSE;
           */
        }
       if (!value_table->value_copy)
        {
-         g_warning ("missing `value_copy()' for type `%s'", type_name);
+         g_warning ("missing 'value_copy()' for type '%s'", type_name);
          return FALSE;
        }
       if ((value_table->collect_format || value_table->collect_value) &&
          (!value_table->collect_format || !value_table->collect_value))
        {
-         g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
+         g_warning ("one of 'collect_format' and 'collect_value()' is unspecified for type '%s'",
                     type_name);
          return FALSE;
        }
       if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
        {
-         g_warning ("the `%s' specification for type `%s' is too long or invalid",
+         g_warning ("the '%s' specification for type '%s' is too long or invalid",
                     "collect_format",
                     type_name);
          return FALSE;
@@ -827,13 +866,13 @@ check_value_table_I (const gchar           *type_name,
       if ((value_table->lcopy_format || value_table->lcopy_value) &&
          (!value_table->lcopy_format || !value_table->lcopy_value))
        {
-         g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
+         g_warning ("one of 'lcopy_format' and 'lcopy_value()' is unspecified for type '%s'",
                     type_name);
          return FALSE;
        }
       if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
        {
-         g_warning ("the `%s' specification for type `%s' is too long or invalid",
+         g_warning ("the '%s' specification for type '%s' is too long or invalid",
                     "lcopy_format",
                     type_name);
          return FALSE;
@@ -858,11 +897,11 @@ check_type_info_I (TypeNode        *pnode,
       (info->instance_size || info->n_preallocs || info->instance_init))
     {
       if (pnode)
-       g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
+       g_warning ("cannot instantiate '%s', derived from non-instantiatable parent type '%s'",
                   type_name,
                   NODE_NAME (pnode));
       else
-       g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
+       g_warning ("cannot instantiate '%s' as non-instantiatable fundamental",
                   type_name);
       return FALSE;
     }
@@ -872,18 +911,18 @@ check_type_info_I (TypeNode        *pnode,
        info->class_size || info->base_init || info->base_finalize))
     {
       if (pnode)
-       g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
+       g_warning ("cannot create class for '%s', derived from non-classed parent type '%s'",
                   type_name,
                    NODE_NAME (pnode));
       else
-       g_warning ("cannot create class for `%s' as non-classed fundamental",
+       g_warning ("cannot create class for '%s' as non-classed fundamental",
                   type_name);
       return FALSE;
     }
   /* check interface size */
   if (is_interface && info->class_size < sizeof (GTypeInterface))
     {
-      g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
+      g_warning ("specified interface size for type '%s' is smaller than 'GTypeInterface' size",
                 type_name);
       return FALSE;
     }
@@ -892,14 +931,14 @@ check_type_info_I (TypeNode        *pnode,
     {
       if (info->class_size < sizeof (GTypeClass))
        {
-         g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
+         g_warning ("specified class size for type '%s' is smaller than 'GTypeClass' size",
                     type_name);
          return FALSE;
        }
       if (pnode && info->class_size < pnode->data->class.class_size)
        {
-         g_warning ("specified class size for type `%s' is smaller "
-                    "than the parent type's `%s' class size",
+         g_warning ("specified class size for type '%s' is smaller "
+                    "than the parent type's '%s' class size",
                     type_name,
                     NODE_NAME (pnode));
          return FALSE;
@@ -910,14 +949,14 @@ check_type_info_I (TypeNode        *pnode,
     {
       if (info->instance_size < sizeof (GTypeInstance))
        {
-         g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
+         g_warning ("specified instance size for type '%s' is smaller than 'GTypeInstance' size",
                     type_name);
          return FALSE;
        }
       if (pnode && info->instance_size < pnode->data->instance.instance_size)
        {
-         g_warning ("specified instance size for type `%s' is smaller "
-                    "than the parent type's `%s' instance size",
+         g_warning ("specified instance size for type '%s' is smaller "
+                    "than the parent type's '%s' instance size",
                     type_name,
                     NODE_NAME (pnode));
          return FALSE;
@@ -957,22 +996,28 @@ check_add_interface_L (GType instance_type,
   
   if (!node || !node->is_instantiatable)
     {
-      g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
+      g_warning ("cannot add interfaces to invalid (non-instantiatable) type '%s'",
                 type_descriptive_name_I (instance_type));
       return FALSE;
     }
   if (!iface || !NODE_IS_IFACE (iface))
     {
-      g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
+      g_warning ("cannot add invalid (non-interface) type '%s' to type '%s'",
                 type_descriptive_name_I (iface_type),
                 NODE_NAME (node));
       return FALSE;
     }
+  if (node->data && node->data->class.class)
+    {
+      g_warning ("attempting to add an interface (%s) to class (%s) after class_init",
+                 NODE_NAME (iface), NODE_NAME (node));
+      return FALSE;
+    }
   tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
   if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
     {
       /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
-      g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
+      g_warning ("cannot add sub-interface '%s' to type '%s' which does not conform to super-interface '%s'",
                 NODE_NAME (iface),
                 NODE_NAME (node),
                 NODE_NAME (tnode));
@@ -994,7 +1039,7 @@ check_add_interface_L (GType instance_type,
   tnode = find_conforming_child_type_L (node, iface);  /* tnode is_a node */
   if (tnode)
     {
-      g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
+      g_warning ("cannot add interface type '%s' to type '%s', since type '%s' already conforms to interface",
                 NODE_NAME (iface),
                 NODE_NAME (node),
                 NODE_NAME (tnode));
@@ -1006,7 +1051,7 @@ check_add_interface_L (GType instance_type,
       tnode = lookup_type_node_I (prerequisites[i]);
       if (!type_node_is_a_L (node, tnode))
        {
-         g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
+         g_warning ("cannot add interface type '%s' to type '%s' which does not conform to prerequisite '%s'",
                     NODE_NAME (iface),
                     NODE_NAME (node),
                     NODE_NAME (tnode));
@@ -1023,7 +1068,7 @@ check_interface_info_I (TypeNode             *iface,
 {
   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
     {
-      g_warning ("interface type `%s' for type `%s' comes without initializer",
+      g_warning ("interface type '%s' for type '%s' comes without initializer",
                 NODE_NAME (iface),
                 type_descriptive_name_I (instance_type));
       return FALSE;
@@ -1068,8 +1113,10 @@ type_data_make_W (TypeNode              *node,
       vtable_size += 2;
     }
    
-  if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
+  if (node->is_instantiatable) /* careful, is_instantiatable is also is_classed */
     {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+
       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
       if (vtable_size)
        vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
@@ -1086,6 +1133,9 @@ type_data_make_W (TypeNode              *node,
        * after the parent class has been initialized
        */
       data->instance.private_size = 0;
+      data->instance.class_private_size = 0;
+      if (pnode)
+        data->instance.class_private_size = pnode->data->instance.class_private_size;
 #ifdef DISABLE_MEM_POOLS
       data->instance.n_preallocs = 0;
 #else  /* !DISABLE_MEM_POOLS */
@@ -1095,6 +1145,8 @@ type_data_make_W (TypeNode              *node,
     }
   else if (node->is_classed) /* only classed */
     {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+
       data = g_malloc0 (sizeof (ClassData) + vtable_size);
       if (vtable_size)
        vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
@@ -1105,6 +1157,9 @@ type_data_make_W (TypeNode              *node,
       data->class.class_finalize = info->class_finalize;
       data->class.class_data = info->class_data;
       data->class.class = NULL;
+      data->class.class_private_size = 0;
+      if (pnode)
+        data->class.class_private_size = pnode->data->class.class_private_size;
       data->class.init_state = UNINITIALIZED;
     }
   else if (NODE_IS_IFACE (node))
@@ -1120,6 +1175,12 @@ type_data_make_W (TypeNode              *node,
       data->iface.dflt_data = info->class_data;
       data->iface.dflt_vtable = NULL;
     }
+  else if (NODE_IS_BOXED (node))
+    {
+      data = g_malloc0 (sizeof (BoxedData) + vtable_size);
+      if (vtable_size)
+       vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData));
+    }
   else
     {
       data = g_malloc0 (sizeof (CommonData) + vtable_size);
@@ -1225,7 +1286,7 @@ iface_node_has_available_offset_L (TypeNode *iface_node,
 {
   guint8 *offsets;
 
-  offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->data->iface.offsets, guint8);
+  offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
   if (offsets == NULL)
     return TRUE;
 
@@ -1276,7 +1337,7 @@ iface_node_set_offset_L (TypeNode *iface_node,
   int new_size, old_size;
   int i;
 
-  old_offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->data->iface.offsets, guint8);
+  old_offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
   if (old_offsets == NULL)
     old_size = 0;
   else
@@ -1288,7 +1349,7 @@ iface_node_set_offset_L (TypeNode *iface_node,
     }
   new_size = MAX (old_size, offset + 1);
 
-  offsets = _g_atomic_array_copy (&iface_node->data->iface.offsets,
+  offsets = _g_atomic_array_copy (&iface_node->_prot.offsets,
                                  0, new_size - old_size);
 
   /* Mark new area as unused */
@@ -1297,7 +1358,7 @@ iface_node_set_offset_L (TypeNode *iface_node,
 
   offsets[offset] = index + 1;
 
-  _g_atomic_array_update (&iface_node->data->iface.offsets, offsets);
+  _g_atomic_array_update (&iface_node->_prot.offsets, offsets);
 }
 
 static void
@@ -1463,8 +1524,8 @@ type_iface_add_prerequisite_W (TypeNode *iface,
                                              IFACE_NODE_PREREQUISITES (iface),
                                              IFACE_NODE_N_PREREQUISITES (iface));
   prerequisites = IFACE_NODE_PREREQUISITES (iface);
-  g_memmove (prerequisites + i + 1, prerequisites + i,
-            sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
+  memmove (prerequisites + i + 1, prerequisites + i,
+           sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
   prerequisites[i] = prerequisite_type;
   
   /* we want to get notified when prerequisites get added to prerequisite_node */
@@ -1488,8 +1549,8 @@ type_iface_add_prerequisite_W (TypeNode *iface,
 
 /**
  * g_type_interface_add_prerequisite:
- * @interface_type: #GType value of an interface type.
- * @prerequisite_type: #GType value of an interface or instantiatable type.
+ * @interface_type: #GType value of an interface type
+ * @prerequisite_type: #GType value of an interface or instantiatable type
  *
  * Adds @prerequisite_type to the list of prerequisites of @interface_type.
  * This means that any type implementing @interface_type must also implement
@@ -1512,7 +1573,7 @@ g_type_interface_add_prerequisite (GType interface_type,
   prerequisite_node = lookup_type_node_I (prerequisite_type);
   if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
     {
-      g_warning ("interface type `%s' or prerequisite type `%s' invalid",
+      g_warning ("interface type '%s' or prerequisite type '%s' invalid",
                 type_descriptive_name_I (interface_type),
                 type_descriptive_name_I (prerequisite_type));
       return;
@@ -1522,7 +1583,7 @@ g_type_interface_add_prerequisite (GType interface_type,
   if (holders)
     {
       G_WRITE_UNLOCK (&type_rw_lock);
-      g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
+      g_warning ("unable to add prerequisite '%s' to interface '%s' which is already in use for '%s'",
                 type_descriptive_name_I (prerequisite_type),
                 type_descriptive_name_I (interface_type),
                 type_descriptive_name_I (holders->instance_type));
@@ -1532,7 +1593,7 @@ g_type_interface_add_prerequisite (GType interface_type,
     {
       guint i;
       
-      /* can have at most one publically installable instantiatable prerequisite */
+      /* can have at most one publicly installable instantiatable prerequisite */
       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
        {
          TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]);
@@ -1540,7 +1601,7 @@ g_type_interface_add_prerequisite (GType interface_type,
          if (prnode->is_instantiatable)
            {
              G_WRITE_UNLOCK (&type_rw_lock);
-             g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
+             g_warning ("adding prerequisite '%s' to interface '%s' conflicts with existing prerequisite '%s'",
                         type_descriptive_name_I (prerequisite_type),
                         type_descriptive_name_I (interface_type),
                         type_descriptive_name_I (NODE_TYPE (prnode)));
@@ -1566,7 +1627,7 @@ g_type_interface_add_prerequisite (GType interface_type,
   else
     {
       G_WRITE_UNLOCK (&type_rw_lock);
-      g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
+      g_warning ("prerequisite '%s' for interface '%s' is neither instantiatable nor interface",
                 type_descriptive_name_I (prerequisite_type),
                 type_descriptive_name_I (interface_type));
     }
@@ -1575,14 +1636,16 @@ g_type_interface_add_prerequisite (GType interface_type,
 /**
  * g_type_interface_prerequisites:
  * @interface_type: an interface type
- * @n_prerequisites: location to return the number of prerequisites, or %NULL
+ * @n_prerequisites: (out) (allow-none): location to return the number
+ *     of prerequisites, or %NULL
  *
  * Returns the prerequisites of an interfaces type.
  *
  * Since: 2.2
  *
- * Returns: a newly-allocated zero-terminated array of #GType containing
- *  the prerequisites of @interface_type
+ * Returns: (array length=n_prerequisites) (transfer full): a
+ *     newly-allocated zero-terminated array of #GType containing
+ *     the prerequisites of @interface_type
  */
 GType*
 g_type_interface_prerequisites (GType  interface_type,
@@ -1605,9 +1668,11 @@ g_type_interface_prerequisites (GType  interface_type,
        {
          GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
          TypeNode *node = lookup_type_node_I (prerequisite);
-         if (node->is_instantiatable &&
-             (!inode || type_node_is_a_L (node, inode)))
-           inode = node;
+         if (node->is_instantiatable)
+            {
+              if (!inode || type_node_is_a_L (node, inode))
+               inode = node;
+            }
          else
            types[n++] = NODE_TYPE (node);
        }
@@ -1700,93 +1765,9 @@ type_iface_blow_holder_info_Wm (TypeNode *iface,
     }
 }
 
-/* Assumes type's class already exists
- */
-static inline size_t
-type_total_instance_size_I (TypeNode *node)
-{
-  gsize total_instance_size;
-
-  total_instance_size = node->data->instance.instance_size;
-  if (node->data->instance.private_size != 0)
-    total_instance_size = ALIGN_STRUCT (total_instance_size) + node->data->instance.private_size;
-
-  return total_instance_size;
-}
-
-/* --- type structure creation/destruction --- */
-typedef struct {
-  gpointer instance;
-  gpointer class;
-} InstanceRealClass;
-
-static gint
-instance_real_class_cmp (gconstpointer p1,
-                         gconstpointer p2)
-{
-  const InstanceRealClass *irc1 = p1;
-  const InstanceRealClass *irc2 = p2;
-  guint8 *i1 = irc1->instance;
-  guint8 *i2 = irc2->instance;
-  return G_BSEARCH_ARRAY_CMP (i1, i2);
-}
-
-G_LOCK_DEFINE_STATIC (instance_real_class);
-static GBSearchArray *instance_real_class_bsa = NULL;
-static GBSearchConfig instance_real_class_bconfig = {
-  sizeof (InstanceRealClass),
-  instance_real_class_cmp,
-  0,
-};
-
-static inline void
-instance_real_class_set (gpointer    instance,
-                         GTypeClass *class)
-{
-  InstanceRealClass key;
-  key.instance = instance;
-  key.class = class;
-  G_LOCK (instance_real_class);
-  if (!instance_real_class_bsa)
-    instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig);
-  instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key);
-  G_UNLOCK (instance_real_class);
-}
-
-static inline void
-instance_real_class_remove (gpointer instance)
-{
-  InstanceRealClass key, *node;
-  guint index;
-  key.instance = instance;
-  G_LOCK (instance_real_class);
-  node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
-  index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node);
-  instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index);
-  if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa))
-    {
-      g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig);
-      instance_real_class_bsa = NULL;
-    }
-  G_UNLOCK (instance_real_class);
-}
-
-static inline GTypeClass*
-instance_real_class_get (gpointer instance)
-{
-  InstanceRealClass key, *node;
-  GTypeClass *class;
-  key.instance = instance;
-  G_LOCK (instance_real_class);
-  node = instance_real_class_bsa ? g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key) : NULL;
-  class = node ? node->class : NULL;
-  G_UNLOCK (instance_real_class);
-  return class;
-}
-
 /**
- * g_type_create_instance:
- * @type: An instantiatable type to create an instance for.
+ * g_type_create_instance: (skip)
+ * @type: an instantiatable type to create an instance for
  *
  * Creates and initializes an instance of @type if @type is valid and
  * can be instantiated. The type system only performs basic allocation
@@ -1794,16 +1775,19 @@ instance_real_class_get (gpointer instance)
  * happen through functions supplied by the type's fundamental type
  * implementation.  So use of g_type_create_instance() is reserved for
  * implementators of fundamental types only. E.g. instances of the
- * #GObject hierarchy should be created via g_object_new() and
- * <emphasis>never</emphasis> directly through
- * g_type_create_instance() which doesn't handle things like singleton
- * objects or object construction.  Note: Do <emphasis>not</emphasis>
- * use this function, unless you're implementing a fundamental
- * type. Also language bindings should <emphasis>not</emphasis> use
- * this function but g_object_new() instead.
- *
- * Returns: An allocated and initialized instance, subject to further
- *  treatment by the fundamental type implementation.
+ * #GObject hierarchy should be created via g_object_new() and never
+ * directly through g_type_create_instance() which doesn't handle things
+ * like singleton objects or object construction.
+ *
+ * The extended members of the returned instance are guaranteed to be filled
+ * with zeros.
+ *
+ * Note: Do not use this function, unless you're implementing a
+ * fundamental type. Also language bindings should not use this
+ * function, but g_object_new() instead.
+ *
+ * Returns: an allocated and initialized instance, subject to further
+ *     treatment by the fundamental type implementation
  */
 GTypeInstance*
 g_type_create_instance (GType type)
@@ -1811,30 +1795,64 @@ g_type_create_instance (GType type)
   TypeNode *node;
   GTypeInstance *instance;
   GTypeClass *class;
-  guint i, total_size;
-  
+  gchar *allocated;
+  gint private_size;
+  gint ivar_size;
+  guint i;
+
   node = lookup_type_node_I (type);
   if (!node || !node->is_instantiatable)
     {
-      g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
+      g_error ("cannot create new instance of invalid (non-instantiatable) type '%s'",
                 type_descriptive_name_I (type));
-      return NULL;
     }
   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type))
     {
-      g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
+      g_error ("cannot create instance of abstract (non-instantiatable) type '%s'",
                 type_descriptive_name_I (type));
-      return NULL;
     }
   
   class = g_type_class_ref (type);
-  total_size = type_total_instance_size_I (node);
 
-  instance = g_slice_alloc0 (total_size);
+  /* We allocate the 'private' areas before the normal instance data, in
+   * reverse order.  This allows the private area of a particular class
+   * to always be at a constant relative address to the instance data.
+   * If we stored the private data after the instance data this would
+   * not be the case (since a subclass that added more instance
+   * variables would push the private data further along).
+   *
+   * This presents problems for valgrindability, of course, so we do a
+   * workaround for that case.  We identify the start of the object to
+   * valgrind as an allocated block (so that pointers to objects show up
+   * as 'reachable' instead of 'possibly lost').  We then add an extra
+   * pointer at the end of the object, after all instance data, back to
+   * the start of the private area so that it is also recorded as
+   * reachable.  We also add extra private space at the start because
+   * valgrind doesn't seem to like us claiming to have allocated an
+   * address that it saw allocated by malloc().
+   */
+  private_size = node->data->instance.private_size;
+  ivar_size = node->data->instance.instance_size;
+
+  if (private_size && RUNNING_ON_VALGRIND)
+    {
+      private_size += ALIGN_STRUCT (1);
+
+      /* Allocate one extra pointer size... */
+      allocated = g_slice_alloc0 (private_size + ivar_size + sizeof (gpointer));
+      /* ... and point it back to the start of the private data. */
+      *(gpointer *) (allocated + private_size + ivar_size) = allocated + ALIGN_STRUCT (1);
+
+      /* Tell valgrind that it should treat the object itself as such */
+      VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, ivar_size + sizeof (gpointer), 0, TRUE);
+      VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
+    }
+  else
+    allocated = g_slice_alloc0 (private_size + ivar_size);
+
+  instance = (GTypeInstance *) (allocated + private_size);
 
-  if (node->data->instance.private_size)
-    instance_real_class_set (instance, class);
   for (i = node->n_supers; i > 0; i--)
     {
       TypeNode *pnode;
@@ -1846,19 +1864,26 @@ g_type_create_instance (GType type)
          pnode->data->instance.instance_init (instance, class);
        }
     }
-  if (node->data->instance.private_size)
-    instance_real_class_remove (instance);
 
   instance->g_class = class;
   if (node->data->instance.instance_init)
     node->data->instance.instance_init (instance, class);
-  
+
+#ifdef G_ENABLE_DEBUG
+  IF_DEBUG (INSTANCE_COUNT)
+    {
+      g_atomic_int_inc ((int *) &node->instance_count);
+    }
+#endif
+
+  TRACE(GOBJECT_OBJECT_NEW(instance, type));
+
   return instance;
 }
 
 /**
  * g_type_free_instance:
- * @instance: an instance of a type.
+ * @instance: an instance of a type
  *
  * Frees an instance of a type, returning it to the instance pool for
  * the type, if there is one.
@@ -1871,30 +1896,62 @@ g_type_free_instance (GTypeInstance *instance)
 {
   TypeNode *node;
   GTypeClass *class;
-  
+  gchar *allocated;
+  gint private_size;
+  gint ivar_size;
+
   g_return_if_fail (instance != NULL && instance->g_class != NULL);
   
   class = instance->g_class;
   node = lookup_type_node_I (class->g_type);
   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
     {
-      g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
+      g_warning ("cannot free instance of invalid (non-instantiatable) type '%s'",
                 type_descriptive_name_I (class->g_type));
       return;
     }
   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
     {
-      g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
+      g_warning ("cannot free instance of abstract (non-instantiatable) type '%s'",
                 NODE_NAME (node));
       return;
     }
   
   instance->g_class = NULL;
-#ifdef G_ENABLE_DEBUG  
-  memset (instance, 0xaa, type_total_instance_size_I (node));
+  private_size = node->data->instance.private_size;
+  ivar_size = node->data->instance.instance_size;
+  allocated = ((gchar *) instance) - private_size;
+
+#ifdef G_ENABLE_DEBUG
+  memset (allocated, 0xaa, ivar_size + private_size);
+#endif
+
+  /* See comment in g_type_create_instance() about what's going on here.
+   * We're basically unwinding what we put into motion there.
+   */
+  if (private_size && RUNNING_ON_VALGRIND)
+    {
+      private_size += ALIGN_STRUCT (1);
+      allocated -= ALIGN_STRUCT (1);
+
+      /* Clear out the extra pointer... */
+      *(gpointer *) (allocated + private_size + ivar_size) = NULL;
+      /* ... and ensure we include it in the size we free. */
+      g_slice_free1 (private_size + ivar_size + sizeof (gpointer), allocated);
+
+      VALGRIND_FREELIKE_BLOCK (allocated + ALIGN_STRUCT (1), 0);
+      VALGRIND_FREELIKE_BLOCK (instance, 0);
+    }
+  else
+    g_slice_free1 (private_size + ivar_size, allocated);
+
+#ifdef G_ENABLE_DEBUG
+  IF_DEBUG (INSTANCE_COUNT)
+    {
+      g_atomic_int_add ((int *) &node->instance_count, -1);
+    }
 #endif
-  g_slice_free1 (type_total_instance_size_I (node), instance);
 
   g_type_class_unref (class);
 }
@@ -2065,12 +2122,17 @@ type_class_init_Wm (TypeNode   *node,
   TypeNode *bnode, *pnode;
   guint i;
   
+  /* Accessing data->class will work for instantiable types
+   * too because ClassData is a subset of InstanceData
+   */
   g_assert (node->is_classed && node->data &&
            node->data->class.class_size &&
            !node->data->class.class &&
            node->data->class.init_state == UNINITIALIZED);
-
-  class = g_malloc0 (node->data->class.class_size);
+  if (node->data->class.class_private_size)
+    class = g_malloc0 (ALIGN_STRUCT (node->data->class.class_size) + node->data->class.class_private_size);
+  else
+    class = g_malloc0 (node->data->class.class_size);
   node->data->class.class = class;
   g_atomic_int_set (&node->data->class.init_state, BASE_CLASS_INIT);
   
@@ -2079,6 +2141,7 @@ type_class_init_Wm (TypeNode   *node,
       TypeNode *pnode = lookup_type_node_I (pclass->g_type);
       
       memcpy (class, pclass, pnode->data->class.class_size);
+      memcpy (G_STRUCT_MEMBER_P (class, ALIGN_STRUCT (node->data->class.class_size)), G_STRUCT_MEMBER_P (pclass, ALIGN_STRUCT (pnode->data->class.class_size)), pnode->data->class.class_private_size);
 
       if (node->is_instantiatable)
        {
@@ -2271,7 +2334,7 @@ type_data_last_unref_Wm (TypeNode *node,
   
   if (!node->data || NODE_REFCOUNT (node) == 0)
     {
-      g_warning ("cannot drop last reference to unreferenced type `%s'",
+      g_warning ("cannot drop last reference to unreferenced type '%s'",
                 NODE_NAME (node));
       return;
     }
@@ -2370,25 +2433,33 @@ type_data_unref_U (TypeNode *node,
     {
       if (!node->plugin)
        {
-         g_warning ("static type `%s' unreferenced too often",
+         g_warning ("static type '%s' unreferenced too often",
                     NODE_NAME (node));
          return;
        }
+      else
+        {
+          /* This is the last reference of a type from a plugin.  We are
+           * experimentally disabling support for unloading type
+           * plugins, so don't allow the last ref to drop.
+           */
+          return;
+        }
 
       g_assert (current > 0);
 
-      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+      g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
       G_WRITE_LOCK (&type_rw_lock);
       type_data_last_unref_Wm (node, uncached);
       G_WRITE_UNLOCK (&type_rw_lock);
-      g_static_rec_mutex_unlock (&class_init_rec_mutex);
+      g_rec_mutex_unlock (&class_init_rec_mutex);
       return;
     }
   } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current - 1));
 }
 
 /**
- * g_type_add_class_cache_func:
+ * g_type_add_class_cache_func: (skip)
  * @cache_data: data to be passed to @cache_func
  * @cache_func: a #GTypeClassCacheFunc
  *
@@ -2417,7 +2488,7 @@ g_type_add_class_cache_func (gpointer            cache_data,
 }
 
 /**
- * g_type_remove_class_cache_func:
+ * g_type_remove_class_cache_func: (skip)
  * @cache_data: data that was given when adding @cache_func
  * @cache_func: a #GTypeClassCacheFunc
  *
@@ -2440,9 +2511,9 @@ g_type_remove_class_cache_func (gpointer            cache_data,
        static_class_cache_funcs[i].cache_func == cache_func)
       {
        static_n_class_cache_funcs--;
-       g_memmove (static_class_cache_funcs + i,
-                  static_class_cache_funcs + i + 1,
-                  sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
+       memmove (static_class_cache_funcs + i,
+                 static_class_cache_funcs + i + 1,
+                 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
        static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
        found_it = TRUE;
        break;
@@ -2456,17 +2527,17 @@ g_type_remove_class_cache_func (gpointer            cache_data,
 
 
 /**
- * g_type_add_interface_check:
+ * g_type_add_interface_check: (skip)
  * @check_data: data to pass to @check_func
  * @check_func: function to be called after each interface
- *              is initialized.
+ *     is initialized
  *
  * Adds a function to be called after an interface vtable is
- * initialized for any class (i.e. after the @interface_init member of
- * #GInterfaceInfo has been called).
+ * initialized for any class (i.e. after the @interface_init
+ * member of #GInterfaceInfo has been called).
  *
- * This function is useful when you want to check an invariant that
- * depends on the interfaces of a class. For instance, the
+ * This function is useful when you want to check an invariant
+ * that depends on the interfaces of a class. For instance, the
  * implementation of #GObject uses this facility to check that an
  * object implements all of the properties that are defined on its
  * interfaces.
@@ -2490,7 +2561,7 @@ g_type_add_interface_check (gpointer                  check_data,
 }
 
 /**
- * g_type_remove_interface_check:
+ * g_type_remove_interface_check: (skip)
  * @check_data: callback data passed to g_type_add_interface_check()
  * @check_func: callback function passed to g_type_add_interface_check()
  *
@@ -2514,9 +2585,9 @@ g_type_remove_interface_check (gpointer                check_data,
        static_iface_check_funcs[i].check_func == check_func)
       {
        static_n_iface_check_funcs--;
-       g_memmove (static_iface_check_funcs + i,
-                  static_iface_check_funcs + i + 1,
-                  sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
+       memmove (static_iface_check_funcs + i,
+                 static_iface_check_funcs + i + 1,
+                 sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
        static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
        found_it = TRUE;
        break;
@@ -2531,20 +2602,21 @@ g_type_remove_interface_check (gpointer                check_data,
 /* --- type registration --- */
 /**
  * g_type_register_fundamental:
- * @type_id: A predefined type identifier.
- * @type_name: 0-terminated string used as the name of the new type.
- * @info: The #GTypeInfo structure for this type.
- * @finfo: The #GTypeFundamentalInfo structure for this type.
- * @flags: Bitwise combination of #GTypeFlags values.
+ * @type_id: a predefined type identifier
+ * @type_name: 0-terminated string used as the name of the new type
+ * @info: #GTypeInfo structure for this type
+ * @finfo: #GTypeFundamentalInfo structure for this type
+ * @flags: bitwise combination of #GTypeFlags values
  *
  * Registers @type_id as the predefined identifier and @type_name as the
- * name of a fundamental type.  The type system uses the information
- * contained in the #GTypeInfo structure pointed to by @info and the
- * #GTypeFundamentalInfo structure pointed to by @finfo to manage the
- * type and its instances.  The value of @flags determines additional
- * characteristics of the fundamental type.
+ * name of a fundamental type. If @type_id is already registered, or a
+ * type named @type_name is already registered, the behaviour is undefined.
+ * The type system uses the information contained in the #GTypeInfo structure
+ * pointed to by @info and the #GTypeFundamentalInfo structure pointed to by
+ * @finfo to manage the type and its instances. The value of @flags determines
+ * additional characteristics of the fundamental type.
  *
- * Returns: The predefined type identifier.
+ * Returns: the predefined type identifier
  */
 GType
 g_type_register_fundamental (GType                       type_id,
@@ -2555,7 +2627,7 @@ g_type_register_fundamental (GType                       type_id,
 {
   TypeNode *node;
   
-  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_assert_type_system_initialized ();
   g_return_val_if_fail (type_id > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (info != NULL, 0);
@@ -2566,7 +2638,7 @@ g_type_register_fundamental (GType                       type_id,
   if ((type_id & TYPE_ID_MASK) ||
       type_id > G_TYPE_FUNDAMENTAL_MAX)
     {
-      g_warning ("attempt to register fundamental type `%s' with invalid type id (%" G_GSIZE_FORMAT ")",
+      g_warning ("attempt to register fundamental type '%s' with invalid type id (%" G_GSIZE_FORMAT ")",
                 type_name,
                 type_id);
       return 0;
@@ -2574,13 +2646,13 @@ g_type_register_fundamental (GType                       type_id,
   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
     {
-      g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
+      g_warning ("cannot register instantiatable fundamental type '%s' as non-classed",
                 type_name);
       return 0;
     }
   if (lookup_type_node_I (type_id))
     {
-      g_warning ("cannot register existing fundamental type `%s' (as `%s')",
+      g_warning ("cannot register existing fundamental type '%s' (as '%s')",
                 type_descriptive_name_I (type_id),
                 type_name);
       return 0;
@@ -2599,14 +2671,14 @@ g_type_register_fundamental (GType                       type_id,
 }
 
 /**
- * g_type_register_static_simple:
- * @parent_type: Type from which this type will be derived.
- * @type_name: 0-terminated string used as the name of the new type.
- * @class_size: Size of the class structure (see #GTypeInfo)
- * @class_init: Location of the class initialization function (see #GTypeInfo)
- * @instance_size: Size of the instance structure (see #GTypeInfo)
- * @instance_init: Location of the instance initialization function (see #GTypeInfo)
- * @flags: Bitwise combination of #GTypeFlags values.
+ * g_type_register_static_simple: (skip)
+ * @parent_type: type from which this type will be derived
+ * @type_name: 0-terminated string used as the name of the new type
+ * @class_size: size of the class structure (see #GTypeInfo)
+ * @class_init: location of the class initialization function (see #GTypeInfo)
+ * @instance_size: size of the instance structure (see #GTypeInfo)
+ * @instance_init: location of the instance initialization function (see #GTypeInfo)
+ * @flags: bitwise combination of #GTypeFlags values
  *
  * Registers @type_name as the name of a new static type derived from
  * @parent_type.  The value of @flags determines the nature (e.g.
@@ -2615,7 +2687,7 @@ g_type_register_fundamental (GType                       type_id,
  *
  * Since: 2.12
  *
- * Returns: The new type identifier.
+ * Returns: the new type identifier
  */
 GType
 g_type_register_static_simple (GType             parent_type,
@@ -2628,6 +2700,12 @@ g_type_register_static_simple (GType             parent_type,
 {
   GTypeInfo info;
 
+  /* Instances are not allowed to be larger than this. If you have a big
+   * fixed-length array or something, point to it instead.
+   */
+  g_return_val_if_fail (class_size <= G_MAXUINT16, G_TYPE_INVALID);
+  g_return_val_if_fail (instance_size <= G_MAXUINT16, G_TYPE_INVALID);
+
   info.class_size = class_size;
   info.base_init = NULL;
   info.base_finalize = NULL;
@@ -2644,18 +2722,18 @@ g_type_register_static_simple (GType             parent_type,
 
 /**
  * g_type_register_static:
- * @parent_type: Type from which this type will be derived.
- * @type_name: 0-terminated string used as the name of the new type.
- * @info: The #GTypeInfo structure for this type.
- * @flags: Bitwise combination of #GTypeFlags values.
+ * @parent_type: type from which this type will be derived
+ * @type_name: 0-terminated string used as the name of the new type
+ * @info: #GTypeInfo structure for this type
+ * @flags: bitwise combination of #GTypeFlags values
  *
  * Registers @type_name as the name of a new static type derived from
- * @parent_type.  The type system uses the information contained in the
+ * @parent_type. The type system uses the information contained in the
  * #GTypeInfo structure pointed to by @info to manage the type and its
- * instances (if not abstract).  The value of @flags determines the nature
+ * instances (if not abstract). The value of @flags determines the nature
  * (e.g. abstract or not) of the type.
  *
- * Returns: The new type identifier.
+ * Returns: the new type identifier
  */
 GType
 g_type_register_static (GType            parent_type,
@@ -2666,7 +2744,7 @@ g_type_register_static (GType            parent_type,
   TypeNode *pnode, *node;
   GType type = 0;
   
-  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_assert_type_system_initialized ();
   g_return_val_if_fail (parent_type > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (info != NULL, 0);
@@ -2676,7 +2754,7 @@ g_type_register_static (GType            parent_type,
     return 0;
   if (info->class_finalize)
     {
-      g_warning ("class finalizer specified for static type `%s'",
+      g_warning ("class finalizer specified for static type '%s'",
                 type_name);
       return 0;
     }
@@ -2699,10 +2777,10 @@ g_type_register_static (GType            parent_type,
 
 /**
  * g_type_register_dynamic:
- * @parent_type: Type from which this type will be derived.
- * @type_name: 0-terminated string used as the name of the new type.
- * @plugin: The #GTypePlugin structure to retrieve the #GTypeInfo from.
- * @flags: Bitwise combination of #GTypeFlags values.
+ * @parent_type: type from which this type will be derived
+ * @type_name: 0-terminated string used as the name of the new type
+ * @plugin: #GTypePlugin structure to retrieve the #GTypeInfo from
+ * @flags: bitwise combination of #GTypeFlags values
  *
  * Registers @type_name as the name of a new dynamic type derived from
  * @parent_type.  The type system uses the information contained in the
@@ -2710,7 +2788,7 @@ g_type_register_static (GType            parent_type,
  * instances (if not abstract).  The value of @flags determines the nature
  * (e.g. abstract or not) of the type.
  *
- * Returns: The new type identifier or #G_TYPE_INVALID if registration failed.
+ * Returns: the new type identifier or #G_TYPE_INVALID if registration failed
  */
 GType
 g_type_register_dynamic (GType        parent_type,
@@ -2721,7 +2799,7 @@ g_type_register_dynamic (GType        parent_type,
   TypeNode *pnode, *node;
   GType type;
   
-  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_assert_type_system_initialized ();
   g_return_val_if_fail (parent_type > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (plugin != NULL, 0);
@@ -2743,14 +2821,14 @@ g_type_register_dynamic (GType        parent_type,
 
 /**
  * g_type_add_interface_static:
- * @instance_type: #GType value of an instantiable type.
- * @interface_type: #GType value of an interface type.
- * @info: The #GInterfaceInfo structure for this
- *        (@instance_type, @interface_type) combination.
+ * @instance_type: #GType value of an instantiable type
+ * @interface_type: #GType value of an interface type
+ * @info: #GInterfaceInfo structure for this
+ *        (@instance_type, @interface_type) combination
  *
- * Adds the static @interface_type to @instantiable_type.  The information
- * contained in the #GTypeInterfaceInfo structure pointed to by @info
- * is used to manage the relationship.
+ * Adds the static @interface_type to @instantiable_type.
+ * The information contained in the #GInterfaceInfo structure
+ * pointed to by @info is used to manage the relationship.
  */
 void
 g_type_add_interface_static (GType                 instance_type,
@@ -2765,7 +2843,7 @@ g_type_add_interface_static (GType                 instance_type,
    * class initialized, however this function is rarely enough called to take
    * the simple route and always acquire class_init_rec_mutex.
    */
-  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+  g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   G_WRITE_LOCK (&type_rw_lock);
   if (check_add_interface_L (instance_type, interface_type))
     {
@@ -2775,14 +2853,14 @@ g_type_add_interface_static (GType                 instance_type,
         type_add_interface_Wm (node, iface, info, NULL);
     }
   G_WRITE_UNLOCK (&type_rw_lock);
-  g_static_rec_mutex_unlock (&class_init_rec_mutex);
+  g_rec_mutex_unlock (&class_init_rec_mutex);
 }
 
 /**
  * g_type_add_interface_dynamic:
- * @instance_type: the #GType value of an instantiable type.
- * @interface_type: the #GType value of an interface type.
- * @plugin: the #GTypePlugin structure to retrieve the #GInterfaceInfo from.
+ * @instance_type: #GType value of an instantiable type
+ * @interface_type: #GType value of an interface type
+ * @plugin: #GTypePlugin structure to retrieve the #GInterfaceInfo from
  *
  * Adds the dynamic @interface_type to @instantiable_type. The information
  * contained in the #GTypePlugin structure pointed to by @plugin
@@ -2803,7 +2881,7 @@ g_type_add_interface_dynamic (GType        instance_type,
     return;
 
   /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
-  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+  g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   G_WRITE_LOCK (&type_rw_lock);
   if (check_add_interface_L (instance_type, interface_type))
     {
@@ -2811,20 +2889,21 @@ g_type_add_interface_dynamic (GType        instance_type,
       type_add_interface_Wm (node, iface, NULL, plugin);
     }
   G_WRITE_UNLOCK (&type_rw_lock);
-  g_static_rec_mutex_unlock (&class_init_rec_mutex);
+  g_rec_mutex_unlock (&class_init_rec_mutex);
 }
 
 
 /* --- public API functions --- */
 /**
  * g_type_class_ref:
- * @type: Type ID of a classed type.
+ * @type: type ID of a classed type
  *
  * Increments the reference count of the class structure belonging to
  * @type. This function will demand-create the class if it doesn't
  * exist already.
  *
- * Returns: The #GTypeClass structure for the given type ID.
+ * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
+ *     structure for the given type ID
  */
 gpointer
 g_type_class_ref (GType type)
@@ -2838,7 +2917,7 @@ g_type_class_ref (GType type)
   node = lookup_type_node_I (type);
   if (!node || !node->is_classed)
     {
-      g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
+      g_warning ("cannot retrieve class for invalid (unclassed) type '%s'",
                 type_descriptive_name_I (type));
       return NULL;
     }
@@ -2857,7 +2936,7 @@ g_type_class_ref (GType type)
    * node->data->class.init_state == INITIALIZED, because any
    * concurrently running initialization was guarded by class_init_rec_mutex.
    */
-  g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+  g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
 
   /* we need an initialized parent class for initializing derived classes */
   ptype = NODE_PARENT_TYPE (node);
@@ -2876,14 +2955,14 @@ g_type_class_ref (GType type)
   if (pclass)
     g_type_class_unref (pclass);
 
-  g_static_rec_mutex_unlock (&class_init_rec_mutex);
+  g_rec_mutex_unlock (&class_init_rec_mutex);
 
   return node->data->class.class;
 }
 
 /**
  * g_type_class_unref:
- * @g_class: The #GTypeClass structure to unreference.
+ * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
  *
  * Decrements the reference count of the class structure being passed in.
  * Once the last reference count of a class has been released, classes
@@ -2902,17 +2981,17 @@ g_type_class_unref (gpointer g_class)
   if (node && node->is_classed && NODE_REFCOUNT (node))
     type_data_unref_U (node, FALSE);
   else
-    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
+    g_warning ("cannot unreference class of invalid (unclassed) type '%s'",
               type_descriptive_name_I (class->g_type));
 }
 
 /**
- * g_type_class_unref_uncached:
- * @g_class: The #GTypeClass structure to unreference.
+ * g_type_class_unref_uncached: (skip)
+ * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
  *
  * A variant of g_type_class_unref() for use in #GTypeClassCacheFunc
  * implementations. It unreferences a class without consulting the chain
- * of #GTypeClassCacheFunc<!-- -->s, avoiding the recursion which would occur
+ * of #GTypeClassCacheFuncs, avoiding the recursion which would occur
  * otherwise.
  */
 void
@@ -2927,21 +3006,23 @@ g_type_class_unref_uncached (gpointer g_class)
   if (node && node->is_classed && NODE_REFCOUNT (node))
     type_data_unref_U (node, TRUE);
   else
-    g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
+    g_warning ("cannot unreference class of invalid (unclassed) type '%s'",
               type_descriptive_name_I (class->g_type));
 }
 
 /**
  * g_type_class_peek:
- * @type: Type ID of a classed type.
+ * @type: type ID of a classed type
  *
- * This function is essentially the same as g_type_class_ref(), except that
- * the classes reference count isn't incremented. As a consequence, this function
- * may return %NULL if the class of the type passed in does not currently
- * exist (hasn't been referenced before).
+ * This function is essentially the same as g_type_class_ref(),
+ * except that the classes reference count isn't incremented.
+ * As a consequence, this function may return %NULL if the class
+ * of the type passed in does not currently exist (hasn't been
+ * referenced before).
  *
- * Returns: The #GTypeClass structure for the given type ID or %NULL
- *  if the class does not currently exist.
+ * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
+ *     structure for the given type ID or %NULL if the class does not
+ *     currently exist
  */
 gpointer
 g_type_class_peek (GType type)
@@ -2950,28 +3031,28 @@ g_type_class_peek (GType type)
   gpointer class;
   
   node = lookup_type_node_I (type);
-  G_READ_LOCK (&type_rw_lock);
-  if (node && node->is_classed && node->data &&
+  if (node && node->is_classed && NODE_REFCOUNT (node) &&
       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
     /* ref_count _may_ be 0 */
     class = node->data->class.class;
   else
     class = NULL;
-  G_READ_UNLOCK (&type_rw_lock);
   
   return class;
 }
 
 /**
  * g_type_class_peek_static:
- * @type: Type ID of a classed type.
+ * @type: type ID of a classed type
  *
  * A more efficient version of g_type_class_peek() which works only for
  * static types.
  * 
+ * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
+ *     structure for the given type ID or %NULL if the class does not
+ *     currently exist or is dynamically loaded
+ *
  * Since: 2.4
- * Returns: The #GTypeClass structure for the given type ID or %NULL
- *  if the class does not currently exist or is dynamically loaded.
  */
 gpointer
 g_type_class_peek_static (GType type)
@@ -2980,35 +3061,33 @@ g_type_class_peek_static (GType type)
   gpointer class;
   
   node = lookup_type_node_I (type);
-  G_READ_LOCK (&type_rw_lock);
-  if (node && node->is_classed && node->data &&
+  if (node && node->is_classed && NODE_REFCOUNT (node) &&
       /* peek only static types: */ node->plugin == NULL &&
       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
     /* ref_count _may_ be 0 */
     class = node->data->class.class;
   else
     class = NULL;
-  G_READ_UNLOCK (&type_rw_lock);
   
   return class;
 }
 
 /**
  * g_type_class_peek_parent:
- * @g_class: The #GTypeClass structure to retrieve the parent class for.
+ * @g_class: (type GObject.TypeClass): the #GTypeClass structure to
+ *     retrieve the parent class for
  *
  * This is a convenience function often needed in class initializers.
  * It returns the class structure of the immediate parent type of the
  * class passed in.  Since derived classes hold a reference count on
  * their parent classes as long as they are instantiated, the returned
- * class will always exist. This function is essentially equivalent
- * to:
+ * class will always exist.
  *
- * <programlisting>
- * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)));
- * </programlisting>
+ * This function is essentially equivalent to:
+ * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)))
  *
- * Returns: The parent class of @g_class.
+ * Returns: (type GObject.TypeClass) (transfer none): the parent class
+ *     of @g_class
  */
 gpointer
 g_type_class_peek_parent (gpointer g_class)
@@ -3029,21 +3108,22 @@ g_type_class_peek_parent (gpointer g_class)
       class = node->data->class.class;
     }
   else if (NODE_PARENT_TYPE (node))
-    g_warning (G_STRLOC ": invalid class pointer `%p'", g_class);
+    g_warning (G_STRLOC ": invalid class pointer '%p'", g_class);
   
   return class;
 }
 
 /**
  * g_type_interface_peek:
- * @instance_class: A #GTypeClass structure.
- * @iface_type: An interface ID which this class conforms to.
+ * @instance_class: (type GObject.TypeClass): a #GTypeClass structure
+ * @iface_type: an interface ID which this class conforms to
  *
  * Returns the #GTypeInterface structure of an interface to which the
  * passed in class conforms.
  *
- * Returns: The GTypeInterface structure of iface_type if implemented
- *          by @instance_class, %NULL otherwise
+ * Returns: (type GObject.TypeInterface) (transfer none): the #GTypeInterface
+ *     structure of @iface_type if implemented by @instance_class, %NULL
+ *     otherwise
  */
 gpointer
 g_type_interface_peek (gpointer instance_class,
@@ -3061,23 +3141,24 @@ g_type_interface_peek (gpointer instance_class,
   if (node && node->is_instantiatable && iface)
     type_lookup_iface_vtable_I (node, iface, &vtable);
   else
-    g_warning (G_STRLOC ": invalid class pointer `%p'", class);
+    g_warning (G_STRLOC ": invalid class pointer '%p'", class);
   
   return vtable;
 }
 
 /**
  * g_type_interface_peek_parent:
- * @g_iface: A #GTypeInterface structure.
+ * @g_iface: (type GObject.TypeInterface): a #GTypeInterface structure
  *
  * Returns the corresponding #GTypeInterface structure of the parent type
  * of the instance type to which @g_iface belongs. This is useful when
  * deriving the implementation of an interface from the parent type and
  * then possibly overriding some methods.
  *
- * Returns: The corresponding #GTypeInterface structure of the parent
- *          type of the instance type to which @g_iface belongs, or
- *          %NULL if the parent type doesn't conform to the interface.
+ * Returns: (transfer none) (type GObject.TypeInterface): the
+ *     corresponding #GTypeInterface structure of the parent type of the
+ *     instance type to which @g_iface belongs, or %NULL if the parent
+ *     type doesn't conform to the interface
  */
 gpointer
 g_type_interface_peek_parent (gpointer g_iface)
@@ -3096,7 +3177,7 @@ g_type_interface_peek_parent (gpointer g_iface)
   if (node && node->is_instantiatable && iface)
     type_lookup_iface_vtable_I (node, iface, &vtable);
   else if (node)
-    g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface);
+    g_warning (G_STRLOC ": invalid interface pointer '%p'", g_iface);
   
   return vtable;
 }
@@ -3111,17 +3192,16 @@ g_type_interface_peek_parent (gpointer g_iface)
  * If the type is not currently in use, then the default vtable
  * for the type will be created and initalized by calling
  * the base interface init and default vtable init functions for
- * the type (the @<structfield>base_init</structfield>
- * and <structfield>class_init</structfield> members of #GTypeInfo).
+ * the type (the @base_init and @class_init members of #GTypeInfo).
  * Calling g_type_default_interface_ref() is useful when you
  * want to make sure that signals and properties for an interface
  * have been installed.
  *
  * Since: 2.4
  *
- * Returns: the default vtable for the interface; call
- *          g_type_default_interface_unref() when you are done using
- *          the interface.
+ * Returns: (type GObject.TypeInterface) (transfer none): the default
+ *     vtable for the interface; call g_type_default_interface_unref()
+ *     when you are done using the interface.
  */
 gpointer
 g_type_default_interface_ref (GType g_type)
@@ -3144,12 +3224,12 @@ g_type_default_interface_ref (GType g_type)
   if (!node->data || !node->data->iface.dflt_vtable)
     {
       G_WRITE_UNLOCK (&type_rw_lock);
-      g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
+      g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
       G_WRITE_LOCK (&type_rw_lock);
       node = lookup_type_node_I (g_type);
       type_data_ref_Wm (node);
       type_iface_ensure_dflt_vtable_Wm (node);
-      g_static_rec_mutex_unlock (&class_init_rec_mutex);
+      g_rec_mutex_unlock (&class_init_rec_mutex);
     }
   else
     type_data_ref_Wm (node); /* ref_count >= 1 already */
@@ -3169,8 +3249,9 @@ g_type_default_interface_ref (GType g_type)
  *
  * Since: 2.4
  *
- * Returns: the default vtable for the interface, or %NULL
- *          if the type is not currently in use.
+ * Returns: (type GObject.TypeInterface) (transfer none): the default
+ *     vtable for the interface, or %NULL if the type is not currently
+ *     in use
  */
 gpointer
 g_type_default_interface_peek (GType g_type)
@@ -3179,27 +3260,24 @@ g_type_default_interface_peek (GType g_type)
   gpointer vtable;
   
   node = lookup_type_node_I (g_type);
-  G_READ_LOCK (&type_rw_lock);
-  if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable)
+  if (node && NODE_IS_IFACE (node) && NODE_REFCOUNT (node))
     vtable = node->data->iface.dflt_vtable;
   else
     vtable = NULL;
-  G_READ_UNLOCK (&type_rw_lock);
   
   return vtable;
 }
 
 /**
  * g_type_default_interface_unref:
- * @g_iface: the default vtable structure for a interface, as
- *           returned by g_type_default_interface_ref()
+ * @g_iface: (type GObject.TypeInterface): the default vtable
+ *     structure for a interface, as returned by g_type_default_interface_ref()
  *
  * Decrements the reference count for the type corresponding to the
  * interface default vtable @g_iface. If the type is dynamic, then
  * when no one is using the interface and all references have
  * been released, the finalize function for the interface's default
- * vtable (the <structfield>class_finalize</structfield> member of
- * #GTypeInfo) will be called.
+ * vtable (the @class_finalize member of #GTypeInfo) will be called.
  *
  * Since: 2.4
  */
@@ -3221,7 +3299,7 @@ g_type_default_interface_unref (gpointer g_iface)
 
 /**
  * g_type_name:
- * @type: Type to return name for.
+ * @type: type to return name for
  *
  * Get the unique name that is assigned to a type ID.  Note that this
  * function (like all other GType API) cannot cope with invalid type
@@ -3229,14 +3307,14 @@ g_type_default_interface_unref (gpointer g_iface)
  * other validly registered type ID, but randomized type IDs should
  * not be passed in and will most likely lead to a crash.
  *
- * Returns: Static type name or %NULL.
+ * Returns: static type name or %NULL
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_type_name (GType type)
 {
   TypeNode *node;
   
-  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, NULL);
+  g_assert_type_system_initialized ();
   
   node = lookup_type_node_I (type);
   
@@ -3245,11 +3323,11 @@ g_type_name (GType type)
 
 /**
  * g_type_qname:
- * @type: Type to return quark of type name for.
+ * @type: type to return quark of type name for
  *
  * Get the corresponding quark of the type IDs name.
  *
- * Returns: The type names quark or 0.
+ * Returns: the type names quark or 0
  */
 GQuark
 g_type_qname (GType type)
@@ -3263,42 +3341,37 @@ g_type_qname (GType type)
 
 /**
  * g_type_from_name:
- * @name: Type name to lookup.
+ * @name: type name to lookup
  *
  * Lookup the type ID from a given type name, returning 0 if no type
  * has been registered under this name (this is the preferred method
  * to find out by name whether a specific type has been registered
  * yet).
  *
- * Returns: Corresponding type ID or 0.
+ * Returns: corresponding type ID or 0
  */
 GType
 g_type_from_name (const gchar *name)
 {
   GType type = 0;
-  GQuark quark;
   
   g_return_val_if_fail (name != NULL, 0);
   
-  quark = g_quark_try_string (name);
-  if (quark)
-    {
-      G_READ_LOCK (&type_rw_lock);
-      type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));
-      G_READ_UNLOCK (&type_rw_lock);
-    }
+  G_READ_LOCK (&type_rw_lock);
+  type = (GType) g_hash_table_lookup (static_type_nodes_ht, name);
+  G_READ_UNLOCK (&type_rw_lock);
   
   return type;
 }
 
 /**
  * g_type_parent:
- * @type: The derived type.
+ * @type: the derived type
  *
- * Return the direct parent type of the passed in type.  If the passed
+ * Return the direct parent type of the passed in type. If the passed
  * in type has no parent, i.e. is a fundamental type, 0 is returned.
  *
- * Returns: The parent type.
+ * Returns: the parent type
  */
 GType
 g_type_parent (GType type)
@@ -3312,12 +3385,12 @@ g_type_parent (GType type)
 
 /**
  * g_type_depth:
- * @type: A #GType value.
+ * @type: a #GType
  *
  * Returns the length of the ancestry of the passed in type. This
  * includes the type itself, so that e.g. a fundamental type has depth 1.
  *
- * Returns: The depth of @type.
+ * Returns: the depth of @type
  */
 guint
 g_type_depth (GType type)
@@ -3331,18 +3404,18 @@ g_type_depth (GType type)
 
 /**
  * g_type_next_base:
- * @leaf_type: Descendant of @root_type and the type to be returned.
- * @root_type: Immediate parent of the returned type.
+ * @leaf_type: descendant of @root_type and the type to be returned
+ * @root_type: immediate parent of the returned type
  *
  * Given a @leaf_type and a @root_type which is contained in its
  * anchestry, return the type that @root_type is the immediate parent
- * of.  In other words, this function determines the type that is
+ * of. In other words, this function determines the type that is
  * derived directly from @root_type which is also a base class of
  * @leaf_type.  Given a root type and a leaf type, this function can
  * be used to determine the types and order in which the leaf type is
  * descended from the root type.
  *
- * Returns: Immediate child of @root_type and anchestor of @leaf_type.
+ * Returns: immediate child of @root_type and anchestor of @leaf_type
  */
 GType
 g_type_next_base (GType type,
@@ -3429,14 +3502,15 @@ type_node_conforms_to_U (TypeNode *node,
 
 /**
  * g_type_is_a:
- * @type: Type to check anchestry for.
- * @is_a_type: Possible anchestor of @type or interface @type could conform to.
+ * @type: type to check anchestry for
+ * @is_a_type: possible anchestor of @type or interface that @type
+ *     could conform to
  *
  * If @is_a_type is a derivable type, check whether @type is a
- * descendant of @is_a_type.  If @is_a_type is an interface, check
+ * descendant of @is_a_type. If @is_a_type is an interface, check
  * whether @type conforms to it.
  *
- * Returns: %TRUE if @type is_a @is_a_type holds true.
+ * Returns: %TRUE if @type is a @is_a_type
  */
 gboolean
 g_type_is_a (GType type,
@@ -3444,6 +3518,9 @@ g_type_is_a (GType type,
 {
   TypeNode *node, *iface_node;
   gboolean is_a;
+
+  if (type == iface_type)
+    return TRUE;
   
   node = lookup_type_node_I (type);
   iface_node = lookup_type_node_I (iface_type);
@@ -3454,13 +3531,15 @@ g_type_is_a (GType type,
 
 /**
  * g_type_children:
- * @type: The parent type.
- * @n_children: Optional #guint pointer to contain the number of child types.
+ * @type: the parent type
+ * @n_children: (out) (allow-none): location to store the length of
+ *     the returned array, or %NULL
  *
- * Return a newly allocated and 0-terminated array of type IDs, listing the
- * child types of @type. The return value has to be g_free()ed after use.
+ * Return a newly allocated and 0-terminated array of type IDs, listing
+ * the child types of @type.
  *
- * Returns: Newly allocated and 0-terminated array of child types.
+ * Returns: (array length=n_children) (transfer full): Newly allocated
+ *     and 0-terminated array of child types, free with g_free()
  */
 GType*
 g_type_children (GType  type,
@@ -3495,15 +3574,15 @@ g_type_children (GType  type,
 
 /**
  * g_type_interfaces:
- * @type: The type to list interface types for.
- * @n_interfaces: Optional #guint pointer to contain the number of
- *                interface types.
+ * @type: the type to list interface types for
+ * @n_interfaces: (out) (allow-none): location to store the length of
+ *     the returned array, or %NULL
  *
- * Return a newly allocated and 0-terminated array of type IDs, listing the
- * interface types that @type conforms to. The return value has to be
- * g_free()ed after use.
+ * Return a newly allocated and 0-terminated array of type IDs, listing
+ * the interface types that @type conforms to.
  *
- * Returns: Newly allocated and 0-terminated array of interface types.
+ * Returns: (array length=n_interfaces) (transfer full): Newly allocated
+ *     and 0-terminated array of interface types, free with g_free()
  */
 GType*
 g_type_interfaces (GType  type,
@@ -3601,7 +3680,11 @@ type_get_qdata_L (TypeNode *node,
  * Obtains data which has previously been attached to @type
  * with g_type_set_qdata().
  *
- * Returns: the data, or %NULL if no data was found
+ * Note that this does not take subtyping into account; data
+ * attached to one type with g_type_set_qdata() cannot
+ * be retrieved from a subtype using g_type_get_qdata().
+ *
+ * Returns: (transfer none): the data, or %NULL if no data was found
  */
 gpointer
 g_type_get_qdata (GType  type,
@@ -3655,7 +3738,7 @@ type_set_qdata_W (TypeNode *node,
   for (i = 0; i < gdata->n_qdatas - 1; i++)
     if (qdata[i].quark > quark)
       break;
-  g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
+  memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
   qdata[i].quark = quark;
   qdata[i].data = data;
 }
@@ -3698,7 +3781,7 @@ type_add_flags_W (TypeNode  *node,
   g_return_if_fail (node != NULL);
   
   if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
-    g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
+    g_warning ("tagging type '%s' as abstract after class initialization", NODE_NAME (node));
   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
   dflags |= flags;
   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
@@ -3706,9 +3789,9 @@ type_add_flags_W (TypeNode  *node,
 
 /**
  * g_type_query:
- * @type: the #GType value of a static, classed type.
- * @query: A user provided structure that is filled in with constant values
- *  upon success.
+ * @type: #GType of a static, classed type
+ * @query: (out caller-allocates): a user provided structure that is
+ *     filled in with constant values upon success
  *
  * Queries the type system for information about a specific type.
  * This function will fill in a user-provided structure to hold
@@ -3743,6 +3826,34 @@ g_type_query (GType       type,
     }
 }
 
+/**
+ * g_type_get_instance_count:
+ * @type: a #GType
+ *
+ * Returns the number of instances allocated of the particular type;
+ * this is only available if GLib is built with debugging support and
+ * the instance_count debug flag is set (by setting the GOBJECT_DEBUG
+ * variable to include instance-count).
+ *
+ * Returns: the number of instances allocated of the given type;
+ *   if instance counts are not available, returns 0.
+ *
+ * Since: 2.44
+ */
+int
+g_type_get_instance_count (GType type)
+{
+#ifdef G_ENABLE_DEBUG
+  TypeNode *node;
+
+  node = lookup_type_node_I (type);
+  g_return_val_if_fail (node != NULL, 0);
+
+  return g_atomic_int_get (&node->instance_count);
+#else
+  return 0;
+#endif
+}
 
 /* --- implementation details --- */
 gboolean
@@ -3784,13 +3895,12 @@ g_type_test_flags (GType type,
 
 /**
  * g_type_get_plugin:
- * @type: The #GType to retrieve the plugin for.
+ * @type: #GType to retrieve the plugin for
  *
- * Returns the #GTypePlugin structure for @type or
- * %NULL if @type does not have a #GTypePlugin structure.
+ * Returns the #GTypePlugin structure for @type.
  *
- * Returns: The corresponding plugin if @type is a dynamic type,
- *  %NULL otherwise.
+ * Returns: (transfer none): the corresponding plugin
+ *     if @type is a dynamic type, %NULL otherwise
  */
 GTypePlugin*
 g_type_get_plugin (GType type)
@@ -3804,16 +3914,16 @@ g_type_get_plugin (GType type)
 
 /**
  * g_type_interface_get_plugin:
- * @instance_type: the #GType value of an instantiatable type.
- * @interface_type: the #GType value of an interface type.
+ * @instance_type: #GType of an instantiatable type
+ * @interface_type: #GType of an interface type
  *
  * Returns the #GTypePlugin structure for the dynamic interface
- * @interface_type which has been added to @instance_type, or %NULL if
- * @interface_type has not been added to @instance_type or does not
- * have a #GTypePlugin structure. See g_type_add_interface_dynamic().
+ * @interface_type which has been added to @instance_type, or %NULL
+ * if @interface_type has not been added to @instance_type or does
+ * not have a #GTypePlugin structure. See g_type_add_interface_dynamic().
  *
- * Returns: the #GTypePlugin for the dynamic interface @interface_type
- *  of @instance_type.
+ * Returns: (transfer none): the #GTypePlugin for the dynamic
+ *     interface @interface_type of @instance_type
  */
 GTypePlugin*
 g_type_interface_get_plugin (GType instance_type,
@@ -3859,8 +3969,8 @@ g_type_interface_get_plugin (GType instance_type,
  * The returned type ID represents the highest currently registered
  * fundamental type identifier.
  *
- * Returns: The nextmost fundamental type ID to be registered,
- *          or 0 if the type system ran out of fundamental type IDs.
+ * Returns: the next available fundamental type ID to be registered,
+ *     or 0 if the type system ran out of fundamental type IDs
  */
 GType
 g_type_fundamental_next (void)
@@ -3879,7 +3989,7 @@ g_type_fundamental_next (void)
  * @type_id: valid type ID
  * 
  * Internal function, used to extract the fundamental type ID portion.
- * use G_TYPE_FUNDAMENTAL() instead.
+ * Use G_TYPE_FUNDAMENTAL() instead.
  * 
  * Returns: fundamental type ID
  */
@@ -3909,6 +4019,17 @@ g_type_check_instance_is_a (GTypeInstance *type_instance,
 }
 
 gboolean
+g_type_check_instance_is_fundamentally_a (GTypeInstance *type_instance,
+                                          GType          fundamental_type)
+{
+  TypeNode *node;
+  if (!type_instance || !type_instance->g_class)
+    return FALSE;
+  node = lookup_type_node_I (type_instance->g_class->g_type);
+  return node && (NODE_FUNDAMENTAL_TYPE(node) == fundamental_type);
+}
+
+gboolean
 g_type_check_class_is_a (GTypeClass *type_class,
                         GType       is_a_type)
 {
@@ -3944,16 +4065,16 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
            return type_instance;
          
          if (is_instantiatable)
-           g_warning ("invalid cast from `%s' to `%s'",
+           g_warning ("invalid cast from '%s' to '%s'",
                       type_descriptive_name_I (type_instance->g_class->g_type),
                       type_descriptive_name_I (iface_type));
          else
-           g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
+           g_warning ("invalid uninstantiatable type '%s' in cast to '%s'",
                       type_descriptive_name_I (type_instance->g_class->g_type),
                       type_descriptive_name_I (iface_type));
        }
       else
-       g_warning ("invalid unclassed pointer in cast to `%s'",
+       g_warning ("invalid unclassed pointer in cast to '%s'",
                   type_descriptive_name_I (iface_type));
     }
   
@@ -3977,28 +4098,28 @@ g_type_check_class_cast (GTypeClass *type_class,
        return type_class;
       
       if (is_classed)
-       g_warning ("invalid class cast from `%s' to `%s'",
+       g_warning ("invalid class cast from '%s' to '%s'",
                   type_descriptive_name_I (type_class->g_type),
                   type_descriptive_name_I (is_a_type));
       else
-       g_warning ("invalid unclassed type `%s' in class cast to `%s'",
+       g_warning ("invalid unclassed type '%s' in class cast to '%s'",
                   type_descriptive_name_I (type_class->g_type),
                   type_descriptive_name_I (is_a_type));
     }
   else
-    g_warning ("invalid class cast from (NULL) pointer to `%s'",
+    g_warning ("invalid class cast from (NULL) pointer to '%s'",
               type_descriptive_name_I (is_a_type));
   return type_class;
 }
 
 /**
  * g_type_check_instance:
- * @instance: A valid #GTypeInstance structure.
+ * @instance: a valid #GTypeInstance structure
  *
- * Private helper function to aid implementation of the G_TYPE_CHECK_INSTANCE()
- * macro.
+ * Private helper function to aid implementation of the
+ * G_TYPE_CHECK_INSTANCE() macro.
  *
- * @Returns:  #TRUE if @instance is valid, #FALSE otherwise.
+ * Returns: %TRUE if @instance is valid, %FALSE otherwise
  */
 gboolean
 g_type_check_instance (GTypeInstance *type_instance)
@@ -4015,7 +4136,7 @@ g_type_check_instance (GTypeInstance *type_instance)
          if (node && node->is_instantiatable)
            return TRUE;
          
-         g_warning ("instance of invalid non-instantiatable type `%s'",
+         g_warning ("instance of invalid non-instantiatable type '%s'",
                     type_descriptive_name_I (type_instance->g_class->g_type));
        }
       else
@@ -4088,16 +4209,17 @@ g_type_check_value_holds (GValue *value,
 }
 
 /**
- * g_type_value_table_peek:
- * @type: A #GType value.
+ * g_type_value_table_peek: (skip)
+ * @type: a #GType
  *
  * Returns the location of the #GTypeValueTable associated with @type.
- * <emphasis>Note that this function should only be used from source code
+ *
+ * Note that this function should only be used from source code
  * that implements or has internal knowledge of the implementation of
- * @type.</emphasis>
+ * @type.
  *
- * Returns: Location of the #GTypeValueTable associated with @type or
- *  %NULL if there is no #GTypeValueTable associated with @type.
+ * Returns: location of the #GTypeValueTable associated with @type or
+ *     %NULL if there is no #GTypeValueTable associated with @type
  */
 GTypeValueTable*
 g_type_value_table_peek (GType type)
@@ -4105,14 +4227,9 @@ g_type_value_table_peek (GType type)
   GTypeValueTable *vtable = NULL;
   TypeNode *node = lookup_type_node_I (type);
   gboolean has_refed_data, has_table;
-  TypeData *data;
 
-  /* speed up common code path, we're not 100% safe here,
-   * but we should only get called with referenced types anyway
-   */
-  data = node ? node->data : NULL;
-  if (node && node->mutatable_check_cache)
-    return data->common.value_table;
+  if (node && NODE_REFCOUNT (node) && node->mutatable_check_cache)
+    return node->data->common.value_table;
 
   G_READ_LOCK (&type_rw_lock);
   
@@ -4148,15 +4265,15 @@ g_type_value_table_peek (GType type)
     return vtable;
   
   if (!node)
-    g_warning (G_STRLOC ": type id `%" G_GSIZE_FORMAT "' is invalid", type);
+    g_warning (G_STRLOC ": type id '%" G_GSIZE_FORMAT "' is invalid", type);
   if (!has_refed_data)
-    g_warning ("can't peek value table for type `%s' which is not currently referenced",
+    g_warning ("can't peek value table for type '%s' which is not currently referenced",
               type_descriptive_name_I (type));
   
   return NULL;
 }
 
-G_CONST_RETURN gchar*
+const gchar *
 g_type_name_from_instance (GTypeInstance *instance)
 {
   if (!instance)
@@ -4165,7 +4282,7 @@ g_type_name_from_instance (GTypeInstance *instance)
     return g_type_name_from_class (instance->g_class);
 }
 
-G_CONST_RETURN gchar*
+const gchar *
 g_type_name_from_class (GTypeClass *g_class)
 {
   if (!g_class)
@@ -4175,48 +4292,103 @@ g_type_name_from_class (GTypeClass *g_class)
 }
 
 
+/* --- private api for gboxed.c --- */
+gpointer
+_g_type_boxed_copy (GType type, gpointer value)
+{
+  TypeNode *node = lookup_type_node_I (type);
+
+  return node->data->boxed.copy_func (value);
+}
+
+void
+_g_type_boxed_free (GType type, gpointer value)
+{
+  TypeNode *node = lookup_type_node_I (type);
+
+  node->data->boxed.free_func (value);
+}
+
+void
+_g_type_boxed_init (GType          type,
+                    GBoxedCopyFunc copy_func,
+                    GBoxedFreeFunc free_func)
+{
+  TypeNode *node = lookup_type_node_I (type);
+
+  node->data->boxed.copy_func = copy_func;
+  node->data->boxed.free_func = free_func;
+}
+
 /* --- initialization --- */
 /**
  * g_type_init_with_debug_flags:
- * @debug_flags: Bitwise combination of #GTypeDebugFlags values for
- *               debugging purposes.
+ * @debug_flags: bitwise combination of #GTypeDebugFlags values for
+ *     debugging purposes
+ *
+ * This function used to initialise the type system with debugging
+ * flags.  Since GLib 2.36, the type system is initialised automatically
+ * and this function does nothing.
  *
- * Similar to g_type_init(), but additionally sets debug flags.
+ * If you need to enable debugging features, use the GOBJECT_DEBUG
+ * environment variable.
+ *
+ * Deprecated: 2.36: the type system is now initialised automatically
  */
 void
 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
 {
-  G_LOCK_DEFINE_STATIC (type_init_lock);
+  g_assert_type_system_initialized ();
+
+  if (debug_flags)
+    g_message ("g_type_init_with_debug_flags() is no longer supported.  Use the GOBJECT_DEBUG environment variable.");
+}
+
+/**
+ * g_type_init:
+ *
+ * This function used to initialise the type system.  Since GLib 2.36,
+ * the type system is initialised automatically and this function does
+ * nothing.
+ *
+ * Deprecated: 2.36: the type system is now initialised automatically
+ */
+void
+g_type_init (void)
+{
+  g_assert_type_system_initialized ();
+}
+
+#if defined (G_HAS_CONSTRUCTORS)
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
+#endif
+G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
+#else
+# error Your platform/compiler is missing constructor support
+#endif
+
+static void
+gobject_init_ctor (void)
+{
   const gchar *env_string;
   GTypeInfo info;
   TypeNode *node;
-  volatile GType votype;
-  
-  G_LOCK (type_init_lock);
-  
+  GType type;
+
   G_WRITE_LOCK (&type_rw_lock);
-  
-  if (static_quark_type_flags)
-    {
-      G_WRITE_UNLOCK (&type_rw_lock);
-      G_UNLOCK (type_init_lock);
-      return;
-    }
-  
+
   /* setup GObject library wide debugging flags */
-  _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
   env_string = g_getenv ("GOBJECT_DEBUG");
   if (env_string != NULL)
     {
-      static GDebugKey debug_keys[] = {
-       { "objects", G_TYPE_DEBUG_OBJECTS },
-       { "signals", G_TYPE_DEBUG_SIGNALS },
+      GDebugKey debug_keys[] = {
+        { "objects", G_TYPE_DEBUG_OBJECTS },
+        { "instance-count", G_TYPE_DEBUG_INSTANCE_COUNT },
+        { "signals", G_TYPE_DEBUG_SIGNALS },
       };
-      
-      _g_type_debug_flags |= g_parse_debug_string (env_string,
-                                                  debug_keys,
-                                                  sizeof (debug_keys) / sizeof (debug_keys[0]));
-      env_string = NULL;
+
+      _g_type_debug_flags = g_parse_debug_string (env_string, debug_keys, G_N_ELEMENTS (debug_keys));
     }
   
   /* quarks */
@@ -4225,7 +4397,7 @@ g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
   
   /* type qname hash table */
-  static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
+  static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
   
   /* invalid type G_TYPE_INVALID (0)
    */
@@ -4234,111 +4406,121 @@ g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
   /* void type G_TYPE_NONE
    */
   node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
-  votype = NODE_TYPE (node);
-  g_assert (votype == G_TYPE_NONE);
+  type = NODE_TYPE (node);
+  g_assert (type == G_TYPE_NONE);
   
   /* interface fundamental type G_TYPE_INTERFACE (!classed)
    */
   memset (&info, 0, sizeof (info));
   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
-  votype = NODE_TYPE (node);
+  type = NODE_TYPE (node);
   type_data_make_W (node, &info, NULL);
-  g_assert (votype == G_TYPE_INTERFACE);
+  g_assert (type == G_TYPE_INTERFACE);
   
   G_WRITE_UNLOCK (&type_rw_lock);
   
-  g_value_c_init ();
+  _g_value_c_init ();
 
   /* G_TYPE_TYPE_PLUGIN
    */
-  votype = g_type_plugin_get_type ();
+  g_type_ensure (g_type_plugin_get_type ());
   
   /* G_TYPE_* value types
    */
-  g_value_types_init ();
+  _g_value_types_init ();
   
   /* G_TYPE_ENUM & G_TYPE_FLAGS
    */
-  g_enum_types_init ();
+  _g_enum_types_init ();
   
   /* G_TYPE_BOXED
    */
-  g_boxed_type_init ();
+  _g_boxed_type_init ();
   
   /* G_TYPE_PARAM
    */
-  g_param_type_init ();
+  _g_param_type_init ();
   
   /* G_TYPE_OBJECT
    */
-  g_object_type_init ();
+  _g_object_type_init ();
   
   /* G_TYPE_PARAM_* pspec types
    */
-  g_param_spec_types_init ();
+  _g_param_spec_types_init ();
   
   /* Value Transformations
    */
-  g_value_transforms_init ();
+  _g_value_transforms_init ();
   
   /* Signal system
    */
-  g_signal_init ();
-  
-  G_UNLOCK (type_init_lock);
-}
-
-/**
- * g_type_init:
- *
- * Prior to any use of the type system, g_type_init() has to be called
- * to initialize the type system and assorted other code portions
- * (such as the various fundamental type implementations or the signal
- * system).
- */
-void
-g_type_init (void)
-{
-  g_type_init_with_debug_flags (0);
+  _g_signal_init ();
 }
 
 /**
  * g_type_class_add_private:
  * @g_class: class structure for an instantiatable type
- * @private_size: size of private structure.
+ * @private_size: size of private structure
+ *
+ * Registers a private structure for an instantiatable type.
  *
- * Registers a private structure for an instantiatable type;
- * when an object is allocated, the private structures for
+ * When an object is allocated, the private structures for
  * the type and all of its parent types are allocated
  * sequentially in the same memory block as the public
- * structures. This function should be called in the
- * type's class_init() function. The private structure can
- * be retrieved using the G_TYPE_INSTANCE_GET_PRIVATE() macro.
+ * structures, and are zero-filled.
+ *
+ * Note that the accumulated size of the private structures of
+ * a type and all its parent types cannot exceed 64 KiB.
+ *
+ * This function should be called in the type's class_init() function.
+ * The private structure can be retrieved using the
+ * G_TYPE_INSTANCE_GET_PRIVATE() macro.
+ *
  * The following example shows attaching a private structure
- * <structname>MyObjectPrivate</structname> to an object
- * <structname>MyObject</structname> defined in the standard GObject
- * fashion.
+ * MyObjectPrivate to an object MyObject defined in the standard
+ * GObject fashion in the type's class_init() function.
  *
- * |[
+ * Note the use of a structure member "priv" to avoid the overhead
+ * of repeatedly calling MY_OBJECT_GET_PRIVATE().
+ *
+ * |[<!-- language="C" --> 
+ * typedef struct _MyObject        MyObject;
  * typedef struct _MyObjectPrivate MyObjectPrivate;
  *
+ * struct _MyObject {
+ *  GObject parent;
+ *
+ *  MyObjectPrivate *priv;
+ * };
+ *
  * struct _MyObjectPrivate {
  *   int some_field;
  * };
  *
- * #define MY_OBJECT_GET_PRIVATE(o)  \
- *    (G_TYPE_INSTANCE_GET_PRIVATE ((o), MY_TYPE_OBJECT, MyObjectPrivate))
- *
  * static void
  * my_object_class_init (MyObjectClass *klass)
  * {
  *   g_type_class_add_private (klass, sizeof (MyObjectPrivate));
  * }
  *
+ * static void
+ * my_object_init (MyObject *my_object)
+ * {
+ *   my_object->priv = G_TYPE_INSTANCE_GET_PRIVATE (my_object,
+ *                                                  MY_TYPE_OBJECT,
+ *                                                  MyObjectPrivate);
+ *   // my_object->priv->some_field will be automatically initialised to 0
+ * }
+ *
  * static int
  * my_object_get_some_field (MyObject *my_object)
  * {
- *   MyObjectPrivate *priv = MY_OBJECT_GET_PRIVATE (my_object);
+ *   MyObjectPrivate *priv;
+ *
+ *   g_return_val_if_fail (MY_IS_OBJECT (my_object), 0);
+ *
+ *   priv = my_object->priv;
  *
  *   return priv->some_field;
  * }
@@ -4352,9 +4534,9 @@ g_type_class_add_private (gpointer g_class,
 {
   GType instance_type = ((GTypeClass *)g_class)->g_type;
   TypeNode *node = lookup_type_node_I (instance_type);
-  gsize offset;
 
   g_return_if_fail (private_size > 0);
+  g_return_if_fail (private_size <= 0xffff);
 
   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
     {
@@ -4368,79 +4550,319 @@ g_type_class_add_private (gpointer g_class,
       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
       if (node->data->instance.private_size != pnode->data->instance.private_size)
        {
-         g_warning ("g_type_add_private() called multiple times for the same type");
+         g_warning ("g_type_class_add_private() called multiple times for the same type");
          return;
        }
     }
   
   G_WRITE_LOCK (&type_rw_lock);
 
-  offset = ALIGN_STRUCT (node->data->instance.private_size);
-  node->data->instance.private_size = offset + private_size;
+  private_size = ALIGN_STRUCT (node->data->instance.private_size + private_size);
+  g_assert (private_size <= 0xffff);
+  node->data->instance.private_size = private_size;
   
   G_WRITE_UNLOCK (&type_rw_lock);
 }
 
+/* semi-private, called only by the G_ADD_PRIVATE macro */
+gint
+g_type_add_instance_private (GType class_gtype,
+                             gsize private_size)
+{
+  TypeNode *node = lookup_type_node_I (class_gtype);
+
+  g_return_val_if_fail (private_size > 0, 0);
+  g_return_val_if_fail (private_size <= 0xffff, 0);
+
+  if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
+    {
+      g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
+                type_descriptive_name_I (class_gtype));
+      return 0;
+    }
+
+  if (node->plugin != NULL)
+    {
+      g_warning ("cannot use g_type_add_instance_private() with dynamic type '%s'",
+                 type_descriptive_name_I (class_gtype));
+      return 0;
+    }
+
+  /* in the future, we want to register the private data size of a type
+   * directly from the get_type() implementation so that we can take full
+   * advantage of the type definition macros that we already have.
+   *
+   * unfortunately, this does not behave correctly if a class in the middle
+   * of the type hierarchy uses the "old style" of private data registration
+   * from the class_init() implementation, as the private data offset is not
+   * going to be known until the full class hierarchy is initialized.
+   *
+   * in order to transition our code to the Glorious New Futureā„¢, we proceed
+   * with a two-step implementation: first, we provide this new function to
+   * register the private data size in the get_type() implementation and we
+   * hide it behind a macro. the function will return the private size, instead
+   * of the offset, which will be stored inside a static variable defined by
+   * the G_DEFINE_TYPE_EXTENDED macro. the G_DEFINE_TYPE_EXTENDED macro will
+   * check the variable and call g_type_class_add_instance_private(), which
+   * will use the data size and actually register the private data, then
+   * return the computed offset of the private data, which will be stored
+   * inside the static variable, so we can use it to retrieve the pointer
+   * to the private data structure.
+   *
+   * once all our code has been migrated to the new idiomatic form of private
+   * data registration, we will change the g_type_add_instance_private()
+   * function to actually perform the registration and return the offset
+   * of the private data; g_type_class_add_instance_private() already checks
+   * if the passed argument is negative (meaning that it's an offset in the
+   * GTypeInstance allocation) and becomes a no-op if that's the case. this
+   * should make the migration fully transparent even if we're effectively
+   * copying this macro into everybody's code.
+   */
+  return private_size;
+}
+
+/* semi-private function, should only be used by G_DEFINE_TYPE_EXTENDED */
+void
+g_type_class_adjust_private_offset (gpointer  g_class,
+                                    gint     *private_size_or_offset)
+{
+  GType class_gtype = ((GTypeClass *) g_class)->g_type;
+  TypeNode *node = lookup_type_node_I (class_gtype);
+  gssize private_size;
+
+  g_return_if_fail (private_size_or_offset != NULL);
+
+  /* if we have been passed the offset instead of the private data size,
+   * then we consider this as a no-op, and just return the value. see the
+   * comment in g_type_add_instance_private() for the full explanation.
+   */
+  if (*private_size_or_offset > 0)
+    g_return_if_fail (*private_size_or_offset <= 0xffff);
+  else
+    return;
+
+  if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
+    {
+      g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
+                type_descriptive_name_I (class_gtype));
+      *private_size_or_offset = 0;
+      return;
+    }
+
+  if (NODE_PARENT_TYPE (node))
+    {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+      if (node->data->instance.private_size != pnode->data->instance.private_size)
+       {
+         g_warning ("g_type_add_instance_private() called multiple times for the same type");
+          *private_size_or_offset = 0;
+         return;
+       }
+    }
+
+  G_WRITE_LOCK (&type_rw_lock);
+
+  private_size = ALIGN_STRUCT (node->data->instance.private_size + *private_size_or_offset);
+  g_assert (private_size <= 0xffff);
+  node->data->instance.private_size = private_size;
+
+  *private_size_or_offset = -(gint) node->data->instance.private_size;
+
+  G_WRITE_UNLOCK (&type_rw_lock);
+}
+
 gpointer
 g_type_instance_get_private (GTypeInstance *instance,
                             GType          private_type)
 {
-  TypeNode *instance_node;
+  TypeNode *node;
+
+  g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
+
+  node = lookup_type_node_I (private_type);
+  if (G_UNLIKELY (!node || !node->is_instantiatable))
+    {
+      g_warning ("instance of invalid non-instantiatable type '%s'",
+                 type_descriptive_name_I (instance->g_class->g_type));
+      return NULL;
+    }
+
+  return ((gchar *) instance) - node->data->instance.private_size;
+}
+
+/**
+ * g_type_class_get_instance_private_offset: (skip)
+ * @g_class: a #GTypeClass
+ *
+ * Gets the offset of the private data for instances of @g_class.
+ *
+ * This is how many bytes you should add to the instance pointer of a
+ * class in order to get the private data for the type represented by
+ * @g_class.
+ *
+ * You can only call this function after you have registered a private
+ * data area for @g_class using g_type_class_add_private().
+ *
+ * Returns: the offset, in bytes
+ *
+ * Since: 2.38
+ **/
+gint
+g_type_class_get_instance_private_offset (gpointer g_class)
+{
+  GType instance_type;
+  guint16 parent_size;
+  TypeNode *node;
+
+  g_assert (g_class != NULL);
+
+  instance_type = ((GTypeClass *) g_class)->g_type;
+  node = lookup_type_node_I (instance_type);
+
+  g_assert (node != NULL);
+  g_assert (node->is_instantiatable);
+
+  if (NODE_PARENT_TYPE (node))
+    {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+
+      parent_size = pnode->data->instance.private_size;
+    }
+  else
+    parent_size = 0;
+
+  if (node->data->instance.private_size == parent_size)
+    g_error ("g_type_class_get_instance_private_offset() called on class %s but it has no private data",
+             g_type_name (instance_type));
+
+  return -(gint) node->data->instance.private_size;
+}
+
+/**
+ * g_type_add_class_private:
+ * @class_type: GType of an classed type
+ * @private_size: size of private structure
+ *
+ * Registers a private class structure for a classed type;
+ * when the class is allocated, the private structures for
+ * the class and all of its parent types are allocated
+ * sequentially in the same memory block as the public
+ * structures, and are zero-filled.
+ *
+ * This function should be called in the
+ * type's get_type() function after the type is registered.
+ * The private structure can be retrieved using the
+ * G_TYPE_CLASS_GET_PRIVATE() macro.
+ *
+ * Since: 2.24
+ */
+void
+g_type_add_class_private (GType    class_type,
+                         gsize    private_size)
+{
+  TypeNode *node = lookup_type_node_I (class_type);
+  gsize offset;
+
+  g_return_if_fail (private_size > 0);
+
+  if (!node || !node->is_classed || !node->data)
+    {
+      g_warning ("cannot add class private field to invalid type '%s'",
+                type_descriptive_name_I (class_type));
+      return;
+    }
+
+  if (NODE_PARENT_TYPE (node))
+    {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+      if (node->data->class.class_private_size != pnode->data->class.class_private_size)
+       {
+         g_warning ("g_type_add_class_private() called multiple times for the same type");
+         return;
+       }
+    }
+  
+  G_WRITE_LOCK (&type_rw_lock);
+
+  offset = ALIGN_STRUCT (node->data->class.class_private_size);
+  node->data->class.class_private_size = offset + private_size;
+
+  G_WRITE_UNLOCK (&type_rw_lock);
+}
+
+gpointer
+g_type_class_get_private (GTypeClass *klass,
+                         GType       private_type)
+{
+  TypeNode *class_node;
   TypeNode *private_node;
   TypeNode *parent_node;
-  GTypeClass *class;
   gsize offset;
 
-  g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
-
-  /* while instances are initialized, their class pointers change,
-   * so figure the instances real class first
-   */
-  class = instance_real_class_get (instance);
-  if (!class)
-    class = instance->g_class;
+  g_return_val_if_fail (klass != NULL, NULL);
 
-  instance_node = lookup_type_node_I (class->g_type);
-  if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
+  class_node = lookup_type_node_I (klass->g_type);
+  if (G_UNLIKELY (!class_node || !class_node->is_classed))
     {
-      g_warning ("instance of invalid non-instantiatable type `%s'",
-                type_descriptive_name_I (instance->g_class->g_type));
+      g_warning ("class of invalid type '%s'",
+                type_descriptive_name_I (klass->g_type));
       return NULL;
     }
 
   private_node = lookup_type_node_I (private_type);
-  if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
+  if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, class_node)))
     {
       g_warning ("attempt to retrieve private data for invalid type '%s'",
                 type_descriptive_name_I (private_type));
       return NULL;
     }
 
-  /* Note that we don't need a read lock, since instance existing
-   * means that the instance class and all parent classes
-   * exist, so the node->data, node->data->instance.instance_size,
-   * and node->data->instance.private_size are not going to be changed.
-   * for any of the relevant types.
-   */
-
-  offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
+  offset = ALIGN_STRUCT (class_node->data->class.class_size);
 
   if (NODE_PARENT_TYPE (private_node))
     {
       parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
       g_assert (parent_node->data && NODE_REFCOUNT (parent_node) > 0);
 
-      if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size))
+      if (G_UNLIKELY (private_node->data->class.class_private_size == parent_node->data->class.class_private_size))
        {
-         g_warning ("g_type_instance_get_private() requires a prior call to g_type_class_add_private()");
+         g_warning ("g_type_instance_get_class_private() requires a prior call to g_type_add_class_private()");
          return NULL;
        }
 
-      offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
+      offset += ALIGN_STRUCT (parent_node->data->class.class_private_size);
     }
 
-  return G_STRUCT_MEMBER_P (instance, offset);
+  return G_STRUCT_MEMBER_P (klass, offset);
+}
+
+/**
+ * g_type_ensure:
+ * @type: a #GType
+ *
+ * Ensures that the indicated @type has been registered with the
+ * type system, and its _class_init() method has been run.
+ *
+ * In theory, simply calling the type's _get_type() method (or using
+ * the corresponding macro) is supposed take care of this. However,
+ * _get_type() methods are often marked %G_GNUC_CONST for performance
+ * reasons, even though this is technically incorrect (since
+ * %G_GNUC_CONST requires that the function not have side effects,
+ * which _get_type() methods do on the first call). As a result, if
+ * you write a bare call to a _get_type() macro, it may get optimized
+ * out by the compiler. Using g_type_ensure() guarantees that the
+ * type's _get_type() method is called.
+ *
+ * Since: 2.34
+ */
+void
+g_type_ensure (GType type)
+{
+  /* In theory, @type has already been resolved and so there's nothing
+   * to do here. But this protects us in the case where the function
+   * gets inlined (as it might in gobject_init_ctor() above).
+   */
+  if (G_UNLIKELY (type == (GType)-1))
+    g_error ("can't happen");
 }
 
-#define __G_TYPE_C__
-#include "gobjectaliasdef.c"