gtype.c 144 KB
Newer Older
1
/* GObject - GLib Type, Object, Parameter and Signal Library
2
 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
15
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16
 */
17 18 19 20 21 22 23

/*
 * MT safe
 */

#include "config.h"

24
#include "../glib/valgrind.h"
25 26 27
#include <string.h>

#include "gtype.h"
28
#include "gtype-private.h"
29 30
#include "gtypeplugin.h"
#include "gvaluecollector.h"
31
#include "gatomicarray.h"
32
#include "gobject_trace.h"
33

34
#include "gconstructor.h"
35

36 37 38 39
#ifdef G_OS_WIN32
#include <windows.h>
#endif

40 41 42
#ifdef	G_ENABLE_DEBUG
#define	IF_DEBUG(debug_type)	if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
#endif
43

Stefan Kost's avatar
Stefan Kost committed
44 45
/**
 * SECTION:gtype
46 47 48
 * @short_description: The GLib Runtime type identification and
 *     management system
 * @title:Type Information
49
 *
Stefan Kost's avatar
Stefan Kost committed
50 51
 * The GType API is the foundation of the GObject system.  It provides the
 * facilities for registering and managing all fundamental data types,
52
 * user-defined object and interface types.
53
 *
Stefan Kost's avatar
Stefan Kost committed
54 55 56 57 58
 * 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.
59
 *
Stefan Kost's avatar
Stefan Kost committed
60 61 62 63
 * 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.
64
 *
65 66
 * These registration functions are usually called only once from a
 * function whose only purpose is to return the type identifier for a
Stefan Kost's avatar
Stefan Kost committed
67 68 69
 * 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.
70
 *
Stefan Kost's avatar
Stefan Kost committed
71 72 73 74
 * 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.
75
 *
76 77 78 79 80 81 82
 * 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.
 *
83 84 85 86
 * As mentioned in the [GType conventions][gtype-conventions], type names must
 * be at least three characters long. There is no upper length limit. The first
 * character must be a letter (a–z or A–Z) or an underscore (‘_’). Subsequent
 * characters can be letters, numbers or any of ‘-_+’.
Stefan Kost's avatar
Stefan Kost committed
87
 */
88 89 90 91 92 93


/* NOTE: some functions (some internal variants and exported ones)
 * invalidate data portions of the TypeNodes. if external functions/callbacks
 * are called, pointers to memory maintained by TypeNodes have to be looked up
 * again. this affects most of the struct TypeNode fields, e.g. ->children or
94 95 96
 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
 * not ->supers[]), as all those memory portions can get realloc()ed during
 * callback invocation.
97
 *
98 99 100 101 102 103 104 105 106 107 108 109 110
 * LOCKING:
 * lock handling issues when calling static functions are indicated by
 * uppercase letter postfixes, all static functions have to have
 * one of the below postfixes:
 * - _I:	[Indifferent about locking]
 *   function doesn't care about locks at all
 * - _U:	[Unlocked invocation]
 *   no read or write lock has to be held across function invocation
 *   (locks may be acquired and released during invocation though)
 * - _L:	[Locked invocation]
 *   a write lock or more than 0 read locks have to be held across
 *   function invocation
 * - _W:	[Write-locked invocation]
111
 *   a write lock has to be held across function invocation
112 113 114
 * - _Wm:	[Write-locked invocation, mutatable]
 *   like _W, but the write lock might be released and reacquired
 *   during invocation, watch your pointers
115 116
 * - _WmREC:    [Write-locked invocation, mutatable, recursive]
 *   like _Wm, but also acquires recursive mutex class_init_rec_mutex
117 118
 */

119
#ifdef LOCK_DEBUG
120 121 122 123
#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)
124
#else
125 126 127 128
#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)
129
#endif
130
#define	INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
131
    static const gchar _action[] = " invalidly modified type ";  \
Havoc Pennington's avatar
Havoc Pennington committed
132
    gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
133
    if (_arg) \
134
      g_error ("%s(%p)%s'%s'", _fname, _arg, _action, _tname); \
135
    else \
136
      g_error ("%s()%s'%s'", _fname, _action, _tname); \
137
}G_STMT_END
138 139
#define g_assert_type_system_initialized() \
  g_assert (static_quark_type_flags)
140

141 142 143 144 145 146 147 148
#ifdef  G_ENABLE_DEBUG
#define DEBUG_CODE(debug_type, code_block)  G_STMT_START {    \
    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
      { code_block; }                                     \
} G_STMT_END
#else /* !G_ENABLE_DEBUG */
#define DEBUG_CODE(debug_type, code_block)  /* code_block */
#endif  /* G_ENABLE_DEBUG */
149

150 151 152 153
#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
				    G_TYPE_FLAG_INSTANTIATABLE | \
				    G_TYPE_FLAG_DERIVABLE | \
				    G_TYPE_FLAG_DEEP_DERIVABLE)
154
#define	TYPE_FLAG_MASK		   (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
155 156 157
#define	SIZEOF_FUNDAMENTAL_INFO	   ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
						       sizeof (gpointer)), \
                                                  sizeof (glong)))
158

159 160 161 162 163 164 165 166 167 168 169 170
/* The 2*sizeof(size_t) alignment here is borrowed from
 * GNU libc, so it should be good most everywhere.
 * It is more conservative than is needed on some 64-bit
 * platforms, but ia64 does require a 16-byte alignment.
 * The SIMD extensions for x86 and ppc32 would want a
 * larger alignment than this, but we don't need to
 * do better than malloc.
 */
