return TRUE;
#ifndef DISABLE_REMOTING
- if (mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) &&
+ if (mono_defaults.real_proxy_class->supertypes && mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) &&
offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server))
return TRUE;
#endif
/* 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
++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);
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;
}
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;
}
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;
}
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_register_test_bridge_callbacks (g_strdup (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;
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;
+ }
return 0;
}