<p>The public interface of the Mono GC is fairly limited, and
its the only one that embedders should be using:
-
+
+<h3>Garbage Collector</h3>
+
<h4><a name="api:mono_gc_collect">mono_gc_collect</a></h4>
+<h4><a name="api:mono_gc_collection_count">mono_gc_collection_count</a></h4>
<h4><a name="api:mono_gc_max_generation">mono_gc_max_generation</a></h4>
+<h4><a name="api:mono_gc_get_generation">mono_gc_get_generation</a></h4>
<h4><a name="api:mono_gc_get_heap_size">mono_gc_get_heap_size</a></h4>
<h4><a name="api:mono_gc_get_used_size">mono_gc_get_used_size</a></h4>
+<h4><a name="api:mono_gc_walk_heap">mono_gc_walk_heap</a></h4>
+
+<h3>Reference Queues</h3>
-<h3>Weak Links</h3>
+<h4><a name="api:mono_gc_reference_queue_add">mono_gc_reference_queue_add</a></h4>
+<h4><a name="api:mono_gc_reference_queue_free">mono_gc_reference_queue_free</a></h4>
+<h4><a name="api:mono_gc_reference_queue_new">mono_gc_reference_queue_new</a></h4>
-<h4><a name="api:mono_gc_weak_link_add">mono_gc_weak_link_add</a></h4>
-<h4><a name="api:mono_gc_weak_link_get">mono_gc_weak_link_get</a></h4>
-<h4><a name="api:mono_gc_weak_link_remove">mono_gc_weak_link_remove</a></h4>
+<h3>SGen Bridge</h3>
-<h2>Internal Interface</h2>
+ <p>The bridge is a mechanism for SGen to let clients override
+ the death of some unreachable objects. We use it in monodroid
+ to do garbage collection across the Mono and Java heaps.
- <p>The internal interface of the Mono GC is the interface used
- between the runtime engine and the garbage collector.
+ <p>The client can designate some objects as "bridged", which
+ means that they participate in the bridge processing step once
+ SGen considers them unreachable, i.e., dead. Bridged objects
+ must be registered for finalization.
+
+ <p>When SGen is done marking, it puts together a list of all
+ dead bridged objects and then does a strongly connected
+ component analysis over their object graph. That graph will
+ usually contain non-bridged objects, too.
+
+ <p>The output of the SCC analysis is passed to the
+ `cross_references()` callback. It is expected to set the
+ `is_alive` flag on those strongly connected components that it
+ wishes to be kept alive. The value of `is_alive` will be
+ ignored on any SCCs which lack bridges.
+
+ <p>In monodroid each bridged object has a corresponding Java
+ mirror object. In the bridge callback it reifies the Mono
+ object graph in the Java heap so that the full, combined
+ object graph is now instantiated on the Java side. Then it
+ triggers a Java GC, waits for it to finish, and checks which
+ of the Java mirror objects are still alive. For those it sets
+ the `is_alive` flag and returns from the callback.
-<h4><a name="api:mono_gc_disable">mono_gc_disable</a></h4>
-<h4><a name="api:mono_gc_enable">mono_gc_enable</a></h4>
-<h4><a name="api:mono_gc_is_finalizer_thread">mono_gc_is_finalizer_thread</a></h4>
-<h4><a name="api:mono_gc_out_of_memory">mono_gc_out_of_memory</a></h4>
-<h4><a name="api:mono_gc_start_world">mono_gc_start_world</a></h4>
-<h4><a name="api:mono_gc_stop_world">mono_gc_stop_world</a></h4>
-<h4><a name="api:mono_gc_alloc_fixed">mono_gc_alloc_fixed</a></h4>
-<h4><a name="api:mono_gc_enable_events">mono_gc_enable_events</a></h4>
-<h4><a name="api:mono_gc_free_fixed">mono_gc_free_fixed</a></h4>
-<h4><a name="api:mono_gc_make_descr_from_bitmap">mono_gc_make_descr_from_bitmap</a></h4>
-
-
-<h4><a name="api:mono_gc_base_init">mono_gc_base_init</a></h4>
-<h4><a name="api:mono_gc_invoke_finalizers">mono_gc_invoke_finalizers</a></h4>
-<h4><a name="api:mono_gc_is_gc_thread">mono_gc_is_gc_thread</a></h4>
-<h4><a name="api:mono_gc_pending_finalizers">mono_gc_pending_finalizers</a></h4>
-<h4><a name="api:mono_gc_register_thread">mono_gc_register_thread</a></h4>
-<h4><a name="api:mono_gc_finalize_notify">mono_gc_finalize_notify</a></h4>
+ <p>The SCC analysis is done while the world is stopped, but
+ the callback is made with the world running again. Weak links
+ to bridged objects and other objects reachable from them are
+ kept until the callback returns, at which point all links to
+ bridged objects that don't have `is_alive` set are nulled.
+ Note that weak links to non-bridged objects reachable from
+ bridged objects are not nulled. This might be considered a
+ bug.
+
+<div class="mapi-header">
+enum {
+ SGEN_BRIDGE_VERSION = 5
+};
+
+typedef enum {
+ /* Instances of this class should be scanned when computing the transitive dependency among bridges. E.g. List of object*/
+ GC_BRIDGE_TRANSPARENT_CLASS,
+ /* Instances of this class should not be scanned when computing the transitive dependency among bridges. E.g. String*/
+ GC_BRIDGE_OPAQUE_CLASS,
+ /* Instances of this class should be bridged and have their dependency computed. */
+ GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS,
+ /* Instances of this class should be bridged but no dependencies should not be calculated. */
+ GC_BRIDGE_OPAQUE_BRIDGE_CLASS,
+} MonoGCBridgeObjectKind;
+
+typedef struct {
+ mono_bool is_alive; /* to be set by the cross reference callback */
+ int num_objs;
+ MonoObject *objs [MONO_ZERO_LEN_ARRAY];
+} MonoGCBridgeSCC;
+
+typedef struct {
+ int src_scc_index;
+ int dst_scc_index;
+} MonoGCBridgeXRef;
+
+typedef struct {
+ int bridge_version;
+ /*
+ * Tells the runtime which classes to even consider when looking for
+ * bridged objects. If subclasses are to be considered as well, the
+ * subclass check must be done in the callback.
+ */
+ MonoGCBridgeObjectKind (*bridge_class_kind) (MonoClass *klass);
+ /*
+ * This is only called on objects for whose classes
+ * `bridge_class_kind()` returned `XXX_BRIDGE_CLASS`.
+ */
+ mono_bool (*is_bridge_object) (MonoObject *object);
+ void (*cross_references) (int num_sccs, MonoGCBridgeSCC **sccs, int num_xrefs, MonoGCBridgeXRef *xrefs);
+} MonoGCBridgeCallbacks;
+</div>
+
+<h4><a name="api:mono_gc_register_bridge_callbacks">mono_gc_register_bridge_callbacks</a></h4>
+<h4><a name="api:mono_gc_wait_for_bridge_processing">mono_gc_wait_for_bridge_processing</a></h4>
+
+<h3>Write Barriers</h3>
+
+<h4><a name="api:mono_gc_wbarrier_arrayref_copy">mono_gc_wbarrier_arrayref_copy</a></h4>
+<h4><a name="api:mono_gc_wbarrier_generic_nostore">mono_gc_wbarrier_generic_nostore</a></h4>
+<h4><a name="api:mono_gc_wbarrier_generic_store">mono_gc_wbarrier_generic_store</a></h4>
+<h4><a name="api:mono_gc_wbarrier_generic_store_atomic">mono_gc_wbarrier_generic_store_atomic</a></h4>
+<h4><a name="api:mono_gc_wbarrier_object_copy">mono_gc_wbarrier_object_copy</a></h4>
+<h4><a name="api:mono_gc_wbarrier_set_arrayref">mono_gc_wbarrier_set_arrayref</a></h4>
+<h4><a name="api:mono_gc_wbarrier_set_field">mono_gc_wbarrier_set_field</a></h4>
+<h4><a name="api:mono_gc_wbarrier_value_copy">mono_gc_wbarrier_value_copy</a></h4>