#define STRUCT_ALIGNMENT (2 * sizeof (gsize))
#define ALIGN_STRUCT(offset) \
      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)

171

172
/* --- typedefs --- */
173 174
typedef struct _TypeNode        TypeNode;
typedef struct _CommonData      CommonData;
175
typedef struct _BoxedData       BoxedData;
176 177 178 179
typedef struct _IFaceData       IFaceData;
typedef struct _ClassData       ClassData;
typedef struct _InstanceData    InstanceData;
typedef union  _TypeData        TypeData;
180
typedef struct _IFaceEntries    IFaceEntries;
181 182 183 184 185
typedef struct _IFaceEntry      IFaceEntry;
typedef struct _IFaceHolder	IFaceHolder;


/* --- prototypes --- */
186
static inline GTypeFundamentalInfo*	type_node_fundamental_info_I	(TypeNode		*node);
187
static	      void			type_add_flags_W		(TypeNode		*node,
188
									 GTypeFlags		 flags);
189
static	      void			type_data_make_W		(TypeNode		*node,
190 191
									 const GTypeInfo	*info,
									 const GTypeValueTable	*value_table);
192
static inline void			type_data_ref_Wm		(TypeNode		*node);
193
static inline void			type_data_unref_U               (TypeNode		*node,
194
									 gboolean		 uncached);
195
static void				type_data_last_unref_Wm		(TypeNode *              node,
196
									 gboolean		 uncached);
197 198 199 200 201
static inline gpointer			type_get_qdata_L		(TypeNode		*node,
									 GQuark			 quark);
static inline void			type_set_qdata_W		(TypeNode		*node,
									 GQuark			 quark,
									 gpointer		 data);
202 203
static IFaceHolder*			type_iface_peek_holder_L	(TypeNode		*iface,
									 GType			 instance_type);
204 205 206 207
static gboolean                         type_iface_vtable_base_init_Wm  (TypeNode               *iface,
                                                                         TypeNode               *node);
static void                             type_iface_vtable_iface_init_Wm (TypeNode               *iface,
                                                                         TypeNode               *node);
208 209
static gboolean				type_node_is_a_L		(TypeNode		*node,
									 TypeNode		*iface_node);
210 211


212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
/* --- enumeration --- */

/* The InitState enumeration is used to track the progress of initializing
 * both classes and interface vtables. Keeping the state of initialization
 * is necessary to handle new interfaces being added while we are initializing
 * the class or other interfaces.
 */
typedef enum
{
  UNINITIALIZED,
  BASE_CLASS_INIT,
  BASE_IFACE_INIT,
  CLASS_INIT,
  IFACE_INIT,
  INITIALIZED
} InitState;

229 230 231
/* --- structures --- */
struct _TypeNode
{
232
  guint volatile ref_count;
233 234 235
#ifdef G_ENABLE_DEBUG
  guint volatile instance_count;
#endif
236
  GTypePlugin *plugin;
Benjamin Otte's avatar
Benjamin Otte committed
237
  guint        n_children; /* writable with lock */
238
  guint        n_supers : 8;
239
  guint        n_prerequisites : 9;
240 241
  guint        is_classed : 1;
  guint        is_instantiatable : 1;
242
  guint        mutatable_check_cache : 1;	/* combines some common path checks */
Benjamin Otte's avatar
Benjamin Otte committed
243
  GType       *children; /* writable with lock */
244
  TypeData * volatile data;
245
  GQuark       qname;
246
  GData       *global_gdata;
247
  union {
248
    GAtomicArray iface_entries;		/* for !iface types */
249
    GAtomicArray offsets;
250
  } _prot;
251
  GType       *prerequisites;
252 253
  GType        supers[1]; /* flexible array */
};
254

255 256
#define SIZEOF_BASE_TYPE_NODE()			(G_STRUCT_OFFSET (TypeNode, supers))
#define MAX_N_SUPERS				(255)
257
#define MAX_N_CHILDREN				(G_MAXUINT)
258
#define	MAX_N_INTERFACES			(255) /* Limited by offsets being 8 bits */
259
#define	MAX_N_PREREQUISITES			(511)
260 261
#define NODE_TYPE(node)				(node->supers[0])
#define NODE_PARENT_TYPE(node)			(node->supers[1])
262
#define NODE_FUNDAMENTAL_TYPE(node)		(node->supers[node->n_supers])
263
#define NODE_NAME(node)				(g_quark_to_string (node->qname))
264
#define NODE_REFCOUNT(node)                     ((guint) g_atomic_int_get ((int *) &(node)->ref_count))
265
#define	NODE_IS_BOXED(node)			(NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_BOXED)
266
#define	NODE_IS_IFACE(node)			(NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
267 268
#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))
269 270
#define	IFACE_NODE_N_PREREQUISITES(node)	((node)->n_prerequisites)
#define	IFACE_NODE_PREREQUISITES(node)		((node)->prerequisites)
271 272 273 274
#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))
#define	iface_node_set_dependants_array_W(n,d)	(type_set_qdata_W ((n), static_quark_dependants_array, (d)))
275 276
#define	TYPE_ID_MASK				((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))

277 278 279 280
#define NODE_IS_ANCESTOR(ancestor, node)                                                    \
        ((ancestor)->n_supers <= (node)->n_supers &&                                        \
	 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))

281 282 283 284 285 286 287
struct _IFaceHolder
{
  GType           instance_type;
  GInterfaceInfo *info;
  GTypePlugin    *plugin;
  IFaceHolder    *next;
};
288

