X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-gc.c;h=f4ad5c1c90c40255fd107f20ff37a17ad3fc8eb6;hb=524f732a6d8c29f0bfe64a47b89eab8a97aaac0d;hp=23cca50895138efb1ab1964ff0103da85f4ae5e8;hpb=3a86569d2768d0fb43d7eac5be868c0005501e4a;p=mono.git diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 23cca508951..f4ad5c1c90c 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -207,7 +207,6 @@ #include "metadata/method-builder.h" #include "metadata/profiler-private.h" #include "metadata/monitor.h" -#include "metadata/threadpool-internals.h" #include "metadata/mempool-internals.h" #include "metadata/marshal.h" #include "metadata/runtime.h" @@ -367,6 +366,8 @@ mono_gc_flush_info (void) #define TV_ELAPSED SGEN_TV_ELAPSED #define TV_ELAPSED_MS SGEN_TV_ELAPSED_MS +SGEN_TV_DECLARE (sgen_init_timestamp); + #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) NurseryClearPolicy nursery_clear_policy = CLEAR_AT_TLAB_CREATION; @@ -609,141 +610,6 @@ gray_queue_redirect (SgenGrayQueue *queue) } } -static gboolean -is_xdomain_ref_allowed (gpointer *ptr, char *obj, MonoDomain *domain) -{ - MonoObject *o = (MonoObject*)(obj); - MonoObject *ref = (MonoObject*)*(ptr); - int offset = (char*)(ptr) - (char*)o; - - if (o->vtable->klass == mono_defaults.thread_class && offset == G_STRUCT_OFFSET (MonoThread, internal_thread)) - return TRUE; - if (o->vtable->klass == mono_defaults.internal_thread_class && offset == G_STRUCT_OFFSET (MonoInternalThread, current_appcontext)) - return TRUE; - -#ifndef DISABLE_REMOTING - if (mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) && - offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server)) - return TRUE; -#endif - /* Thread.cached_culture_info */ - if (!strcmp (ref->vtable->klass->name_space, "System.Globalization") && - !strcmp (ref->vtable->klass->name, "CultureInfo") && - !strcmp(o->vtable->klass->name_space, "System") && - !strcmp(o->vtable->klass->name, "Object[]")) - return TRUE; - /* - * at System.IO.MemoryStream.InternalConstructor (byte[],int,int,bool,bool) [0x0004d] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:121 - * at System.IO.MemoryStream..ctor (byte[]) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.IO/MemoryStream.cs:81 - * at (wrapper remoting-invoke-with-check) System.IO.MemoryStream..ctor (byte[]) - * at System.Runtime.Remoting.Messaging.CADMethodCallMessage.GetArguments () [0x0000d] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Messaging/CADMessages.cs:327 - * at System.Runtime.Remoting.Messaging.MethodCall..ctor (System.Runtime.Remoting.Messaging.CADMethodCallMessage) [0x00017] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs:87 - * at System.AppDomain.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage,byte[]&,System.Runtime.Remoting.Messaging.CADMethodReturnMessage&) [0x00018] in /home/schani/Work/novell/trunk/mcs/class/corlib/System/AppDomain.cs:1213 - * at (wrapper remoting-invoke-with-check) System.AppDomain.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage,byte[]&,System.Runtime.Remoting.Messaging.CADMethodReturnMessage&) - * at System.Runtime.Remoting.Channels.CrossAppDomainSink.ProcessMessageInDomain (byte[],System.Runtime.Remoting.Messaging.CADMethodCallMessage) [0x00008] in /home/schani/Work/novell/trunk/mcs/class/corlib/System.Runtime.Remoting.Channels/CrossAppDomainChannel.cs:198 - * at (wrapper runtime-invoke) object.runtime_invoke_CrossAppDomainSink/ProcessMessageRes_object_object (object,intptr,intptr,intptr) - */ - if (!strcmp (ref->vtable->klass->name_space, "System") && - !strcmp (ref->vtable->klass->name, "Byte[]") && - !strcmp (o->vtable->klass->name_space, "System.IO") && - !strcmp (o->vtable->klass->name, "MemoryStream")) - return TRUE; - /* append_job() in threadpool.c */ - if (!strcmp (ref->vtable->klass->name_space, "System.Runtime.Remoting.Messaging") && - !strcmp (ref->vtable->klass->name, "AsyncResult") && - !strcmp (o->vtable->klass->name_space, "System") && - !strcmp (o->vtable->klass->name, "Object[]") && - mono_thread_pool_is_queue_array ((MonoArray*) o)) - return TRUE; - return FALSE; -} - -static void -check_reference_for_xdomain (gpointer *ptr, char *obj, MonoDomain *domain) -{ - MonoObject *o = (MonoObject*)(obj); - MonoObject *ref = (MonoObject*)*(ptr); - int offset = (char*)(ptr) - (char*)o; - MonoClass *class; - MonoClassField *field; - char *str; - - if (!ref || ref->vtable->domain == domain) - return; - if (is_xdomain_ref_allowed (ptr, obj, domain)) - return; - - field = NULL; - for (class = o->vtable->klass; class; class = class->parent) { - int i; - - for (i = 0; i < class->field.count; ++i) { - if (class->fields[i].offset == offset) { - field = &class->fields[i]; - break; - } - } - if (field) - break; - } - - if (ref->vtable->klass == mono_defaults.string_class) - str = mono_string_to_utf8 ((MonoString*)ref); - else - str = NULL; - g_print ("xdomain reference in %p (%s.%s) at offset %d (%s) to %p (%s.%s) (%s) - pointed to by:\n", - o, o->vtable->klass->name_space, o->vtable->klass->name, - offset, field ? field->name : "", - ref, ref->vtable->klass->name_space, ref->vtable->klass->name, str ? str : ""); - mono_gc_scan_for_specific_ref (o, TRUE); - if (str) - g_free (str); -} - -#undef HANDLE_PTR -#define HANDLE_PTR(ptr,obj) check_reference_for_xdomain ((ptr), (obj), domain) - -static void -scan_object_for_xdomain_refs (char *start, mword size, void *data) -{ - MonoDomain *domain = ((MonoObject*)start)->vtable->domain; - - #include "sgen-scan-object.h" -} - -static gboolean scan_object_for_specific_ref_precise = TRUE; - -#undef HANDLE_PTR -#define HANDLE_PTR(ptr,obj) do { \ - if ((MonoObject*)*(ptr) == key) { \ - g_print ("found ref to %p in object %p (%s) at offset %td\n", \ - key, (obj), safe_name ((obj)), ((char*)(ptr) - (char*)(obj))); \ - } \ - } while (0) - -static void -scan_object_for_specific_ref (char *start, MonoObject *key) -{ - char *forwarded; - - if ((forwarded = SGEN_OBJECT_IS_FORWARDED (start))) - start = forwarded; - - if (scan_object_for_specific_ref_precise) { - #include "sgen-scan-object.h" - } else { - mword *words = (mword*)start; - size_t size = safe_object_get_size ((MonoObject*)start); - int i; - for (i = 0; i < size / sizeof (mword); ++i) { - if (words [i] == (mword)key) { - g_print ("found possible ref to %p in object %p (%s) at offset %td\n", - key, start, safe_name (start), i * sizeof (mword)); - } - } - } -} - void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags) { @@ -772,111 +638,6 @@ sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc } } -static void -scan_object_for_specific_ref_callback (char *obj, size_t size, MonoObject *key) -{ - scan_object_for_specific_ref (obj, key); -} - -static void -check_root_obj_specific_ref (RootRecord *root, MonoObject *key, MonoObject *obj) -{ - if (key != obj) - return; - g_print ("found ref to %p in root record %p\n", key, root); -} - -static MonoObject *check_key = NULL; -static RootRecord *check_root = NULL; - -static void -check_root_obj_specific_ref_from_marker (void **obj) -{ - check_root_obj_specific_ref (check_root, check_key, *obj); -} - -static void -scan_roots_for_specific_ref (MonoObject *key, int root_type) -{ - void **start_root; - RootRecord *root; - check_key = key; - - SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) { - mword desc = root->root_desc; - - check_root = root; - - switch (desc & ROOT_DESC_TYPE_MASK) { - case ROOT_DESC_BITMAP: - desc >>= ROOT_DESC_TYPE_SHIFT; - while (desc) { - if (desc & 1) - check_root_obj_specific_ref (root, key, *start_root); - desc >>= 1; - start_root++; - } - return; - case ROOT_DESC_COMPLEX: { - gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc); - int bwords = (*bitmap_data) - 1; - void **start_run = start_root; - bitmap_data++; - while (bwords-- > 0) { - gsize bmap = *bitmap_data++; - void **objptr = start_run; - while (bmap) { - if (bmap & 1) - check_root_obj_specific_ref (root, key, *objptr); - bmap >>= 1; - ++objptr; - } - start_run += GC_BITS_PER_WORD; - } - break; - } - case ROOT_DESC_USER: { - MonoGCRootMarkFunc marker = sgen_get_user_descriptor_func (desc); - marker (start_root, check_root_obj_specific_ref_from_marker); - break; - } - case ROOT_DESC_RUN_LEN: - g_assert_not_reached (); - default: - g_assert_not_reached (); - } - } SGEN_HASH_TABLE_FOREACH_END; - - check_key = NULL; - check_root = NULL; -} - -void -mono_gc_scan_for_specific_ref (MonoObject *key, gboolean precise) -{ - void **ptr; - RootRecord *root; - - scan_object_for_specific_ref_precise = precise; - - sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key, TRUE); - - major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key); - - sgen_los_iterate_objects ((IterateObjectCallbackFunc)scan_object_for_specific_ref_callback, key); - - scan_roots_for_specific_ref (key, ROOT_TYPE_NORMAL); - scan_roots_for_specific_ref (key, ROOT_TYPE_WBARRIER); - - SGEN_HASH_TABLE_FOREACH (&roots_hash [ROOT_TYPE_PINNED], ptr, root) { - while (ptr < (void**)root->end_root) { - check_root_obj_specific_ref (root, *ptr, key); - ++ptr; - } - } SGEN_HASH_TABLE_FOREACH_END; -} - static gboolean need_remove_object_for_domain (char *start, MonoDomain *domain) { @@ -897,7 +658,7 @@ process_object_for_domain_clearing (char *start, MonoDomain *domain) /* The object could be a proxy for an object in the domain we're deleting. */ #ifndef DISABLE_REMOTING - if (mono_class_has_parent_fast (vt->klass, mono_defaults.real_proxy_class)) { + if (mono_defaults.real_proxy_class->supertypes && mono_class_has_parent_fast (vt->klass, mono_defaults.real_proxy_class)) { MonoObject *server = ((MonoRealProxy*)start)->unwrapped_server; /* The server could already have been zeroed out, so @@ -910,85 +671,6 @@ process_object_for_domain_clearing (char *start, MonoDomain *domain) #endif } -static MonoDomain *check_domain = NULL; - -static void -check_obj_not_in_domain (void **o) -{ - g_assert (((MonoObject*)(*o))->vtable->domain != check_domain); -} - -static void -scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type) -{ - void **start_root; - RootRecord *root; - check_domain = domain; - SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) { - mword desc = root->root_desc; - - /* The MonoDomain struct is allowed to hold - references to objects in its own domain. */ - if (start_root == (void**)domain) - continue; - - switch (desc & ROOT_DESC_TYPE_MASK) { - case ROOT_DESC_BITMAP: - desc >>= ROOT_DESC_TYPE_SHIFT; - while (desc) { - if ((desc & 1) && *start_root) - check_obj_not_in_domain (*start_root); - desc >>= 1; - start_root++; - } - break; - case ROOT_DESC_COMPLEX: { - gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc); - int bwords = (*bitmap_data) - 1; - void **start_run = start_root; - bitmap_data++; - while (bwords-- > 0) { - gsize bmap = *bitmap_data++; - void **objptr = start_run; - while (bmap) { - if ((bmap & 1) && *objptr) - check_obj_not_in_domain (*objptr); - bmap >>= 1; - ++objptr; - } - start_run += GC_BITS_PER_WORD; - } - break; - } - case ROOT_DESC_USER: { - MonoGCRootMarkFunc marker = sgen_get_user_descriptor_func (desc); - marker (start_root, check_obj_not_in_domain); - break; - } - case ROOT_DESC_RUN_LEN: - g_assert_not_reached (); - default: - g_assert_not_reached (); - } - } SGEN_HASH_TABLE_FOREACH_END; - - check_domain = NULL; -} - -static void -check_for_xdomain_refs (void) -{ - LOSObject *bigobj; - - sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, - (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE); - - major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL); - - for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) - scan_object_for_xdomain_refs (bigobj->data, sgen_los_object_size (bigobj), NULL); -} - static gboolean clear_domain_process_object (char *obj, MonoDomain *domain) { @@ -1064,9 +746,9 @@ mono_gc_clear_domain (MonoDomain * domain) sgen_clear_nursery_fragments (); if (xdomain_checks && domain != mono_get_root_domain ()) { - scan_for_registered_roots_in_domain (domain, ROOT_TYPE_NORMAL); - scan_for_registered_roots_in_domain (domain, ROOT_TYPE_WBARRIER); - check_for_xdomain_refs (); + sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_NORMAL); + sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_WBARRIER); + sgen_check_for_xdomain_refs (); } /*Ephemerons and dislinks must be processed before LOS since they might end up pointing @@ -1089,7 +771,7 @@ mono_gc_clear_domain (MonoDomain * domain) objects with major-mark&sweep), but we might need to dereference a pointer from an object to another object if the first object is a proxy. */ - major_collector.iterate_objects (TRUE, TRUE, (IterateObjectCallbackFunc)clear_domain_process_major_object_callback, domain); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)clear_domain_process_major_object_callback, domain); for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) clear_domain_process_object (bigobj->data, domain); @@ -1109,8 +791,8 @@ mono_gc_clear_domain (MonoDomain * domain) prev = bigobj; bigobj = bigobj->next; } - major_collector.iterate_objects (TRUE, FALSE, (IterateObjectCallbackFunc)clear_domain_free_major_non_pinned_object_callback, domain); - major_collector.iterate_objects (FALSE, TRUE, (IterateObjectCallbackFunc)clear_domain_free_major_pinned_object_callback, domain); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_NON_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_non_pinned_object_callback, domain); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_pinned_object_callback, domain); if (domain == mono_get_root_domain ()) { if (G_UNLIKELY (do_pin_stats)) @@ -1933,7 +1615,7 @@ finish_gray_stack (int generation, GrayQueue *queue) ++ephemeron_rounds; } while (!done_with_ephemerons); - sgen_scan_togglerefs (start_addr, end_addr, ctx); + sgen_mark_togglerefs (start_addr, end_addr, ctx); if (sgen_need_bridge_processing ()) { /*Make sure the gray stack is empty before we process bridge objects so we get liveness right*/ @@ -2000,6 +1682,13 @@ finish_gray_stack (int generation, GrayQueue *queue) */ clear_unreachable_ephemerons (ctx); + /* + * We clear togglerefs only after all possible chances of revival are done. + * This is semantically more inline with what users expect and it allows for + * user finalizers to correctly interact with TR objects. + */ + sgen_clear_togglerefs (start_addr, end_addr, ctx); + TV_GETTIME (btv); SGEN_LOG (2, "Finalize queue handling scan for %s generation: %d usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds); @@ -2205,28 +1894,28 @@ init_stats (void) if (inited) return; - mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_pre_collection_fragment_clear); - mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_pinning); - mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_scan_remsets); - mono_counters_register ("Minor scan pinned", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_scan_pinned); - mono_counters_register ("Minor scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_scan_registered_roots); - mono_counters_register ("Minor scan thread data", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_scan_thread_data); - mono_counters_register ("Minor finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_finish_gray_stack); - mono_counters_register ("Minor fragment creation", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_minor_fragment_creation); - - mono_counters_register ("Major fragment clear", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_pre_collection_fragment_clear); - mono_counters_register ("Major pinning", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_pinning); - mono_counters_register ("Major scan pinned", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_pinned); - mono_counters_register ("Major scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_registered_roots); - mono_counters_register ("Major scan thread data", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_thread_data); - mono_counters_register ("Major scan alloc_pinned", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_alloc_pinned); - mono_counters_register ("Major scan finalized", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_finalized); - mono_counters_register ("Major scan big objects", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_scan_big_objects); - mono_counters_register ("Major finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_finish_gray_stack); - mono_counters_register ("Major free big objects", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_free_bigobjs); - mono_counters_register ("Major LOS sweep", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_los_sweep); - mono_counters_register ("Major sweep", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_sweep); - mono_counters_register ("Major fragment creation", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &time_major_fragment_creation); + mono_counters_register ("Minor fragment clear", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pre_collection_fragment_clear); + mono_counters_register ("Minor pinning", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_pinning); + mono_counters_register ("Minor scan remembered set", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_remsets); + mono_counters_register ("Minor scan pinned", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_pinned); + mono_counters_register ("Minor scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_registered_roots); + mono_counters_register ("Minor scan thread data", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_scan_thread_data); + mono_counters_register ("Minor finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_finish_gray_stack); + mono_counters_register ("Minor fragment creation", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_minor_fragment_creation); + + mono_counters_register ("Major fragment clear", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_pre_collection_fragment_clear); + mono_counters_register ("Major pinning", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_pinning); + mono_counters_register ("Major scan pinned", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_pinned); + mono_counters_register ("Major scan registered roots", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_registered_roots); + mono_counters_register ("Major scan thread data", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_thread_data); + mono_counters_register ("Major scan alloc_pinned", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_alloc_pinned); + mono_counters_register ("Major scan finalized", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_finalized); + mono_counters_register ("Major scan big objects", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_scan_big_objects); + mono_counters_register ("Major finish gray stack", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_finish_gray_stack); + mono_counters_register ("Major free big objects", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_free_bigobjs); + mono_counters_register ("Major LOS sweep", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_los_sweep); + mono_counters_register ("Major sweep", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_sweep); + mono_counters_register ("Major fragment creation", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &time_major_fragment_creation); mono_counters_register ("Number of pinned objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_pinned_objects); @@ -2559,7 +2248,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) if (xdomain_checks) { sgen_clear_nursery_fragments (); - check_for_xdomain_refs (); + sgen_check_for_xdomain_refs (); } nursery_section->next_data = nursery_next; @@ -2840,7 +2529,7 @@ major_copy_or_mark_from_roots (int *old_next_pin_slot, gboolean finish_up_concur if (xdomain_checks) { sgen_clear_nursery_fragments (); - check_for_xdomain_refs (); + sgen_check_for_xdomain_refs (); } if (!concurrent_collection_in_progress) { @@ -3326,6 +3015,7 @@ major_start_concurrent_collection (const char *reason) g_assert (num_objects_marked == 0); MONO_GC_CONCURRENT_START_BEGIN (GENERATION_OLD); + binary_protocol_concurrent_start (); // FIXME: store reason and pass it when finishing major_start_collection (TRUE, NULL); @@ -3346,6 +3036,7 @@ major_update_or_finish_concurrent_collection (gboolean force_finish) memset (&unpin_queue, 0, sizeof (unpin_queue)); MONO_GC_CONCURRENT_UPDATE_FINISH_BEGIN (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ()); + binary_protocol_concurrent_update_finish (); g_assert (sgen_gray_object_queue_is_empty (&gray_queue)); @@ -4113,7 +3804,10 @@ sgen_thread_register (SgenThreadInfo* info, void *addr) binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info)); + /* On win32, stack_start_limit should be 0, since the stack can grow dynamically */ +#ifndef HOST_WIN32 mono_thread_info_get_stack_bounds (&staddr, &stsize); +#endif if (staddr) { info->stack_start_limit = staddr; info->stack_end = staddr + stsize; @@ -4145,14 +3839,19 @@ sgen_thread_detach (SgenThreadInfo *p) * the thread */ if (mono_domain_get ()) - mono_thread_detach (mono_thread_current ()); + mono_thread_detach_internal (mono_thread_internal_current ()); } static void sgen_thread_unregister (SgenThreadInfo *p) { - binary_protocol_thread_unregister ((gpointer)mono_thread_info_get_tid (p)); - SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)mono_thread_info_get_tid (p)); + MonoNativeThreadId tid; + + tid = mono_thread_info_get_tid (p); + binary_protocol_thread_unregister ((gpointer)tid); + SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)tid); + + mono_threads_add_joinable_thread ((gpointer)tid); if (gc_callbacks.thread_detach_func) { gc_callbacks.thread_detach_func (p->runtime_data); @@ -4222,7 +3921,7 @@ mono_gc_pthread_detach (pthread_t thread) void mono_gc_pthread_exit (void *retval) { - mono_thread_info_dettach (); + mono_thread_info_detach (); pthread_exit (retval); } @@ -4276,12 +3975,12 @@ mono_gc_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count) HEAVY_STAT (++stat_wbarrier_arrayref_copy); /*This check can be done without taking a lock since dest_ptr array is pinned*/ if (ptr_in_nursery (dest_ptr) || count <= 0) { - mono_gc_memmove (dest_ptr, src_ptr, count * sizeof (gpointer)); + mono_gc_memmove_aligned (dest_ptr, src_ptr, count * sizeof (gpointer)); return; } -#ifdef SGEN_BINARY_PROTOCOL - { +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + if (binary_protocol_is_heavy_enabled ()) { int i; for (i = 0; i < count; ++i) { gpointer dest = (gpointer*)dest_ptr + i; @@ -4331,7 +4030,7 @@ find_object_for_ptr (char *ptr) * be called from gdb, so we don't care. */ found_obj = NULL; - major_collector.iterate_objects (TRUE, TRUE, find_object_for_ptr_callback, ptr); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, find_object_for_ptr_callback, ptr); return found_obj; } @@ -4426,7 +4125,7 @@ void mono_gc_wbarrier_value_copy_bitmap (gpointer _dest, gpointer _src, int size } } -#ifdef SGEN_BINARY_PROTOCOL +#ifdef SGEN_HEAVY_BINARY_PROTOCOL #undef HANDLE_PTR #define HANDLE_PTR(ptr,obj) do { \ gpointer o = *(gpointer*)(ptr); \ @@ -4455,12 +4154,12 @@ mono_gc_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass * if (ptr_in_nursery (dest) || ptr_on_stack (dest) || !SGEN_CLASS_HAS_REFERENCES (klass)) { size_t element_size = mono_class_value_size (klass, NULL); size_t size = count * element_size; - mono_gc_memmove (dest, src, size); + mono_gc_memmove_atomic (dest, src, size); return; } -#ifdef SGEN_BINARY_PROTOCOL - { +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + if (binary_protocol_is_heavy_enabled ()) { size_t element_size = mono_class_value_size (klass, NULL); int i; for (i = 0; i < count; ++i) { @@ -4488,13 +4187,14 @@ mono_gc_wbarrier_object_copy (MonoObject* obj, MonoObject *src) if (ptr_in_nursery (obj) || ptr_on_stack (obj)) { size = mono_object_class (obj)->instance_size; - mono_gc_memmove ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject), + mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject), size - sizeof (MonoObject)); return; } -#ifdef SGEN_BINARY_PROTOCOL - scan_object_for_binary_protocol_copy_wbarrier (obj, (char*)src, (mword) src->vtable->gc_descr); +#ifdef SGEN_HEAVY_BINARY_PROTOCOL + if (binary_protocol_is_heavy_enabled ()) + scan_object_for_binary_protocol_copy_wbarrier (obj, (char*)src, (mword) src->vtable->gc_descr); #endif remset.wbarrier_object_copy (obj, src); @@ -4579,7 +4279,7 @@ mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data) sgen_clear_nursery_fragments (); sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi, FALSE); - major_collector.iterate_objects (TRUE, TRUE, walk_references, &hwi); + major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, walk_references, &hwi); sgen_los_iterate_objects (walk_references, &hwi); return 0; @@ -4835,6 +4535,8 @@ mono_gc_base_init (void) } } while (result != 0); + SGEN_TV_GETTIME (sgen_init_timestamp); + LOCK_INIT (gc_mutex); pagesize = mono_pagesize (); @@ -4846,6 +4548,7 @@ mono_gc_base_init (void) cb.thread_attach = sgen_thread_attach; cb.mono_method_is_critical = (gpointer)is_critical_method; #ifndef HOST_WIN32 + cb.thread_exit = mono_gc_pthread_exit; cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create; #endif @@ -4876,6 +4579,8 @@ mono_gc_base_init (void) sgen_init_internal_allocator (); sgen_init_nursery_allocator (); sgen_init_fin_weak_hash (); + sgen_init_stw (); + sgen_init_hash_table (); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_SECTION, SGEN_SIZEOF_GC_MEM_SECTION); sgen_register_fixed_internal_mem_type (INTERNAL_MEM_FINALIZE_READY_ENTRY, sizeof (FinalizeReadyEntry)); @@ -5022,11 +4727,16 @@ mono_gc_base_init (void) } continue; } - if (g_str_has_prefix (opt, "bridge=")) { + if (g_str_has_prefix (opt, "bridge-implementation=")) { opt = strchr (opt, '=') + 1; - sgen_register_test_bridge_callbacks (g_strdup (opt)); + sgen_set_bridge_implementation (opt); continue; } + if (g_str_has_prefix (opt, "toggleref-test")) { + sgen_register_test_toggleref_callback (); + continue; + } + #ifdef USER_CONFIG if (g_str_has_prefix (opt, "nursery-size=")) { long val; @@ -5249,12 +4959,10 @@ mono_gc_base_init (void) fprintf (heap_dump_file, "\n"); do_pin_stats = TRUE; } -#ifdef SGEN_BINARY_PROTOCOL } else if (g_str_has_prefix (opt, "binary-protocol=")) { char *filename = strchr (opt, '=') + 1; binary_protocol_init (filename); -#endif - } else { + } else if (!sgen_bridge_handle_gc_debug (opt)) { sgen_env_var_error (MONO_GC_DEBUG_NAME, "Ignoring.", "Unknown option `%s`.", opt); if (usage_printed) @@ -5281,9 +4989,8 @@ mono_gc_base_init (void) fprintf (stderr, " print-allowance\n"); fprintf (stderr, " print-pinning\n"); fprintf (stderr, " heap-dump=\n"); -#ifdef SGEN_BINARY_PROTOCOL fprintf (stderr, " binary-protocol=\n"); -#endif + sgen_bridge_print_gc_debug_usage (); fprintf (stderr, "\n"); usage_printed = TRUE; @@ -5613,8 +5320,16 @@ sgen_get_remset (void) guint mono_gc_get_vtable_bits (MonoClass *class) { - if (sgen_need_bridge_processing () && sgen_is_bridge_class (class)) + /* FIXME move this to the bridge code */ + if (!sgen_need_bridge_processing ()) + return 0; + switch (sgen_bridge_class_kind (class)) { + case GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS: + case GC_BRIDGE_OPAQUE_BRIDGE_CLASS: return SGEN_GC_BIT_BRIDGE_OBJECT; + case GC_BRIDGE_OPAQUE_CLASS: + return SGEN_GC_BIT_BRIDGE_OPAQUE_OBJECT; + } return 0; } @@ -5643,4 +5358,12 @@ sgen_gc_event_moves (void) } } +gint64 +sgen_timestamp (void) +{ + SGEN_TV_DECLARE (timestamp); + SGEN_TV_GETTIME (timestamp); + return SGEN_TV_ELAPSED (sgen_init_timestamp, timestamp); +} + #endif /* HAVE_SGEN_GC */