diff options
Diffstat (limited to 'docs/gc-variables-in-c')
-rw-r--r-- | docs/gc-variables-in-c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/docs/gc-variables-in-c b/docs/gc-variables-in-c new file mode 100644 index 00000000000..61a7802fc18 --- /dev/null +++ b/docs/gc-variables-in-c @@ -0,0 +1,96 @@ + 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.
\ No newline at end of file |