Skip to content
Commit 31fde567 authored by Allison Karlitskaya's avatar Allison Karlitskaya
Browse files

gtype: put private data before the instance

Classically, a GTypeInstance has had the following layout:

 [[[[GTypeInstance] GObject] TypeA] TypeB] [TypeAPrivate] [TypeBPrivate]

where TypeB is a subclass of TypeA which is a GObject.  Both TypeA and
TypeB use pivate data.

The main problem with this approach is that the offset between a pointer
to an instance of TypeA and the TypeAPrivate is not constant: it changes
depending on the depth of derivation and the size of the instance
structures of the derived types.  For example, changing the size of the
TypeB structure in the above example would push the TypeAPrivate further
along.

This complicates the implementation of g_type_instance_get_private().
In particular, during object construction when the class pointer to the
'complete type' of the object is not yet stored in the header of the
GTypeInstance, we need a lookup table in order to be able to implement
g_type_instance_get_private() accurately.

We can avoid this problem by storing the private data before the
structures, in reverse order, like so:

  [TypeBPrivate] [TypeAPrivate] [[[[GTypeInstance] GObject] TypeA] TypeB]

Now the distance between TypeA and TypeAPrivate depends only on the size
of GObject and GTypeInstance, which are static.  Even in the case of
TypeB, the distance is not statically known but can be determined at
runtime and is constant (because we will know the size of TypeAPrivate
by the time we initialise TypeB and it won't change).

This approach requires a slighty dirty trick: allocating extra memory
_before_ the pointer we return from g_type_create_instance().  The main
problem with this is that it will cause valgrind to behave very badly,
reporting almost everything as "possibly lost".

We can correct for this by including a few valgrind client requests in
order to inform it that the start of the GTypeInstance should be
considered a block of memory and that pointers to it should mean that
this block is reachable.  In order to make the private data reachable,
we also declare it as a block and include an extra pointer from the end
of the primary block pointing back at it.  All of this is only done if
we are running under Valgrind.

https://bugzilla.gnome.org/show_bug.cgi?id=698595
parent 00fbc2f0
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment