if (!array_fill_vtable) {
static MonoClass klass;
static char _vtable[sizeof(MonoVTable)+8];
- MonoVTable* vtable = (MonoVTable*) ALIGN_TO(_vtable, 8);
+ MonoVTable* vtable = (MonoVTable*) ALIGN_TO((mword)_vtable, 8);
gsize bmap;
MonoDomain *domain = mono_get_root_domain ();
/*Ephemerons and dislinks must be processed before LOS since they might end up pointing
to memory returned to the OS.*/
null_ephemerons_for_domain (domain);
-
- for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i) {
- sgen_null_links_if (object_in_domain_predicate, domain, i, FALSE);
- sgen_null_links_if (object_in_domain_predicate, domain, i, TRUE);
- }
+ sgen_null_links_for_domain (domain);
for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i)
sgen_remove_finalizers_if (object_in_domain_predicate, domain, i);
FOREACH_THREAD (info) {
int skip_reason = 0;
+ void *aligned_stack_start = (void*)(mword) ALIGN_TO ((mword)info->client_info.stack_start, SIZEOF_VOID_P);
+
if (info->client_info.skip) {
SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start);
skip_reason = 1;
g_assert (info->client_info.suspend_done);
SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
- mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, info->client_info.stack_start, info->client_info.stack_end, precise, &ctx);
+ mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, aligned_stack_start, info->client_info.stack_end, precise, &ctx);
} else if (!precise) {
if (!conservative_stack_mark) {
fprintf (stderr, "Precise stack mark not supported - disabling.\n");
conservative_stack_mark = TRUE;
}
- sgen_conservatively_pin_objects_from (info->client_info.stack_start, info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
+ sgen_conservatively_pin_objects_from (aligned_stack_start, info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
}
if (!precise) {
sgen_conservatively_pin_objects_from ((void**)&info->client_info.regs, (void**)&info->client_info.regs + ARCH_NUM_REGS,
start_nursery, end_nursery, PIN_TYPE_STACK);
#endif
+ {
+ // This is used on Coop GC for platforms where we cannot get the data for individual registers.
+ // We force a spill of all registers into the stack and pass a chunk of data into sgen.
+ MonoThreadUnwindState *state = mono_thread_info_get_suspend_state (info);
+ if (state && state->gc_stackdata) {
+ sgen_conservatively_pin_objects_from (state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
+ start_nursery, end_nursery, PIN_TYPE_STACK);
+ }
+ }
}
} END_FOREACH_THREAD
}
return SGEN_MAX_SMALL_OBJ_SIZE;
}
+gpointer
+sgen_client_default_metadata (void)
+{
+ return mono_domain_get ();
+}
+
+gpointer
+sgen_client_metadata_for_object (GCObject *obj)
+{
+ return mono_object_domain (obj);
+}
+
+/**
+ * mono_gchandle_is_in_domain:
+ * @gchandle: a GCHandle's handle.
+ * @domain: An application domain.
+ *
+ * Returns: true if the object wrapped by the @gchandle belongs to the specific @domain.
+ */
+gboolean
+mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
+{
+ MonoDomain *gchandle_domain = sgen_gchandle_get_metadata (gchandle);
+ return domain->domain_id == gchandle_domain->domain_id;
+}
+
+/**
+ * mono_gchandle_free_domain:
+ * @unloading: domain that is unloading
+ *
+ * Function used internally to cleanup any GC handle for objects belonging
+ * to the specified domain during appdomain unload.
+ */
void
-mono_gc_weak_link_register (volatile gpointer *link_addr, MonoObject *obj, gboolean track)
+mono_gchandle_free_domain (MonoDomain *unloading)
{
- binary_protocol_dislink_add ((gpointer)link_addr, obj, track);
+}
+
+static gpointer
+null_link_if_in_domain (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user)
+{
+ MonoDomain *unloading_domain = user;
+ MonoDomain *obj_domain;
+ gboolean is_weak = MONO_GC_HANDLE_TYPE_IS_WEAK (handle_type);
+ if (MONO_GC_HANDLE_IS_OBJECT_POINTER (hidden)) {
+ MonoObject *obj = MONO_GC_REVEAL_POINTER (hidden, is_weak);
+ obj_domain = mono_object_domain (obj);
+ } else {
+ obj_domain = MONO_GC_REVEAL_POINTER (hidden, is_weak);
+ }
+ if (unloading_domain->domain_id == obj_domain->domain_id)
+ return NULL;
+ return hidden;
}
void
-mono_gc_weak_link_unregister (volatile gpointer *link_addr, gboolean track)
+sgen_null_links_for_domain (MonoDomain *domain)
{
- binary_protocol_dislink_remove ((gpointer)link_addr, track);
+ guint type;
+ for (type = HANDLE_TYPE_MIN; type < HANDLE_TYPE_MAX; ++type)
+ sgen_gchandle_iterate (type, GENERATION_OLD, null_link_if_in_domain, domain);
}
void
-mono_gc_ensure_weak_links_accessible (void)
+mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
+{
+ sgen_gchandle_set_target (gchandle, obj);
+}
+
+void
+sgen_client_gchandle_created (int handle_type, GCObject *obj, guint32 handle)
+{
+#ifndef DISABLE_PERFCOUNTERS
+ mono_perfcounters->gc_num_handles++;
+#endif
+ mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_CREATED, handle_type, handle, obj);
+}
+
+void
+sgen_client_gchandle_destroyed (int handle_type, guint32 handle)
+{
+#ifndef DISABLE_PERFCOUNTERS
+ mono_perfcounters->gc_num_handles--;
+#endif
+ mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handle_type, handle, NULL);
+}
+
+void
+sgen_client_ensure_weak_gchandles_accessible (void)
{
/*
* During the second bridge processing step the world is
/* FIXME: A GC can occur after this check fails, in which case we
* should wait for bridge processing but would fail to do so.
*/
- mono_gc_wait_for_bridge_processing ();
-}
-
-void
-mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
-{
- sgen_gchandle_set_target (gchandle, obj);
+ if (G_UNLIKELY (bridge_processing_in_progress))
+ mono_gc_wait_for_bridge_processing ();
}
gboolean