Skip to content

Instantly share code, notes, and snippets.

@kumpera
Created April 30, 2010 19:17
Show Gist options
  • Save kumpera/385632 to your computer and use it in GitHub Desktop.
Save kumpera/385632 to your computer and use it in GitHub Desktop.
diff --git a/mono/metadata/gc-internal.h b/mono/metadata/gc-internal.h
index f975762..cb8fb5a 100644
--- a/mono/metadata/gc-internal.h
+++ b/mono/metadata/gc-internal.h
@@ -74,6 +74,10 @@ void mono_gc_remove_weak_track_handle (guint32 gchandle) MONO_INTERNAL;
GSList* mono_gc_remove_weak_track_object (MonoDomain *domain, MonoObject *obj) MONO_INTERNAL;
#endif
+/*Ephemeron functionality*/
+void mono_gc_ephemeron_array_add (MonoObject *obj) MONO_INTERNAL;
+
+
MonoBoolean
GCHandle_CheckCurrentDomain (guint32 gchandle) MONO_INTERNAL;
diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h
index 16c4347..ae90890 100644
--- a/mono/metadata/icall-def.h
+++ b/mono/metadata/icall-def.h
@@ -637,6 +637,10 @@ ICALL_TYPE(PARAMI, "System.Reflection.ParameterInfo", PARAMI_1)
ICALL(PARAMI_1, "GetMetadataToken", mono_reflection_get_token)
ICALL(PARAMI_2, "GetTypeModifiers", param_info_get_type_modifiers)
+ICALL_TYPE(EPHE, "System.Runtime.CompilerServices.Ephemeron", EPHE_1)
+ICALL(EPHE_1, "register_ephemeron_array", mono_gc_ephemeron_array_add)
+
+
ICALL_TYPE(RUNH, "System.Runtime.CompilerServices.RuntimeHelpers", RUNH_1)
ICALL(RUNH_1, "GetObjectValue", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue)
/* REMOVEME: no longer needed, just so we dont break things when not needed */
diff --git a/mono/metadata/object.c b/mono/metadata/object.c
index 59a6263..8e546c2 100644
--- a/mono/metadata/object.c
+++ b/mono/metadata/object.c
@@ -633,6 +633,15 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
size = max_size;
}
+#ifdef HAVE_SGEN_GC
+ /*An Ephemeron cannot be marked by sgen*/
+ if (!static_fields && class->image == mono_defaults.corlib && !strcmp ("Ephemeron", class->name)) {
+ *max_set = 0;
+ memset (bitmap, 0, size / 8);
+ return bitmap;
+ }
+#endif
+
for (p = class; p != NULL; p = p->parent) {
gpointer iter = NULL;
while ((field = mono_class_get_fields (p, &iter))) {
diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c
index a0d75b3..8a21402 100644
--- a/mono/metadata/sgen-gc.c
+++ b/mono/metadata/sgen-gc.c
@@ -330,6 +330,7 @@ enum {
INTERNAL_MEM_STORE_REMSET,
INTERNAL_MEM_MS_TABLES,
INTERNAL_MEM_MS_BLOCK_INFO,
+ INTERNAL_MEM_EPHEMERON_LINK,
INTERNAL_MEM_MAX
};
@@ -734,6 +735,13 @@ struct _DisappearingLinkHashTable {
int num_links;
};
+typedef struct _EphemeronLinkNode EphemeronLinkNode;
+
+struct _EphemeronLinkNode {
+ EphemeronLinkNode *next;
+ void **array;
+};
+
#define LARGE_INTERNAL_MEM_HEADER_MAGIC 0x7d289f3a
typedef struct _LargeInternalMemHeader LargeInternalMemHeader;
@@ -775,6 +783,8 @@ static FinalizeEntry *critical_fin_list = NULL;
static DisappearingLinkHashTable minor_disappearing_link_hash;
static DisappearingLinkHashTable major_disappearing_link_hash;
+static EphemeronLinkNode *ephemeron_list;
+
static int num_ready_finalizers = 0;
static int no_finalize = 0;
@@ -1025,6 +1035,9 @@ void mono_gc_scan_for_specific_ref (MonoObject *key);
static void init_stats (void);
+static int ephemerons_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end);
+static void clear_unreachable_ephemerons (char *start, char *end);
+
//#define BINARY_PROTOCOL
#include "sgen-protocol.c"
#include "sgen-pinning.c"
@@ -1454,8 +1467,8 @@ mono_gc_get_bitmap_for_descr (void *descr, int *numbits)
} \
} while (0)
-//#include "sgen-major-copying.c"
-#include "sgen-marksweep.c"
+#include "sgen-major-copying.c"
+//#include "sgen-marksweep.c"
static gboolean
is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain)
@@ -2827,6 +2840,20 @@ finish_gray_stack (char *start_addr, char *end_addr, int generation)
TV_GETTIME (btv);
DEBUG (2, fprintf (gc_debug_file, "Finalize queue handling scan for %s generation: %d usecs\n", generation_name (generation), TV_ELAPSED (atv, btv)));
+ /*handle ephemerons arrays*/
+ g_assert (gray_object_queue_is_empty ());
+ for (;;) {
+ int done = ephemerons_in_range (copy_func, start_addr, end_addr);
+ drain_gray_stack ();
+ if (done)
+ break;
+ }
+
+ clear_unreachable_ephemerons (start_addr, end_addr);
+
+ DEBUG (2, fprintf (gc_debug_file, "Finalize ephemeron handling scan for %s generation\n", generation_name (generation)));
+
+
/*
* handle disappearing links
* Note we do this after checking the finalization queue because if an object
@@ -4199,6 +4226,102 @@ finalize_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end, int g
}
}
+static int
+object_is_reachable (char *object, char *start, char *end)
+{
+ if (object >= start && object < end && !object_is_fin_ready (object))
+ return 1;
+ return major_is_object_live (object);
+}
+
+/* LOCKING: requires that the GC lock is held */
+static void
+clear_unreachable_ephemerons (char *start, char *end)
+{
+ int i;
+ EphemeronLinkNode *current = ephemeron_list;
+
+ while (current) {
+ char *object = REVEAL_POINTER (current->array);
+ /*it has to be alive*/
+ if (!object_is_reachable (object, start, end)) {
+ current = current->next;
+ continue;
+ }
+
+ DEBUG (2, fprintf (gc_debug_file, "Clearing unreachable entries for ephemeron array at %p\n", object));
+ MonoArray *array = (MonoArray*)object;
+ gpointer *ptr = (gpointer*)mono_array_addr_with_size (array, sizeof (mword) * 2, 0);
+ for (i = 0; i < mono_array_length (array); ++i) {
+ char *key = ptr [0];
+ char *value = ptr [1];
+ if (key)
+ DEBUG (2, fprintf (gc_debug_file, "[%d] key %p (%s) value %p (%s)\n", i,
+ key, key && object_is_reachable (key, start, end) ? "reachable" : "unreachable",
+ value, value && object_is_reachable (value, start, end) ? "reachable" : "unreachable"));
+
+
+ if (key && !object_is_reachable (key, start, end)) {
+ ptr [0] = NULL;
+ ptr [1] = NULL;
+ }
+
+ ptr += 2;
+ }
+ current = current->next;
+ }
+}
+
+/* LOCKING: requires that the GC lock is held */
+static int
+ephemerons_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end)
+{
+ int i;
+ int nothing_marked = 1;
+ EphemeronLinkNode *current = ephemeron_list;
+
+ while (current) {
+ char *object = REVEAL_POINTER (current->array);
+ /*it has to be alive*/
+ if (!object_is_reachable (object, start, end)) {
+ DEBUG (2, fprintf (gc_debug_file, "Ephemeron array at %p is not reachable\n", object));
+ current = current->next;
+ continue;
+ }
+
+ copy_func ((void**)&object);
+ current->array = HIDE_POINTER (object, FALSE);
+
+ DEBUG (2, fprintf (gc_debug_file, "Processing Ephemeron array at %p\n", object));
+ MonoArray *array = (MonoArray*)object;
+ gpointer *ptr = (gpointer*)mono_array_addr_with_size (array, sizeof (mword) * 2, 0);
+ for (i = 0; i < mono_array_length (array); ++i) {
+ char *key = ptr [0];
+ char *value = ptr [1];
+ if (key)
+ DEBUG (2, fprintf (gc_debug_file, "[%d] key %p (%s) value %p (%s)\n", i,
+ key, key && object_is_reachable (key, start, end) ? "reachable" : "unreachable",
+ value, value && object_is_reachable (value, start, end) ? "reachable" : "unreachable"));
+
+
+ if (key && object_is_reachable (key, start, end)) {
+ copy_func (ptr); //move the key
+ if (value) {
+ if (!object_is_reachable (value, start, end)) {
+ nothing_marked = 0;
+ copy_func (ptr + 1); //;move the value
+ }
+ }
+ }
+
+ ptr += 2;
+ }
+ current = current->next;
+ }
+ DEBUG (2, fprintf (gc_debug_file, "Ephemeron run finished. Is it done %d\n", nothing_marked));
+ return nothing_marked;
+}
+
/* LOCKING: requires that the GC lock is held */
static void
null_link_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end, int generation)
@@ -4537,6 +4660,18 @@ mono_gc_register_disappearing_link (MonoObject *obj, void **link, gboolean track
}
}
+/* LOCKING: assumes the GC lock is held */
+void
+mono_gc_register_ephemeron_array (MonoObject *obj)
+{
+ EphemeronLinkNode *node = get_internal_mem (sizeof (EphemeronLinkNode), INTERNAL_MEM_EPHEMERON_LINK);
+ node->array = HIDE_POINTER (obj, FALSE);
+ node->next = ephemeron_list;
+ ephemeron_list = node;
+
+ DEBUG (2, fprintf (gc_debug_file, "Registered ephemeron array %p\n", obj));
+}
+
int
mono_gc_invoke_finalizers (void)
{
@@ -6564,6 +6699,14 @@ mono_gc_weak_link_get (void **link_addr)
return (MonoObject*) REVEAL_POINTER (*link_addr);
}
+void
+mono_gc_ephemeron_array_add (MonoObject *obj)
+{
+ LOCK_GC;
+ mono_gc_register_ephemeron_array (obj);
+ UNLOCK_GC;
+}
+
void*
mono_gc_make_descr_from_bitmap (gsize *bitmap, int numbits)
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment