Created
April 30, 2010 19:17
-
-
Save kumpera/385632 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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