+2009-12-02 Mark Probst <mark.probst@gmail.com>
+
+ * appdomain.c: When unloading a domain, zero its static data and
+ perform a minor collection when using SGen. That will get rid of
+ all the remsets pointing into that domain's static data.
+
+ * sgen-gc.c: Allow remsets into static data. By doing this we
+ need less checks so we're more efficient.
+
2009-12-01 Rodrigo Kumpera <rkumpera@novell.com>
* verify.c (mono_method_verify): Check for catch clauses with broken
mono_gc_free_fixed (vtable->data);
}
+static void
+zero_static_data (gpointer key, gpointer value, gpointer user_data)
+{
+ MonoClass *klass = (MonoClass*)key;
+ MonoVTable *vtable = value;
+
+ if (vtable->data && klass->has_static_refs)
+ memset (vtable->data, 0, mono_class_data_size (klass));
+}
+
typedef struct unload_data {
MonoDomain *domain;
char *failure_reason;
mono_loader_lock ();
mono_domain_lock (domain);
+#ifdef HAVE_SGEN_GC
+ /*
+ * We need to make sure that we don't have any remsets
+ * pointing into static data of the to-be-freed domain because
+ * at the next collections they would be invalid. So what we
+ * do is we first zero all static data and then do a minor
+ * collection. Because all references in the static data will
+ * now be null we won't do any unnecessary copies and after
+ * the collection there won't be any more remsets.
+ */
+ g_hash_table_foreach (domain->class_vtable_hash, zero_static_data, domain);
+ mono_gc_collect (0);
+#endif
g_hash_table_foreach (domain->class_vtable_hash, clear_cached_vtable, domain);
#ifdef HAVE_SGEN_GC
deregister_reflection_info_roots (domain);
case REMSET_LOCATION:
ptr = (void**)(*p);
//__builtin_prefetch (ptr);
- if (((void*)ptr < start_nursery || (void*)ptr >= end_nursery) && ptr_in_heap (ptr)) {
+ if (((void*)ptr < start_nursery || (void*)ptr >= end_nursery)) {
*ptr = copy_object (*ptr, start_nursery, end_nursery);
DEBUG (9, fprintf (gc_debug_file, "Overwrote remset at %p with %p\n", ptr, *ptr));
if (!global && *ptr >= start_nursery && *ptr < end_nursery) {
return p + 1;
case REMSET_RANGE:
ptr = (void**)(*p & ~REMSET_TYPE_MASK);
- if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery) || !ptr_in_heap (ptr))
+ if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery))
return p + 2;
count = p [1];
while (count-- > 0) {
return p + 2;
case REMSET_OBJECT:
ptr = (void**)(*p & ~REMSET_TYPE_MASK);
- if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery) || !ptr_in_heap (ptr))
+ if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery))
return p + 1;
scan_object ((char*)ptr, start_nursery, end_nursery);
return p + 1;
switch (p [1]) {
case REMSET_VTYPE:
- if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery) || !ptr_in_heap (ptr))
+ if (((void*)ptr >= start_nursery && (void*)ptr < end_nursery))
return p + 4;
desc = p [2];
count = p [3];
#endif
LOCK_GC;
- if (ptr_in_nursery (ptr) || !ptr_in_heap (ptr)) {
+ if (ptr_in_nursery (ptr) || ptr_on_stack (ptr)) {
DEBUG (8, fprintf (gc_debug_file, "Skipping remset at %p\n", ptr));
UNLOCK_GC;
return;
LOCK_GC;
memmove (dest, src, count * mono_class_value_size (klass, NULL));
rs = REMEMBERED_SET;
- if (ptr_in_nursery (dest) || !ptr_in_heap (dest)) {
+ if (ptr_in_nursery (dest) || ptr_on_stack (dest)) {
UNLOCK_GC;
return;
}
/* do not copy the sync state */
memcpy ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
size - sizeof (MonoObject));
- if (ptr_in_nursery (obj) || !ptr_in_heap (obj)) {
+ if (ptr_in_nursery (obj) || ptr_on_stack (obj)) {
UNLOCK_GC;
return;
}