Merge pull request #5675 from mono/glib-debug-symbols
[mono.git] / docs / gc-variables-in-c
index 004b1aefa5145e3daf92a41df237980f989e61ec..c197e74205e7386e7952747a5eb0e9722b4dfe9e 100644 (file)
@@ -1,14 +1,16 @@
-**THIS IS A WORK IN PROGRESS**
+               Handling GC allocated objects in C
 
-As part of an effort to improve our GC effort, we will be
-moving towards flagging every variable that the GC must know
-about. Previously, global C variables were considered GC roots.
-However, as a part of this effort, we can no longer cast such
-a wide net. We must explicitly declare roots in C code.
+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.
 
-Storing GC allocated objects in C
-For embeders and Mono VM developers
-------------------------------------
+For Mono embedders
+------------------
 
 In C#, if you say:
 class T {
@@ -24,349 +26,75 @@ static MonoObject* o = NULL;
 
 The object in `o' will *NOT* be scanned.
 
-If you need a C variable to be included in the GC's root set, you
-must do the following registration:
+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.
 
-       MONO_GC_REGISTER_ROOT (my_object);
-       
-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
-that object, to remove the reference, set the variable to NULL.
-
-Mono Internal Audit
--------------------
-
-Until now, we have been able to store gc references in
-variables. This means we must audit the source code for where
-this happens, and ensure the GC knows the right roots.
-
-Because this is a change from previous behavior, an audit
-must be done to check for any incorrect uses. Basically,
-we need to check all variables that contain GC allocated objects. This
-includes MonoObject*'s, any other pointer to a managed type,
-and MonoGHashTable's. Any such variable must either
-       1) be added as a root -or-
-       2) only hold values that are referenced elsewhere
-
-The status of the audit is below:
-
-metadata
---------
-appdomain.c
-       No variables which can contain GC allocated data
-
-assembly.c
-       No variables which can contain GC allocated data
-       
-class.c
-       No variables which can contain GC allocated data
-
-debug-helpers.c
-       No variables which can contain GC allocated data
-
-debug-mono-symfile.c
-       No variables
-       
-decimal.c
-       No variables which can contain GC allocated data
-
-domain.c
-       static MonoGHashTable * appdomains_list = NULL;
-               This has been added as a root
-               
-       static MonoDomain *mono_root_domain = NULL;
-               this is added to the `appdomains_list' hashtable
-               which keeps the reference
-       
-       No other variables contain GC allocated data.
-
-environment.c
-       No variables which can contain GC allocated data
-
-exception.c
-       No variables.
-
-file-io.c
-       No variables
-
-filewatcher.c
-       No variablesNo other variables contain GC allocated data.
-gc.c
-       static MonoThread *gc_thread;
-               MonoThread*'s are taken care of by threads.c
-       static gpointer *gc_handles = NULL;
-       static guint8 *gc_handle_types = NULL;
-               These were added as roots
-               
-       No other variables contain GC allocated data.
-icall.c
-       No variables which can contain GC allocated data
-
-image.c
-       No variables which can contain GC allocated data
+       guint32 handle = mono_gchandle_new (my_object, TRUE);
 
-loader.c
-       No variables which can contain GC allocated data
-       
-locales.c
-       No variables
-       
-marshal.c
-       static MonoGHashTable *wrapper_hash;
-               Added as a root
-       static MonoString *string_dummy = NULL;
-               Added as a root
-       No other variables contain GC allocated data.
-       
-mempool.c
-       No variables
-       
-metadata.c
-       No variables which can contain GC allocated data
-
-monitor.c
-       No variables
+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:
 
-mono-config.c
-       No variables which can contain GC allocated data
+       MonoObject* obj = mono_gchandle_get_target (handle);
 
-mono-debug.c
-       No variables which can contain GC allocated data
+When you don't need the handle anymore you need to call:
 
-mono-debug-debugger.c
-       static MonoObject *last_exception = NULL;
-               Added as a root
-       
-       No other variables contain GC allocated data.
-       
-mono-endian.c
-       No variables
+       mono_gchandle_free (handle);
 
-monosn.c
-       Not compiled
+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.
 
-object.c
-       static MonoThread *main_thread;
-               Taken care of by threads.c
-               
-       No other variables contain GC allocated data.
-opcodes.c
-       No variables which can contain GC allocated data
+So code that looked like this:
 
-pedump.c
-       No variables which canMONO_GC_REGISTER_ROOT (my_object); contain GC allocated data
+       static MonoObject* o = NULL;
+       ...
+       o = mono_object_new (...);
+       /* use o */
+       ...
+       /* when done to allow the GC to collect o */
+       o = NULL;
 
-process.c
-       No variables which can contain GC allocated data
-       
-profiler.c
-       No variables which can contain GC allocated data
+should now be changed to:
 
-rand.c
-       No variables
-       
-rawbuffer.c
-       No variables which can contain GC allocated data
+       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);
 
-reflection.c
-       No variables which can contain GC allocated data
-       
-security.c
-       No variables.
-       
-socket-io.c
-       No variables which can contain GC allocated data
-       
-string-icalls.c
-       No variables
-       
-sysmath.c
-       No variables
-       
-threadpool.c
-       static MonoGHashTable *ares_htable = NULL;
-               Added as a root
-       
-       No other variables contain GC allocated data.
-threads.c
-       static MonoGHashTable *threads=NULL
-               Added as a root. This variable keeps a reference to
-               all threads, so it covers other files.
-               
-       No other variables contain GC allocated data.
-typedef.c
-       No variables
-unicode.c
-       No variables which can contain GC allocated data
-verify.c
-       No variables which can contain GC allocated data
-       
 
-utils/
-------
-monobitset.c
-       No variables which can contain GC allocated data
-mono-codeman.c
-       No variables which can contain GC allocated data
-mono-hash.c
-       static MonoGHashNode *node_free_list = NULL;
-               added as a root
-       No other variables contain GC allocated data.
-mono-logger.c
-       No variables which can contain GC allocated data
-mono-math.c
-       No variables which can contain GC allocated data
-mono-md5.c
-       No variables which can contain GC allocated data
-mono-sha1.c
-       No variables which can contain GC allocated data
-mono-uri.c
-       No variables which can contain GC allocated data
-strenc.c
-       No variables which can contain GC allocated data
-strtod.c
-       No variables which can contain GC allocated data
-       
-interp/
---------
-interp.c
-       static MonoGHashTable *method_pointer_hash = NULL;
-               Added as a root
-       No other variables contain GC allocated data.
-main.c
-       No variables which can contain GC allocated data
-mintops.c
-       No variables which can contain GC allocated data
-transform.c
-       No variables which can contain GC allocated data
-       
-mini/
------
+For Mono runtime developers
+---------------------------
 
-abcremoval.c
-       No variables which can contain GC allocated data
-aot.c
-       static MonoGHashTable *aot_modules;
-               Added as root
-       No other variables contain GC allocated data.
-cfold.c
-       No variables which can contain GC allocated data
-cprop.c
-       Not compiled
-debug-mini.c
-       No variables.
-dominators.c
-       No variables
-driver.c
-       No variables which can contain GC allocated data
-exceptions-ppc.c
-       No variables which can contain GC allocated data
-exceptions-s390.c
-       No variables which can contain GC allocated data
-exceptions-sparc.c
-       No variables which can contain GC allocated data
-exceptions-x86.c
-       No variables which can contain GC allocated data
-genmdesc.c
-       Not part of mini
-graph.c
-       No variables which can contain GC allocated data
-helpers.c
-       No variables which can contain GC allocated data
-inssel.c
-       No variables which can contain GC allocated data
-jit-icalls.c
-       No variables
-linear-scan.c
-       No variables
-liveness.c
-       No variables
-main.c
-       No variables
-mini.c
-       No variables which can contain GC allocated data
-mini-exceptions.c
-       No variables which can contain GC allocated data
-mini-ppc.c
-       No variables which can contain GC allocated data
-mini-s390.c
-       No variables which can contain G 
-C allocated data
-mini-sparc.c
-       No variables which can contain GC allocated data
-mini-x86.c
-       No variables which can contain GC allocated data
-regalloc.c
-       No variables which can contain GC allocated data
-ssa.c
-       No variables which can contain GC allocated data
-trace.c
-       No variables which can contain GC allocated data
-tramp-ppc.c
-       No variables which can contain GC allocated data
-tramp-s390.c
-       No variables which can contain GC allocated data
-tramp-sparc.c
-       No variables which can contain GC allocated data
-tramp-x86.c
-       No variables which can contain GC allocated data
+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:
 
-io-layer/
----------
-atomic.c
-       No variables which can contain GC allocated data
-context.c
-       No variables which can contain GC allocated data
-critical-sections.c
-       No variables which can contain GC allocated data
-daemon.c
-       No variables which can contain GC allocated data
-daemon-messages.c
-       No variables which can contain GC allocated data
-error.c
-       No variables which can contain GC allocated data
-events.c
-       No variables which can contain GC allocated data
-handles.c
-       No variables which can contain GC allocated data
-io.c
-       No variables which can contain GC allocated data
-io-layer-dummy.c
-       No variables which can contain GC allocated data
-misc.c
-       No variables which can contain GC allocated data
-mono-mutex.c
-       No variables which can contain GC allocated data
-mutexes.c
-       No variables which can contain GC allocated data
-processes.c
-       No variables which can contain GC allocated data
-security.c
-       No variables which can contain GC allocated data
-semaphores.c
-       No variables which can contain GC allocated data
-shared.c
-       No variables which can contain GC allocated data
-sockets.c
-       No variables which can contain GC allocated data
-system.c
-       No variables which can contain GC allocated data
-threads.c
-       static MonoGHashTable *tls_gc_hash = NULL;
-               added as a root
-       No other variables contain GC allocated data.
+       static gpointer my_gc_data = NULL;
+       ...
+       MONO_GC_REGISTER_ROOT (my_gc_data);
+       my_gc_data = GC_MALLOC (...);
        
-timed-thread.c
-       No variables which can contain GC allocated data
-timefuncs.c
-       No variables which can contain GC allocated data
-wait.c
-       No variables which can contain GC allocated data
-
+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.