289 290 291 292
struct _IFaceEntry
{
  GType           iface_type;
  GTypeInterface *vtable;
293
  InitState       init_state;
294
};
295

296
struct _IFaceEntries {
297
  guint offset_index;
298 299 300 301 302 303
  IFaceEntry entry[1];
};

#define IFACE_ENTRIES_HEADER_SIZE (sizeof(IFaceEntries) - sizeof(IFaceEntry))
#define IFACE_ENTRIES_N_ENTRIES(_entries) ( (G_ATOMIC_ARRAY_DATA_SIZE((_entries)) - IFACE_ENTRIES_HEADER_SIZE) / sizeof(IFaceEntry) )

304 305
struct _CommonData
{
306
  GTypeValueTable  *value_table;
307
};
308

309 310 311 312 313 314 315
struct _BoxedData
{
  CommonData         data;
  GBoxedCopyFunc     copy_func;
  GBoxedFreeFunc     free_func;
};

316 317 318
struct _IFaceData
{
  CommonData         common;
319
  guint16            vtable_size;
320 321
  GBaseInitFunc      vtable_init_base;
  GBaseFinalizeFunc  vtable_finalize_base;
322 323 324 325
  GClassInitFunc     dflt_init;
  GClassFinalizeFunc dflt_finalize;
  gconstpointer      dflt_data;
  gpointer           dflt_vtable;
326
};
327

328 329 330
struct _ClassData
{
  CommonData         common;
331
  guint16            class_size;
332
  guint16            class_private_size;
333
  int volatile       init_state; /* atomic - g_type_class_ref reads it unlocked */
334 335 336 337 338 339 340
  GBaseInitFunc      class_init_base;
  GBaseFinalizeFunc  class_finalize_base;
  GClassInitFunc     class_init;
  GClassFinalizeFunc class_finalize;
  gconstpointer      class_data;
  gpointer           class;
};
341

342 343 344
struct _InstanceData
{
  CommonData         common;
345
  guint16            class_size;
346
  guint16            class_private_size;
347
  int volatile       init_state; /* atomic - g_type_class_ref reads it unlocked */
348 349 350 351 352 353 354
  GBaseInitFunc      class_init_base;
  GBaseFinalizeFunc  class_finalize_base;
  GClassInitFunc     class_init;
  GClassFinalizeFunc class_finalize;
  gconstpointer      class_data;
  gpointer           class;
  guint16            instance_size;
355
  guint16            private_size;
356 357 358
  guint16            n_preallocs;
  GInstanceInitFunc  instance_init;
};
359

360 361 362
union _TypeData
{
  CommonData         common;
363
  BoxedData          boxed;
364 365 366 367
  IFaceData          iface;
  ClassData          class;
  InstanceData       instance;
};
368

369 370 371 372
typedef struct {
  gpointer            cache_data;
  GTypeClassCacheFunc cache_func;
} ClassCacheFunc;
373

374 375 376 377
typedef struct {
  gpointer                check_data;
  GTypeInterfaceCheckFunc check_func;
} IFaceCheckFunc;
378 379 380


/* --- variables --- */
381 382
static GRWLock         type_rw_lock;
static GRecMutex       class_init_rec_mutex;
383 384
static guint           static_n_class_cache_funcs = 0;
static ClassCacheFunc *static_class_cache_funcs = NULL;
385 386
static guint           static_n_iface_check_funcs = 0;
static IFaceCheckFunc *static_iface_check_funcs = NULL;
387
static GQuark          static_quark_type_flags = 0;
388 389
static GQuark          static_quark_iface_holder = 0;
static GQuark          static_quark_dependants_array = 0;
390
static guint           type_registration_serial = 0;
391
GTypeDebugFlags	       _g_type_debug_flags = 0;
392 393

/* --- type nodes --- */
394
static GHashTable       *static_type_nodes_ht = NULL;
395
static TypeNode		*static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };
396
static GType		 static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
397 398

static inline TypeNode*
399
lookup_type_node_I (GType utype)
400
{
401 402
  if (utype > G_TYPE_FUNDAMENTAL_MAX)
    return (TypeNode*) (utype & ~TYPE_ID_MASK);
403
  else
404
    return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
405 406
}

407 408 409
/**
 * g_type_get_type_registration_serial:
 *
410 411
 * Returns an opaque serial number that represents the state of the set
 * of registered types. Any time a type is registered this serial changes,
Matthias Clasen's avatar
Matthias Clasen committed
412 413 414
 * 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.
415 416 417
 *
 * Since: 2.36
 *
418
 * Returns: An unsigned int, representing the state of type registrations
419 420 421 422 423 424 425
 */
guint
g_type_get_type_registration_serial (void)
{
  return (guint)g_atomic_int_get ((gint *)&type_registration_serial);
}

426
static TypeNode*
427 428 429 430 431
type_node_any_new_W (TypeNode             *pnode,
		     GType                 ftype,
		     const gchar          *name,
		     GTypePlugin          *plugin,
		     GTypeFundamentalFlags type_flags)
432
{
433
  guint n_supers;
434 435 436
  GType type;
  TypeNode *node;
  guint i, node_size = 0;
437

438 439
  n_supers = pnode ? pnode->n_supers + 1 : 0;
  
440
  if (!pnode)
441
    node_size += SIZEOF_FUNDAMENTAL_INFO;	      /* fundamental type info */
442
  node_size += SIZEOF_BASE_TYPE_NODE ();	      /* TypeNode structure */
443
  node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
444
  node = g_malloc0 (node_size);
445
  if (!pnode)					      /* offset fundamental types */
446 447
    {
      node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
448
      static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
449 450 451 452
      type = ftype;
    }
  else
    type = (GType) node;
453
  
454 455
  g_assert ((type & TYPE_ID_MASK) == 0);
  
456 457 458 459 460
  node->n_supers = n_supers;
  if (!pnode)
    {
      node->supers[0] = type;
      node->supers[1] = 0;
461
      
462 463
      node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
      node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
464
      
465 466 467 468 469
      if (NODE_IS_IFACE (node))
	{
          IFACE_NODE_N_PREREQUISITES (node) = 0;
	  IFACE_NODE_PREREQUISITES (node) = NULL;
	}
470
      else
471
	_g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node));
472 473 474 475
    }
  else
    {
      node->supers[0] = type;
476
      memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
477
      
478 479
      node->is_classed = pnode->is_classed;
      node->is_instantiatable = pnode->is_instantiatable;
480
      
481
      if (NODE_IS_IFACE (node))
482
	{
483 484
	  IFACE_NODE_N_PREREQUISITES (node) = 0;
	  IFACE_NODE_PREREQUISITES (node) = NULL;
485 486 487
	}
      else
	{
488
	  guint j;
489 490 491 492 493 494
	  IFaceEntries *entries;

	  entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),
					  IFACE_ENTRIES_HEADER_SIZE,
					  0);
	  if (entries)
495
	    {
496 497 498 499 500 501 502
	      for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
		{
		  entries->entry[j].vtable = NULL;
		  entries->entry[j].init_state = UNINITIALIZED;
		}
	      _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),
				      entries);
503
	    }
504
	}
505

506 507 508 509
      i = pnode->n_children++;
      pnode->children = g_renew (GType, pnode->children, pnode->n_children);
      pnode->children[i] = type;
    }
510 511 512

  TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type));

513 514 515 516 517
  node->plugin = plugin;
  node->n_children = 0;
  node->children = NULL;
  node->data = NULL;
  node->qname = g_quark_from_string (name);
518 519
  node->global_gdata = NULL;
  g_hash_table_insert (static_type_nodes_ht,
520
		       (gpointer) g_quark_to_string (node->qname),
521
		       (gpointer) type);
522 523 524

  g_atomic_int_inc ((gint *)&type_registration_serial);

525 526 527 528
  return node;
}

static inline GTypeFundamentalInfo*
529
type_node_fundamental_info_I (TypeNode *node)
530
{
531
  GType ftype = NODE_FUNDAMENTAL_TYPE (node);
532 533
  
  if (ftype != NODE_TYPE (node))
534
    node = lookup_type_node_I (ftype);
535
  
536
  return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
537 538 539
}

static TypeNode*
540 541 542
type_node_fundamental_new_W (GType                 ftype,
			     const gchar          *name,
			     GTypeFundamentalFlags type_flags)
543 544 545
{
  GTypeFundamentalInfo *finfo;
  TypeNode *node;
546 547
  
  g_assert ((ftype & TYPE_ID_MASK) == 0);
548
  g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
549
  
550 551
  if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
    static_fundamental_next++;
552
  
553
  type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
554 555 556
  
  node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
  
557
  finfo = type_node_fundamental_info_I (node);
558
  finfo->type_flags = type_flags;
559
  
560 561 562 563
  return node;
}

static TypeNode*
564 565 566 567
type_node_new_W (TypeNode    *pnode,
		 const gchar *name,
		 GTypePlugin *plugin)
     
568 569 570 571
{
  g_assert (pnode);
  g_assert (pnode->n_supers < MAX_N_SUPERS);
  g_assert (pnode->n_children < MAX_N_CHILDREN);
572
  
573
  return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
574 575 576
}

static inline IFaceEntry*
577
lookup_iface_entry_I (volatile IFaceEntries *entries,
578
		      TypeNode *iface_node)
579
{
580 581 582 583 584
  guint8 *offsets;
  guint offset_index;
  IFaceEntry *check;
  int index;
  IFaceEntry *entry;
585

586 587 588 589
  if (entries == NULL)
    return NULL;

  G_ATOMIC_ARRAY_DO_TRANSACTION
590
    (&iface_node->_prot.offsets, guint8,
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614

     entry = NULL;
     offsets = transaction_data;
     offset_index = entries->offset_index;
     if (offsets != NULL &&
	 offset_index < G_ATOMIC_ARRAY_DATA_SIZE(offsets))
       {
	 index = offsets[offset_index];
	 if (index > 0)
	   {
	     /* zero means unset, subtract one to get real index */
	     index -= 1;

	     if (index < IFACE_ENTRIES_N_ENTRIES (entries))
	       {
		 check = (IFaceEntry *)&entries->entry[index];
		 if (check->iface_type == NODE_TYPE (iface_node))
		   entry = check;
	       }
	   }
       }
     );

 return entry;
615 616
}

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
static inline IFaceEntry*
type_lookup_iface_entry_L (TypeNode *node,
			   TypeNode *iface_node)
{
  if (!NODE_IS_IFACE (iface_node))
    return NULL;

  return lookup_iface_entry_I (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node),
			       iface_node);
}


static inline gboolean
type_lookup_iface_vtable_I (TypeNode *node,
			    TypeNode *iface_node,
			    gpointer *vtable_ptr)
{
  IFaceEntry *entry;
  gboolean res;

  if (!NODE_IS_IFACE (iface_node))
    {
      if (vtable_ptr)
	*vtable_ptr = NULL;
      return FALSE;
    }

  G_ATOMIC_ARRAY_DO_TRANSACTION
    (CLASSED_NODE_IFACES_ENTRIES (node), IFaceEntries,

     entry = lookup_iface_entry_I (transaction_data, iface_node);
     res = entry != NULL;
     if (vtable_ptr)
       {
	 if (entry)
	   *vtable_ptr = entry->vtable;
	 else
	   *vtable_ptr = NULL;
       }
     );

  return res;
}

661
static inline gboolean
662 663
type_lookup_prerequisite_L (TypeNode *iface,
			    GType     prerequisite_type)
664 665 666 667 668
{
  if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
    {
      GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
      guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
669
      
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
      do
	{
	  guint i;
	  GType *check;
	  
	  i = (n_prerequisites + 1) >> 1;
	  check = prerequisites + i;
	  if (prerequisite_type == *check)
	    return TRUE;
	  else if (prerequisite_type > *check)
	    {
	      n_prerequisites -= i;
	      prerequisites = check;
	    }
	  else /* if (prerequisite_type < *check) */
	    n_prerequisites = i - 1;
	}
      while (n_prerequisites);
    }
  return FALSE;
}

692
static const gchar*
693
type_descriptive_name_I (GType type)
694 695 696
{
  if (type)
    {
697
      TypeNode *node = lookup_type_node_I (type);
698 699
      
      return node ? NODE_NAME (node) : "<unknown>";
700 701 702 703 704 705 706 707
    }
  else
    return "<invalid>";
}


/* --- type consistency checks --- */
static gboolean
708 709 710 711
check_plugin_U (GTypePlugin *plugin,
		gboolean     need_complete_type_info,
		gboolean     need_complete_interface_info,
		const gchar *type_name)
712
{
713 714
  /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U 
   */
715 716
  if (!plugin)
    {
717
      g_warning ("plugin handle for type '%s' is NULL",
718 719 720
		 type_name);
      return FALSE;
    }
721
  if (!G_IS_TYPE_PLUGIN (plugin))
722
    {
723
      g_warning ("plugin pointer (%p) for type '%s' is invalid",
724
		 plugin, type_name);
725 726
      return FALSE;
    }
727
  if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
728
    {
729
      g_warning ("plugin for type '%s' has no complete_type_info() implementation",
730 731 732
		 type_name);
      return FALSE;
    }
733
  if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
734
    {
735
      g_warning ("plugin for type '%s' has no complete_interface_info() implementation",
736 737 738 739 740 741 742
		 type_name);
      return FALSE;
    }
  return TRUE;
}

static gboolean
743
check_type_name_I (const gchar *type_name)
744
{
745
  static const gchar extra_chars[] = "-_+";
746 747
  const gchar *p = type_name;
  gboolean name_valid;
748
  
749 750
  if (!type_name[0] || !type_name[1] || !type_name[2])
    {
751
      g_warning ("type name '%s' is too short", type_name);
752 753 754 755 756 757 758 759 760 761 762
      return FALSE;
    }
  /* check the first letter */
  name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
  for (p = type_name + 1; *p; p++)
    name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
		   (p[0] >= 'a' && p[0] <= 'z') ||
		   (p[0] >= '0' && p[0] <= '9') ||
		   strchr (extra_chars, p[0]));
  if (!name_valid)
    {
763
      g_warning ("type name '%s' contains invalid characters", type_name);
764 765 766 767
      return FALSE;
    }
  if (g_type_from_name (type_name))
    {
768
      g_warning ("cannot register existing type '%s'", type_name);
769 770
      return FALSE;
    }
771
  
772 773 774 775
  return TRUE;
}

static gboolean
776
check_derivation_I (GType        parent_type,
777
		    const gchar *type_name)
778
{
779 780
  TypeNode *pnode;
  GTypeFundamentalInfo* finfo;
781
  
782
  pnode = lookup_type_node_I (parent_type);
783 784
  if (!pnode)
    {
785
      g_warning ("cannot derive type '%s' from invalid parent type '%s'",
786
		 type_name,
787
		 type_descriptive_name_I (parent_type));
788 789
      return FALSE;
    }
790
  finfo = type_node_fundamental_info_I (pnode);
791 792 793
  /* ensure flat derivability */
  if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
    {
794
      g_warning ("cannot derive '%s' from non-derivable parent type '%s'",
795 796 797 798 799
		 type_name,
		 NODE_NAME (pnode));
      return FALSE;
    }
  /* ensure deep derivability */
800
  if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
801 802
      !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
    {
803
      g_warning ("cannot derive '%s' from non-fundamental parent type '%s'",
804 805 806 807 808 809 810 811
		 type_name,
		 NODE_NAME (pnode));
      return FALSE;
    }
  
  return TRUE;
}

812 813 814 815 816
static gboolean
check_collect_format_I (const gchar *collect_format)
{
  const gchar *p = collect_format;
  gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
817 818
			   G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
			   G_VALUE_COLLECT_POINTER, 0 };
819
  
820 821 822 823 824 825
  while (*p)
    if (!strchr (valid_format, *p++))
      return FALSE;
  return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
}

826
static gboolean
827 828
check_value_table_I (const gchar           *type_name,
		     const GTypeValueTable *value_table)
