Sophie

Sophie

distrib > Mandriva > 2010.1 > x86_64 > media > main-release > by-pkgid > cce607a8c492c8ede8e5451290758926 > files > 84

mono-doc-2.6.4-4mdv2010.1.x86_64.rpm

		Handling GC allocated objects in C

As part of an effort to improve our GC, we need to keep track
precisely of where objects are stored, so we can incrementally move
from the current conservative GC to a more advanced precise and moving GC.
Previously, all global C variables were considered GC roots, but this makes
the GC less efficient and increases the chances false references are found
to GC memory, hence retaining more memory than needed.
We need to tell the GC that some object is supposed to be kept alive
as if it was referenced in a global variable.

For Mono embedders
------------------

In C#, if you say:
class T {
	static object o;
}

Any object which is stored in `o' is considered to be alive -- it will
not be collected. `o' is a member of the root set for the GC.

However, in C code, this is not the case. If you have:

static MonoObject* o = NULL;

The object in `o' will *NOT* be scanned.

If you need to store an object in a C variable and prevent it from being 
collected, you need to acquire a GC handle for it.

	guint32 handle = mono_gchandle_new (my_object, TRUE);

TRUE means the object will be pinned, so it won't move in memory 
when we'll use a moving GC. You can access the MonoObject* referenced by
a handle with:

	MonoObject* obj = mono_gchandle_get_target (handle);

When you don't need the handle anymore you need to call:

	mono_gchandle_free (handle);

Note that if you assign a new object to the C var, you need to get a new 
handle, it's not enough to store a new object in the C var.

So code that looked like this:

	static MonoObject* o = NULL;
	...
	o = mono_object_new (...);
	/* use o */
	...
	/* when done to allow the GC to collect o */
	o = NULL;

should now be changed to:

	static guint32 o_handle;
	...
	MonoObject *o = mono_object_new (...);
	o_handle = mono_gchandle_new (o, TRUE);
	/* use o or mono_gchandle_get_target (o_handle) */
	...
	/* when done to allow the GC to collect o */
	mono_gchandle_free (o_handle);


For Mono runtime developers
---------------------------

There are two kinds of static vars used to store pointers to GC memory 
that we need to consider:
*) objects
*) other memory chunks allocated with GC_MALLOC().

Objects should be dealt with the GC handle support as detailed above.
Other items should register the static pointer as an area to be considered
part of the root set with the following:

	static gpointer my_gc_data = NULL;
	...
	MONO_GC_REGISTER_ROOT (my_gc_data);
	my_gc_data = GC_MALLOC (...);
	
Note that this registration is not necessary for *LOCAL* variables,
as they are stored on the stack. It is only necessary for global variables,
as they are not a part of the GC's root set.

Once you have done the MONO_GC_REGISTER_ROOT, the variable is just like
a static variable in C#. To keep an object alive, you have the variable reference
the GC memory, to remove the reference, set the variable to NULL.

As we prepare the code for a precise GC, GC_MALLOC () will not be used anymore
in this way in most cases: we'll have a mechanism to specify exactly where
references to GC memory is stored. This mechanism is now available with the new GC,
see usages of mono_gc_alloc_fixed (), mono_gc_register_root () and 
mono_gc_make_descr_from_bitmap().
See also docs/precise-gc for additional info.