#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"
#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;
}
}
-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[]) <IL 0x00020, 0xffffffff>
- * 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&) <IL 0x0003d, 0xffffffff>
- * 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) <IL 0x0004c, 0xffffffff>
- */
- 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)
{
}
}
-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)
{
/* 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
#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)
{
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
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);
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))
++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*/
*/
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);
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);
if (xdomain_checks) {
sgen_clear_nursery_fragments ();
- check_for_xdomain_refs ();
+ sgen_check_for_xdomain_refs ();
}
nursery_section->next_data = nursery_next;
if (xdomain_checks) {
sgen_clear_nursery_fragments ();
- check_for_xdomain_refs ();
+ sgen_check_for_xdomain_refs ();
}
if (!concurrent_collection_in_progress) {
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);
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));
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;
* 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);
void
mono_gc_pthread_exit (void *retval)
{
- mono_thread_info_dettach ();
+ mono_thread_info_detach ();
pthread_exit (retval);
}
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;
* 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;
}
}
}
-#ifdef SGEN_BINARY_PROTOCOL
+#ifdef SGEN_HEAVY_BINARY_PROTOCOL
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
gpointer o = *(gpointer*)(ptr); \
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) {
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);
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;
}
} while (result != 0);
+ SGEN_TV_GETTIME (sgen_init_timestamp);
+
LOCK_INIT (gc_mutex);
pagesize = mono_pagesize ();
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
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));
}
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;
fprintf (heap_dump_file, "<sgen-dump>\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)
fprintf (stderr, " print-allowance\n");
fprintf (stderr, " print-pinning\n");
fprintf (stderr, " heap-dump=<filename>\n");
-#ifdef SGEN_BINARY_PROTOCOL
fprintf (stderr, " binary-protocol=<filename>\n");
-#endif
+ sgen_bridge_print_gc_debug_usage ();
fprintf (stderr, "\n");
usage_printed = TRUE;
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;
}
}
}
+gint64
+sgen_timestamp (void)
+{
+ SGEN_TV_DECLARE (timestamp);
+ SGEN_TV_GETTIME (timestamp);
+ return SGEN_TV_ELAPSED (sgen_init_timestamp, timestamp);
+}
+
#endif /* HAVE_SGEN_GC */