829 830 831 832 833 834
{
  if (!value_table)
    return FALSE;
  else if (value_table->value_init == NULL)
    {
      if (value_table->value_free || value_table->value_copy ||
835
	  value_table->value_peek_pointer ||
836 837
	  value_table->collect_format || value_table->collect_value ||
	  value_table->lcopy_format || value_table->lcopy_value)
838
	g_warning ("cannot handle uninitializable values of type '%s'",
839 840 841 842 843 844 845 846
		   type_name);
      return FALSE;
    }
  else /* value_table->value_init != NULL */
    {
      if (!value_table->value_free)
	{
	  /* +++ optional +++
847
	   * g_warning ("missing 'value_free()' for type '%s'", type_name);
848 849 850 851 852
	   * return FALSE;
	   */
	}
      if (!value_table->value_copy)
	{
853
	  g_warning ("missing 'value_copy()' for type '%s'", type_name);
854 855
	  return FALSE;
	}
856 857 858
      if ((value_table->collect_format || value_table->collect_value) &&
	  (!value_table->collect_format || !value_table->collect_value))
	{
859
	  g_warning ("one of 'collect_format' and 'collect_value()' is unspecified for type '%s'",
860 861 862 863 864
		     type_name);
	  return FALSE;
	}
      if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
	{
865
	  g_warning ("the '%s' specification for type '%s' is too long or invalid",
866 867 868 869 870 871
		     "collect_format",
		     type_name);
	  return FALSE;
	}
      if ((value_table->lcopy_format || value_table->lcopy_value) &&
	  (!value_table->lcopy_format || !value_table->lcopy_value))
872
	{
873
	  g_warning ("one of 'lcopy_format' and 'lcopy_value()' is unspecified for type '%s'",
874 875 876
		     type_name);
	  return FALSE;
	}
877
      if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
878
	{
879
	  g_warning ("the '%s' specification for type '%s' is too long or invalid",
880
		     "lcopy_format",
881 882 883 884 885 886 887 888
		     type_name);
	  return FALSE;
	}
    }
  return TRUE;
}

static gboolean
889
check_type_info_I (TypeNode        *pnode,
890 891 892
		   GType            ftype,
		   const gchar     *type_name,
		   const GTypeInfo *info)
893
{
894
  GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
895
  gboolean is_interface = ftype == G_TYPE_INTERFACE;
896 897
  
  g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
898
  
899 900 901 902 903
  /* check instance members */
  if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
      (info->instance_size || info->n_preallocs || info->instance_init))
    {
      if (pnode)
904
	g_warning ("cannot instantiate '%s', derived from non-instantiatable parent type '%s'",
905 906 907
		   type_name,
		   NODE_NAME (pnode));
      else
908
	g_warning ("cannot instantiate '%s' as non-instantiatable fundamental",
909 910 911 912
		   type_name);
      return FALSE;
    }
  /* check class & interface members */
913
  if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
914
      (info->class_init || info->class_finalize || info->class_data ||
915
       info->class_size || info->base_init || info->base_finalize))
916 917
    {
      if (pnode)
918
	g_warning ("cannot create class for '%s', derived from non-classed parent type '%s'",
919 920 921
		   type_name,
                   NODE_NAME (pnode));
      else
922
	g_warning ("cannot create class for '%s' as non-classed fundamental",
923 924 925 926 927 928
		   type_name);
      return FALSE;
    }
  /* check interface size */
  if (is_interface && info->class_size < sizeof (GTypeInterface))
    {
929
      g_warning ("specified interface size for type '%s' is smaller than 'GTypeInterface' size",
930 931 932 933 934 935 936 937
		 type_name);
      return FALSE;
    }
  /* check class size */
  if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
    {
      if (info->class_size < sizeof (GTypeClass))
	{
938
	  g_warning ("specified class size for type '%s' is smaller than 'GTypeClass' size",
939 940 941 942 943
		     type_name);
	  return FALSE;
	}
      if (pnode && info->class_size < pnode->data->class.class_size)
	{
944 945
	  g_warning ("specified class size for type '%s' is smaller "
		     "than the parent type's '%s' class size",
946 947 948 949 950 951 952 953 954 955
		     type_name,
		     NODE_NAME (pnode));
	  return FALSE;
	}
    }
  /* check instance size */
  if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
    {
      if (info->instance_size < sizeof (GTypeInstance))
	{
956
	  g_warning ("specified instance size for type '%s' is smaller than 'GTypeInstance' size",
957 958 959 960 961
		     type_name);
	  return FALSE;
	}
      if (pnode && info->instance_size < pnode->data->instance.instance_size)
	{
962 963
	  g_warning ("specified instance size for type '%s' is smaller "
		     "than the parent type's '%s' instance size",
964 965 966 967 968
		     type_name,
		     NODE_NAME (pnode));
	  return FALSE;
	}
    }
969
  
970 971 972 973
  return TRUE;
}

static TypeNode*
974 975
find_conforming_child_type_L (TypeNode *pnode,
			      TypeNode *iface)
976 977 978
{
  TypeNode *node = NULL;
  guint i;
979 980
  
  if (type_lookup_iface_entry_L (pnode, iface))
981
    return pnode;
982
  
983
  for (i = 0; i < pnode->n_children && !node; i++)
984
    node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
985
  
986 987 988 989
  return node;
}

static gboolean
990 991
check_add_interface_L (GType instance_type,
		       GType iface_type)
992
{
993 994
  TypeNode *node = lookup_type_node_I (instance_type);
  TypeNode *iface = lookup_type_node_I (iface_type);
995
  IFaceEntry *entry;
996
  TypeNode *tnode;
997 998 999
  GType *prerequisites;
  guint i;

1000
  
1001 1002
  if (!node || !node->is_instantiatable)
    {
1003
      g_warning ("cannot add interfaces to invalid (non-instantiatable) type '%s'",
1004
		 type_descriptive_name_I (instance_type));
1005 1006
      return FALSE;
    }
1007
  if (!iface || !NODE_IS_IFACE (iface))
1008
    {
1009
      g_warning ("cannot add invalid (non-interface) type '%s' to type '%s'",
1010
		 type_descriptive_name_I (iface_type),
1011 1012 1013
		 NODE_NAME (node));
      return FALSE;
    }
1014 1015 1016 1017
  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));
1018
      return FALSE;
1019
    }
1020
  tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
1021
  if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
1022
    {
1023
      /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
1024
      g_warning ("cannot add sub-interface '%s' to type '%s' which does not conform to super-interface '%s'",
1025 1026 1027 1028 1029
		 NODE_NAME (iface),
		 NODE_NAME (node),
		 NODE_NAME (tnode));
      return FALSE;
    }
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
  /* allow overriding of interface type introduced for parent type */
  entry = type_lookup_iface_entry_L (node, iface);
  if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
    {
      /* ok, we do conform to this interface already, but the interface vtable was not
       * yet intialized, and we just conform to the interface because it got added to
       * one of our parents. so we allow overriding of holder info here.
       */
      return TRUE;
    }
  /* check whether one of our children already conforms (or whether the interface
   * got added to this node already)
   */
  tnode = find_conforming_child_type_L (node, iface);  /* tnode is_a node */
1044 1045
  if (tnode)
    {
1046
      g_warning ("cannot add interface type '%s' to type '%s', since type '%s' already conforms to interface",
1047 1048 1049 1050 1051
		 NODE_NAME (iface),
		 NODE_NAME (node),
		 NODE_NAME (tnode));
      return FALSE;
    }
1052 1053 1054 1055 1056 1057
  prerequisites = IFACE_NODE_PREREQUISITES (iface);
  for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    {
      tnode = lookup_type_node_I (prerequisites[i]);
      if (!type_node_is_a_L (node, tnode))
	{
1058
	  g_warning ("cannot add interface type '%s' to type '%s' which does not conform to prerequisite '%s'",
1059 1060 1061 1062 1063 1064
		     NODE_NAME (iface),
		     NODE_NAME (node),
		     NODE_NAME (tnode));
	  return FALSE;
	}
    }
1065 1066 1067 1068
  return TRUE;
}

static gboolean
1069
check_interface_info_I (TypeNode             *iface,
1070 1071
			GType                 instance_type,
			const GInterfaceInfo *info)
1072 1073 1074
{
  if ((info->interface_finalize || info->interface_data) && !info->interface_init)
    {
1075
      g_warning ("interface type '%s' for type '%s' comes without initializer",
1076
		 NODE_NAME (iface),
1077
		 type_descriptive_name_I (instance_type));
1078 1079
      return FALSE;
    }
1080
  
1081 1082 1083 1084
  return TRUE;
}

/* --- type info (type node data) --- */
1085
static void
1086 1087 1088
type_data_make_W (TypeNode              *node,
		  const GTypeInfo       *info,
		  const GTypeValueTable *value_table)
1089
{
1090 1091 1092 1093
  TypeData *data;
  GTypeValueTable *vtable = NULL;
  guint vtable_size = 0;
  
1094 1095
  g_assert (node->data == NULL && info != NULL);
  
1096 1097
  if (!value_table)
    {
1098
      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
      
      if (pnode)
	vtable = pnode->data->common.value_table;
      else
	{
	  static const GTypeValueTable zero_vtable = { NULL, };
	  
	  value_table = &zero_vtable;
	}
    }
  if (value_table)
1110 1111 1112 1113 1114 1115 1116 1117 1118
    {
      /* need to setup vtable_size since we have to allocate it with data in one chunk */
      vtable_size = sizeof (GTypeValueTable);
      if (value_table->collect_format)
	vtable_size += strlen (value_table->collect_format);
      if (value_table->lcopy_format)
	vtable_size += strlen (value_table->lcopy_format);
      vtable_size += 2;
    }
1119
   
Matthias Clasen's avatar
Matthias Clasen committed
1120
  if (node->is_instantiatable) /* careful, is_instantiatable is also is_classed */
1121
    {
1122 1123
      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));

1124 1125 1126
      data = g_malloc0 (sizeof (InstanceData) + vtable_size);
      if (vtable_size)
	vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
1127 1128 1129 1130 1131 1132 1133
      data->instance.class_size = info->class_size;
      data->instance.class_init_base = info->base_init;
      data->instance.class_finalize_base = info->base_finalize;
      data->instance.class_init = info->class_init;
      data->instance.class_finalize = info->class_finalize;
      data->instance.class_data = info->class_data;
      data->instance.class = NULL;
1134
      data->instance.init_state = UNINITIALIZED;
1135
      data->instance.instance_size = info->instance_size;
1136 1137 1138 1139
      /* We'll set the final value for data->instance.private size
       * after the parent class has been initialized
       */
      data->instance.private_size = 0;
1140 1141 1142
      data->instance.class_private_size = 0;
      if (pnode)
        data->instance.class_private_size = pnode->data->instance.class_private_size;
1143
#ifdef	DISABLE_MEM_POOLS
1144
      data->instance.n_preallocs = 0;
1145 1146 1147
#else	/* !DISABLE_MEM_POOLS */
      data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
#endif	/* !DISABLE_MEM_POOLS */
1148 1149 1150 1151
      data->instance.instance_init = info->instance_init;
    }
  else if (node->is_classed) /* only classed */
    {
1152 1153
      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));

1154 1155 1156
      data = g_malloc0 (sizeof (ClassData) + vtable_size);
      if (vtable_size)
	vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
1157 1158 1159 1160 1161 1162 1163
      data->class.class_size = info->class_size;
      data->class.class_init_base = info->base_init;
      data->class.class_finalize_base = info->base_finalize;
      data->class.class_init = info->class_init;
      data->class.class_finalize = info->class_finalize;
      data->class.class_data = info->class_data;
      data->class.class = NULL;
1164 1165 1166
      data->class.class_private_size = 0;
      if (pnode)
        data->class.class_private_size = pnode->data->class.class_private_size;
1167
      data->class.init_state = UNINITIALIZED;
1168
    }
1169
  else if (NODE_IS_IFACE (node))
1170
    {
1171 1172 1173
      data = g_malloc0 (sizeof (IFaceData) + vtable_size);
      if (vtable_size)
	vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
1174 1175 1176
      data->iface.vtable_size = info->class_size;
      data->iface.vtable_init_base = info->base_init;
      data->iface.vtable_finalize_base = info->base_finalize;
1177 1178 1179 1180
      data->iface.dflt_init = info->class_init;
      data->iface.dflt_finalize = info->class_finalize;
      data->iface.dflt_data = info->class_data;
      data->iface.dflt_vtable = NULL;
1181
    }
1182 1183 1184 1185 1186 1187
  else if (NODE_IS_BOXED (node))
    {
      data = g_malloc0 (sizeof (BoxedData) + vtable_size);
      if (vtable_size)
	vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData));
    }
1188
  else
1189 1190 1191 1192 1193 1194
    {
      data = g_malloc0 (sizeof (CommonData) + vtable_size);
      if (vtable_size)
	vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
    }
  
1195
  node->data = data;
1196 1197
  
  if (vtable_size)
1198
    {
1199
      gchar *p;
1200
      
1201 1202 1203 1204
      /* we allocate the vtable and its strings together with the type data, so
       * children can take over their parent's vtable pointer, and we don't
       * need to worry freeing it or not when the child data is destroyed
       */
1205
      *vtable = *value_table;
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
      p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
      p[0] = 0;
      vtable->collect_format = p;
      if (value_table->collect_format)
	{
	  strcat (p, value_table->collect_format);
	  p += strlen (value_table->collect_format);
	}
      p++;
      p[0] = 0;
      vtable->lcopy_format = p;
      if (value_table->lcopy_format)
	strcat  (p, value_table->lcopy_format);
1219
    }
1220
  node->data->common.value_table = vtable;
1221 1222 1223
  node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
				 !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
				   GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
1224
  
1225
  g_assert (node->data->common.value_table != NULL); /* paranoid */
1226

1227
  g_atomic_int_set ((int *) &node->ref_count, 1);
1228 1229 1230
}

static inline void
1231
type_data_ref_Wm (TypeNode *node)
1232 1233 1234
{
  if (!node->data)
    {
1235
      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1236 1237
      GTypeInfo tmp_info;
      GTypeValueTable tmp_value_table;
1238 1239 1240 1241
      
      g_assert (node->plugin != NULL);
      
      if (pnode)
1242 1243 1244 1245 1246
	{
	  type_data_ref_Wm (pnode);
	  if (node->data)
	    INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
	}
1247
      
1248 1249
      memset (&tmp_info, 0, sizeof (tmp_info));
      memset (&tmp_value_table, 0, sizeof (tmp_value_table));
1250 1251
      
      G_WRITE_UNLOCK (&type_rw_lock);
1252
      g_type_plugin_use (node->plugin);
1253
      g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
1254 1255 1256 1257
      G_WRITE_LOCK (&type_rw_lock);
      if (node->data)
	INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
      
1258
      check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info);
1259 1260 1261
      type_data_make_W (node, &tmp_info,
			check_value_table_I (NODE_NAME (node),
					     &tmp_value_table) ? &tmp_value_table : NULL);
1262 1263 1264
    }
  else
    {
1265
      g_assert (NODE_REFCOUNT (node) > 0);
1266
      
1267
      g_atomic_int_inc ((int *) &node->ref_count);
1268 1269 1270
    }
}

1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
static inline gboolean
type_data_ref_U (TypeNode *node)
{
  guint current;

  do {
    current = NODE_REFCOUNT (node);

    if (current < 1)
      return FALSE;
  } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current + 1));

  return TRUE;
}

1286 1287 1288 1289 1290 1291 1292
static gboolean
iface_node_has_available_offset_L (TypeNode *iface_node,
				   int offset,
				   int for_index)
{
  guint8 *offsets;

1293
  offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
  if (offsets == NULL)
    return TRUE;

  if (G_ATOMIC_ARRAY_DATA_SIZE (offsets) <= offset)
    return TRUE;

  if (offsets[offset] == 0 ||
      offsets[offset] == for_index+1)
    return TRUE;

  return FALSE;
}

static int
find_free_iface_offset_L (IFaceEntries *entries)
{
  IFaceEntry *entry;
  TypeNode *iface_node;
  int offset;
  int i;
  int n_entries;

  n_entries = IFACE_ENTRIES_N_ENTRIES (entries);
  offset = -1;
  do
    {
      offset++;
      for (i = 0; i < n_entries; i++)
	{
	  entry = &entries->entry[i];
	  iface_node = lookup_type_node_I (entry->iface_type);

	  if (!iface_node_has_available_offset_L (iface_node, offset, i))
	    break;
	}
    }
  while (i != n_entries);

  return offset;
}

static void
iface_node_set_offset_L (TypeNode *iface_node,
			 int offset,
			 int index)
{
  guint8 *offsets, *old_offset