未验证 提交 25be848b 编写于 作者: V Vlad Brezae 提交者: GitHub

[mono][sgen] Remove old code associated with domain unload (#84242)

* [mono][sgen] Remove unused suspend finalizers functionality

* [mono][sgen] Remove threadpool shutdown logic

No longer used

* [mono][sgen] Remove logic associated with gc shutdown

* [mono][sgen] Remove logic for clearing handle stack during cleanup

* [mono][sgen] Remove code for xdomain checks

* [mono][sgen] Remove more code associated with finalization

* [mono][sgen] Remove code for freeing objects during domain unload

* [mono][sgen] Remove mono_gc_clear_domain

It is dead code
上级 e579ccb6
......@@ -205,12 +205,6 @@ mono_gc_base_init (void)
gc_initialized = TRUE;
}
void
mono_gc_base_cleanup (void)
{
GC_set_finalizer_notifier (NULL);
}
void
mono_gc_init_icalls (void)
{
......@@ -893,16 +887,6 @@ mono_gc_wbarrier_object_copy_internal (MonoObject* obj, MonoObject *src)
m_class_get_instance_size (mono_object_class (obj)) - MONO_ABI_SIZEOF (MonoObject));
}
void
mono_gc_clear_domain (MonoDomain *domain)
{
}
void
mono_gc_suspend_finalizers (void)
{
}
int
mono_gc_get_suspend_signal (void)
{
......
......@@ -69,7 +69,6 @@ mono_object_register_finalizer_handle (MonoObjectHandle obj);
extern void mono_gc_init (void);
MONO_COMPONENT_API extern void mono_gc_base_init (void);
extern void mono_gc_base_cleanup (void);
extern void mono_gc_init_icalls (void);
/*
......@@ -176,10 +175,6 @@ MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor
MONO_COMPONENT_API void mono_gc_deregister_root (char* addr);
void mono_gc_finalize_domain (MonoDomain *domain);
void mono_gc_run_finalize (void *obj, void *data);
void mono_gc_clear_domain (MonoDomain * domain);
/* Signal early termination of finalizer processing inside the gc */
void mono_gc_suspend_finalizers (void);
/*
* Register a root which can only be written using a write barrier.
......
......@@ -246,36 +246,6 @@ mono_handle_stack_free (HandleStack *stack)
free_handle_stack (stack);
}
void
mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain)
{
/* Called by the GC while clearing out objects of the given domain from the heap. */
/* If there are no handles-related bugs, there is nothing to do: if a
* thread accessed objects from the domain it was aborted, so any
* threads left alive cannot have any handles that point into the
* unloading domain. However if there is a handle leak, the handle stack is not */
if (!stack)
return;
/* Root domain only unloaded when mono is shutting down, don't need to check anything */
if (domain == mono_get_root_domain () || mono_runtime_is_shutting_down ())
return;
HandleChunk *cur = stack->bottom;
HandleChunk *last = stack->top;
if (!cur)
return;
while (cur) {
for (int idx = 0; idx < cur->size; ++idx) {
HandleChunkElem *elem = &cur->elems[idx];
if (!elem->o)
continue;
g_assert (mono_object_domain (elem->o) != domain);
}
if (cur == last)
break;
cur = cur->next;
}
}
static void
check_handle_stack_monotonic (HandleStack *stack)
{
......
......@@ -135,7 +135,6 @@ HandleStack* mono_handle_stack_alloc (void);
void mono_handle_stack_free (HandleStack *handlestack);
MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
MONO_COMPONENT_API MonoThreadInfo* mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
void mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain);
#ifdef MONO_HANDLE_TRACK_SP
void mono_handle_chunk_leak_check (HandleStack *handles);
......
......@@ -1108,20 +1108,6 @@ mono_monitor_exit (MonoObject *obj)
MONO_EXTERNAL_ONLY_VOID (mono_monitor_exit_internal (obj));
}
MonoGCHandle
mono_monitor_get_object_monitor_gchandle (MonoObject *object)
{
LockWord lw;
lw.sync = object->synchronisation;
if (lock_word_is_inflated (lw)) {
MonoThreadsSync *mon = lock_word_get_inflated_lock (lw);
return (MonoGCHandle)mon->data;
}
return NULL;
}
/*
* mono_monitor_threads_sync_member_offset:
* @status_offset: returns size and offset of the "status" member
......
......@@ -122,9 +122,6 @@ ICALL_EXPORT
guint32
mono_monitor_enter_v4_fast (MonoObject *obj, MonoBoolean *lock_taken);
MonoGCHandle
mono_monitor_get_object_monitor_gchandle (MonoObject *object);
void
mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset);
#define MONO_THREADS_SYNC_MEMBER_OFFSET(o) ((o)>>8)
......
......@@ -205,28 +205,6 @@ sgen_client_update_copied_object (char *destination, GCVTable gc_vtable, void *o
mono_sgen_register_moved_object (obj, destination);
}
#ifdef XDOMAIN_CHECKS_IN_WBARRIER
extern gboolean sgen_mono_xdomain_checks;
#define sgen_client_wbarrier_generic_nostore_check(ptr) do { \
/* FIXME: ptr_in_heap must be called with the GC lock held */ \
if (sgen_mono_xdomain_checks && *(MonoObject**)ptr && ptr_in_heap (ptr)) { \
char *start = find_object_for_ptr (ptr); \
MonoObject *value = *(MonoObject**)ptr; \
LOCK_GC; \
SGEN_ASSERT (0, start, "Write barrier outside an object?"); \
if (start) { \
MonoObject *obj = (MonoObject*)start; \
if (obj->vtable->domain != value->vtable->domain) \
SGEN_ASSERT (0, is_xdomain_ref_allowed (ptr, start, obj->vtable->domain), "Cross-domain ref not allowed"); \
} \
UNLOCK_GC; \
} \
} while (0)
#else
#define sgen_client_wbarrier_generic_nostore_check(ptr)
#endif
static gboolean G_GNUC_UNUSED
sgen_client_object_has_critical_finalizer (GCObject *obj)
{
......@@ -738,7 +716,6 @@ gboolean sgen_is_managed_allocator (MonoMethod *method);
gboolean sgen_has_managed_allocator (void);
void sgen_disable_native_stack_scan (void);
void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type);
void sgen_null_links_for_domain (MonoDomain *domain);
#endif
......@@ -55,8 +55,6 @@ static guint64 los_array_remsets;
/* If set, mark stacks conservatively, even if precise marking is possible */
static gboolean conservative_stack_mark = FALSE;
/* If set, check that there are no references to the domain left at domain unload */
gboolean sgen_mono_xdomain_checks = FALSE;
/* Functions supplied by the runtime to be called by the GC */
static MonoGCCallbacks gc_callbacks;
......@@ -509,17 +507,6 @@ mono_gc_register_for_finalization (MonoObject *obj, MonoFinalizationProc user_da
sgen_object_register_for_finalization (obj, user_data);
}
static gboolean
object_in_domain_predicate (MonoObject *obj, void *user_data)
{
MonoDomain *domain = (MonoDomain *)user_data;
if (mono_object_domain (obj) == domain) {
SGEN_LOG (5, "Unregistering finalizer for object: %p (%s)", obj, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (obj)));
return TRUE;
}
return FALSE;
}
/**
* mono_gc_finalizers_for_domain:
* \param domain the unloading appdomain
......@@ -531,13 +518,7 @@ object_in_domain_predicate (MonoObject *obj, void *user_data)
void
mono_gc_finalize_domain (MonoDomain *domain)
{
sgen_finalize_if (object_in_domain_predicate, domain);
}
void
mono_gc_suspend_finalizers (void)
{
sgen_set_suspend_finalizers ();
sgen_finalize_all ();
}
/*
......@@ -558,35 +539,6 @@ typedef struct {
static EphemeronLinkNode *ephemeron_list;
/* LOCKING: requires that the GC lock is held */
static MONO_PERMIT (need (sgen_gc_locked)) void
null_ephemerons_for_domain (MonoDomain *domain)
{
EphemeronLinkNode *current = ephemeron_list, *prev = NULL;
while (current) {
MonoObject *object = (MonoObject*)current->array;
if (object)
SGEN_ASSERT (0, object->vtable, "Can't have objects without vtables.");
if (object && object->vtable->domain == domain) {
EphemeronLinkNode *tmp = current;
if (prev)
prev->next = current->next;
else
ephemeron_list = current->next;
current = current->next;
sgen_free_internal (tmp, INTERNAL_MEM_EPHEMERON_LINK);
} else {
prev = current;
current = current->next;
}
}
}
/* LOCKING: requires that the GC lock is held */
void
sgen_client_clear_unreachable_ephemerons (ScanCopyContext ctx)
......@@ -728,172 +680,6 @@ mono_gc_ephemeron_array_add (MonoObject *obj)
return TRUE;
}
/*
* Appdomain handling
*/
static gboolean
need_remove_object_for_domain (GCObject *start, MonoDomain *domain)
{
if (mono_object_domain (start) == domain) {
SGEN_LOG (4, "Need to cleanup object %p", start);
sgen_binary_protocol_cleanup (start, (gpointer)SGEN_LOAD_VTABLE (start), sgen_safe_object_get_size ((GCObject*)start));
return TRUE;
}
return FALSE;
}
static void
process_object_for_domain_clearing (GCObject *start, MonoDomain *domain)
{
MonoVTable *vt = SGEN_LOAD_VTABLE (start);
if (vt->klass == mono_defaults.internal_thread_class)
g_assert (mono_object_domain (start) == mono_get_root_domain ());
}
static gboolean
clear_domain_process_object (GCObject *obj, MonoDomain *domain)
{
gboolean remove;
process_object_for_domain_clearing (obj, domain);
remove = need_remove_object_for_domain (obj, domain);
if (remove && obj->synchronisation) {
MonoGCHandle dislink = mono_monitor_get_object_monitor_gchandle (obj);
if (dislink)
mono_gchandle_free_internal (dislink);
}
return remove;
}
static void
clear_domain_process_minor_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
if (clear_domain_process_object (obj, domain)) {
CANARIFY_SIZE (size);
memset (obj, 0, size);
}
}
static void
clear_domain_process_major_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
clear_domain_process_object (obj, domain);
}
static void
clear_domain_free_major_non_pinned_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
if (need_remove_object_for_domain (obj, domain))
sgen_major_collector.free_non_pinned_object (obj, size);
}
static void
clear_domain_free_major_pinned_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
if (need_remove_object_for_domain (obj, domain))
sgen_major_collector.free_pinned_object (obj, size);
}
static void
clear_domain_process_los_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
clear_domain_process_object (obj, domain);
}
static gboolean
clear_domain_free_los_object_callback (GCObject *obj, size_t size, MonoDomain *domain)
{
return need_remove_object_for_domain (obj, domain);
}
static void
sgen_finish_concurrent_work (const char *reason, gboolean stw)
{
if (sgen_get_concurrent_collection_in_progress ())
sgen_perform_collection (0, GENERATION_OLD, reason, TRUE, stw);
SGEN_ASSERT (0, !sgen_get_concurrent_collection_in_progress (), "We just ordered a synchronous collection. Why are we collecting concurrently?");
sgen_major_collector.finish_sweeping ();
}
/*
* When appdomains are unloaded we can easily remove objects that have finalizers,
* but all the others could still be present in random places on the heap.
* We need a sweep to get rid of them even though it's going to be costly
* with big heaps.
* The reason we need to remove them is because we access the vtable and class
* structures to know the object size and the reference bitmap: once the domain is
* unloaded the point to random memory.
*/
void
mono_gc_clear_domain (MonoDomain * domain)
{
int i;
LOCK_GC;
sgen_binary_protocol_domain_unload_begin (domain);
sgen_stop_world (0, FALSE);
sgen_finish_concurrent_work ("clear domain", FALSE);
sgen_process_fin_stage_entries ();
sgen_clear_nursery_fragments ();
FOREACH_THREAD_ALL (info) {
mono_handle_stack_free_domain (info->client_info.info.handle_stack, domain);
} FOREACH_THREAD_END
if (sgen_mono_xdomain_checks && domain != mono_get_root_domain ()) {
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
to memory returned to the OS.*/
null_ephemerons_for_domain (domain);
sgen_null_links_for_domain (domain);
for (i = GENERATION_NURSERY; i < GENERATION_MAX; ++i)
sgen_remove_finalizers_if (object_in_domain_predicate, domain, i);
sgen_scan_area_with_callback (sgen_nursery_section->data, sgen_nursery_section->end_data,
(IterateObjectCallbackFunc)clear_domain_process_minor_object_callback, domain, FALSE, TRUE);
/* We need two passes over major and large objects because
freeing such objects might give their memory back to the OS
(in the case of large objects) or obliterate its vtable
(pinned objects with major-copying or pinned and non-pinned
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. */
sgen_major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)clear_domain_process_major_object_callback, domain);
sgen_los_iterate_objects ((IterateObjectCallbackFunc)clear_domain_process_los_object_callback, domain);
sgen_los_iterate_objects_free ((IterateObjectResultCallbackFunc)clear_domain_free_los_object_callback, domain);
sgen_major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_NON_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_non_pinned_object_callback, domain);
sgen_major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_PINNED, (IterateObjectCallbackFunc)clear_domain_free_major_pinned_object_callback, domain);
if (domain == mono_get_root_domain ()) {
sgen_pin_stats_report ();
sgen_object_layout_dump (stdout);
}
sgen_restart_world (0, FALSE);
sgen_binary_protocol_domain_unload_end (domain);
sgen_binary_protocol_flush_buffers (FALSE);
UNLOCK_GC;
}
/*
* Allocation
*/
......@@ -2770,31 +2556,6 @@ mono_gchandle_get_target_internal (MonoGCHandle gchandle)
return sgen_gchandle_get_target (MONO_GC_HANDLE_TO_UINT (gchandle));
}
static gpointer
null_link_if_in_domain (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user)
{
MonoDomain *unloading_domain = (MonoDomain *)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 = (MonoObject *)MONO_GC_REVEAL_POINTER (hidden, is_weak);
obj_domain = mono_object_domain (obj);
} else {
obj_domain = (MonoDomain *)MONO_GC_REVEAL_POINTER (hidden, is_weak);
}
if (unloading_domain->domain_id == obj_domain->domain_id)
return NULL;
return hidden;
}
void
sgen_null_links_for_domain (MonoDomain *domain)
{
guint type;
for (type = HANDLE_TYPE_MIN; type < HANDLE_TYPE_MAX; ++type)
sgen_gchandle_iterate ((GCHandleType)type, GENERATION_OLD, null_link_if_in_domain, domain);
}
void
mono_gchandle_set_target (MonoGCHandle gchandle, MonoObject *obj)
{
......@@ -2919,15 +2680,6 @@ sgen_client_description_for_internal_mem_type (int type)
}
}
void
sgen_client_pre_collection_checks (void)
{
if (sgen_mono_xdomain_checks) {
sgen_clear_nursery_fragments ();
sgen_check_for_xdomain_refs ();
}
}
gboolean
sgen_client_vtable_is_inited (MonoVTable *vt)
{
......@@ -3012,9 +2764,7 @@ sgen_client_print_gc_params_usage (void)
gboolean
sgen_client_handle_gc_debug (const char *opt)
{
if (!strcmp (opt, "xdomain-checks")) {
sgen_mono_xdomain_checks = TRUE;
} else if (!strcmp (opt, "do-not-finalize")) {
if (!strcmp (opt, "do-not-finalize")) {
mono_do_not_finalize = TRUE;
} else if (g_str_has_prefix (opt, "do-not-finalize=")) {
opt = strchr (opt, '=') + 1;
......@@ -3040,7 +2790,6 @@ sgen_client_handle_gc_debug (const char *opt)
void
sgen_client_print_gc_debug_usage (void)
{
fprintf (stderr, " xdomain-checks\n");
fprintf (stderr, " do-not-finalize\n");
fprintf (stderr, " log-finalizers\n");
fprintf (stderr, " no-managed-allocator\n");
......@@ -3103,24 +2852,6 @@ mono_gc_base_init (void)
gc_inited = TRUE;
}
void
mono_gc_base_cleanup (void)
{
/*
* Note we don't fully cleanup the GC here, but the threads mainly.
*
* We need to finish any work on the sgen threads before shutting down
* the sgen threadpool. After this point we can still trigger GCs as
* part of domain free, but they should all be forced and not use the
* threadpool.
*/
sgen_finish_concurrent_work ("cleanup", TRUE);
sgen_thread_pool_shutdown ();
// We should have consumed any outstanding moves.
g_assert (sgen_pointer_queue_is_empty (&moved_objects_queue));
}
gboolean
mono_gc_is_null (void)
{
......
......@@ -162,12 +162,6 @@ gboolean sgen_client_vtable_is_inited (GCVTable vtable);
const char* sgen_client_vtable_get_namespace (GCVTable vtable);
const char* sgen_client_vtable_get_name (GCVTable vtable);
/*
* Called before starting collections. The world is already stopped. No action is
* necessary.
*/
void sgen_client_pre_collection_checks (void);
/*
* Must set the thread's thread info to `info`. If the thread's small ID was not already
* initialized in `sgen_client_init()` (for the main thread, usually), it must be done here.
......
......@@ -80,12 +80,6 @@ typedef target_mword SgenDescriptor;
*/
//#define SGEN_CHECK_UPDATE_REFERENCE
/*
* Define this and use the "xdomain-checks" MONO_GC_DEBUG option to
* have cross-domain checks in the write barrier.
*/
//#define XDOMAIN_CHECKS_IN_WBARRIER
/*
* Define this to get number of objects marked information in the
* concurrent GC DTrace probes. Has a small performance impact, so
......@@ -105,11 +99,9 @@ typedef target_mword SgenDescriptor;
#ifndef SGEN_HEAVY_BINARY_PROTOCOL
#ifndef HEAVY_STATISTICS
#define MANAGED_ALLOCATION
#ifndef XDOMAIN_CHECKS_IN_WBARRIER
#define MANAGED_WBARRIER
#endif
#endif
#endif
#if defined (HOST_WASM) || defined(TARGET_WASM)
#define DEFAULT_MAJOR SGEN_MAJOR_SERIAL
......
......@@ -860,167 +860,6 @@ mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise)
find_pinning_ref_from_thread ((char*)key, sizeof (GCObject));
}
#ifndef SGEN_WITHOUT_MONO
static MonoDomain *check_domain = NULL;
static void
check_obj_not_in_domain (MonoObject **o)
{
g_assert (((*o))->vtable->domain != check_domain);
}
static void
check_obj_not_in_domain_callback (GCObject **o, void *gc_data)
{
g_assert ((*o)->vtable->domain != check_domain);
}
void
sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
{
void **start_root;
RootRecord *root;
check_domain = domain;
SGEN_HASH_TABLE_FOREACH (&sgen_roots_hash [root_type], void **, start_root, RootRecord *, root) {
SgenDescriptor 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 ((MonoObject **)*start_root);
desc >>= 1;
start_root++;
}
break;
case ROOT_DESC_COMPLEX: {
gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
int bwords = (int)((*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 ((MonoObject **)*objptr);
bmap >>= 1;
++objptr;
}
start_run += GC_BITS_PER_WORD;
}
break;
}
case ROOT_DESC_VECTOR: {
void **p;
for (p = start_root; p < (void**)root->end_root; p++) {
if (*p)
check_obj_not_in_domain ((MonoObject **)*p);
}
break;
}
case ROOT_DESC_USER: {
SgenUserRootMarkFunc marker = sgen_get_user_descriptor_func (desc);
marker (start_root, check_obj_not_in_domain_callback, NULL);
break;
}
case ROOT_DESC_RUN_LEN:
g_assert_not_reached ();
default:
g_assert_not_reached ();
}
} SGEN_HASH_TABLE_FOREACH_END;
check_domain = NULL;
}
static gboolean
is_xdomain_ref_allowed (GCObject **ptr, GCObject *obj, MonoDomain *domain)
{
return FALSE;
}
static void
check_reference_for_xdomain (GCObject **ptr, GCObject *obj, MonoDomain *domain)
{
MonoObject *ref = *ptr;
size_t offset = (char*)(ptr) - (char*)obj;
MonoClass *klass;
MonoClassField *field;
char *str;
if (!ref || ref->vtable->domain == domain)
return;
if (is_xdomain_ref_allowed (ptr, obj, domain))
return;
field = NULL;
for (klass = obj->vtable->klass; klass; klass = m_class_get_parent (klass)) {
gpointer iter = NULL;
MonoClassField *cur;
while ((cur = mono_class_get_fields_internal (klass, &iter))) {
/* metadata-update: there are no domains in .NET */
g_assert (!m_field_is_from_update (cur));
if (m_field_get_offset (cur) == offset) {
field = cur;
break;
}
}
if (field)
break;
}
if (ref->vtable->klass == mono_defaults.string_class) {
ERROR_DECL (error);
str = mono_string_to_utf8_checked_internal ((MonoString*)ref, error);
mono_error_cleanup (error);
} else
str = NULL;
g_print ("xdomain reference in %p (%s.%s) at offset %zu (%s) to %p (%s.%s) (%s) - pointed to by:\n",
obj, m_class_get_name_space (obj->vtable->klass), m_class_get_name (obj->vtable->klass),
offset, field ? field->name : "",
ref, m_class_get_name_space (ref->vtable->klass), m_class_get_name (ref->vtable->klass), str ? str : "");
mono_gc_scan_for_specific_ref (obj, 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 (GCObject *obj, mword size, void *data)
{
char *start = (char*)obj;
MonoVTable *vtable = SGEN_LOAD_VTABLE (obj);
MonoDomain *domain = vtable->domain;
SgenDescriptor desc = sgen_vtable_get_descriptor (vtable);
#include "sgen-scan-object.h"
}
void
sgen_check_for_xdomain_refs (void)
{
sgen_scan_area_with_callback (sgen_nursery_section->data, sgen_nursery_section->end_data,
(IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL, FALSE, TRUE);
sgen_major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
sgen_los_iterate_objects ((IterateObjectCallbackFunc)scan_object_for_xdomain_refs, NULL);
}
#endif
/* If not null, dump the heap after each collection into this file */
static FILE *heap_dump_file = NULL;
......@@ -1209,11 +1048,6 @@ sgen_find_object_for_ptr (char *ptr)
#else
void
sgen_check_for_xdomain_refs (void)
{
}
void
sgen_check_heap_marked (gboolean nursery_must_be_pinned)
{
......@@ -1269,10 +1103,5 @@ sgen_dump_occupied (char *start, char *end, char *section_start)
{
}
void
sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type)
{
}
#endif /*DISABLE_SGEN_DEBUG_HELPERS */
#endif /*HAVE_SGEN_GC*/
......@@ -568,7 +568,7 @@ sgen_object_register_for_finalization (GCObject *obj, SGenFinalizationProc user_
/* LOCKING: requires that the GC lock is held */
static MONO_PERMIT (need (sgen_gc_locked)) void
finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, SgenHashTable *hash_table)
finalize_all (SgenHashTable *hash_table)
{
GCObject *object;
gpointer dummy G_GNUC_UNUSED;
......@@ -578,15 +578,10 @@ finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, Sge
SGEN_HASH_TABLE_FOREACH (hash_table, GCObject *, object, gpointer, dummy) {
object = tagged_object_get_object (object);
if (predicate (object, user_data)) {
/* remove and put in out_array */
SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
sgen_queue_finalization_entry (object);
SGEN_LOG (5, "Enqueuing object for finalization: %p (%s) (%d)", object, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (object)), sgen_hash_table_num_entries (hash_table));
}
if (sgen_suspend_finalizers)
break;
/* remove and put in out_array */
SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
sgen_queue_finalization_entry (object);
SGEN_LOG (5, "Enqueuing object for finalization: %p (%s) (%d)", object, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (object)), sgen_hash_table_num_entries (hash_table));
} SGEN_HASH_TABLE_FOREACH_END;
}
......@@ -607,32 +602,15 @@ finalize_with_predicate (SgenObjectPredicateFunc predicate, void *user_data, Sge
* objects are still alive.
*/
void
sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data)
sgen_finalize_all ()
{
LOCK_GC;
sgen_process_fin_stage_entries ();
finalize_with_predicate (predicate, user_data, &minor_finalizable_hash);
finalize_with_predicate (predicate, user_data, &major_finalizable_hash);
finalize_all (&minor_finalizable_hash);
finalize_all (&major_finalizable_hash);
UNLOCK_GC;
}
void
sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, int generation)
{
SgenHashTable *hash_table = get_finalize_entry_hash_table (generation);
GCObject *object;
gpointer dummy G_GNUC_UNUSED;
SGEN_HASH_TABLE_FOREACH (hash_table, GCObject *, object, gpointer, dummy) {
object = tagged_object_get_object (object);
if (predicate (object, user_data)) {
SGEN_HASH_TABLE_FOREACH_REMOVE (TRUE);
continue;
}
} SGEN_HASH_TABLE_FOREACH_END;
}
void
sgen_init_fin_weak_hash (void)
{
......
......@@ -1839,8 +1839,6 @@ collect_nursery (const char *reason, gboolean is_overflow)
TV_GETTIME (btv);
time_minor_pre_collection_fragment_clear += TV_ELAPSED (atv, btv);
sgen_client_pre_collection_checks ();
sgen_major_collector.start_nursery_collection ();
sgen_memgov_minor_collection_start ();
......@@ -2078,8 +2076,6 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_
objects_pinned = 0;
sgen_client_pre_collection_checks ();
if (mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) {
/* Remsets are not useful for a major collection */
remset.clear_cards ();
......@@ -2844,13 +2840,6 @@ sgen_object_is_live (GCObject *obj)
*/
static volatile gboolean pending_unqueued_finalizer = FALSE;
volatile gboolean sgen_suspend_finalizers = FALSE;
void
sgen_set_suspend_finalizers (void)
{
sgen_suspend_finalizers = TRUE;
}
int
sgen_gc_invoke_finalizers (void)
......@@ -2906,8 +2895,6 @@ sgen_gc_invoke_finalizers (void)
gboolean
sgen_have_pending_finalizers (void)
{
if (sgen_suspend_finalizers)
return FALSE;
return pending_unqueued_finalizer || !sgen_pointer_queue_is_empty (&fin_ready_queue) || !sgen_pointer_queue_is_empty (&critical_fin_queue);
}
......@@ -3153,8 +3140,6 @@ mono_gc_wbarrier_generic_nostore_internal (gpointer ptr)
HEAVY_STAT (++stat_wbarrier_generic_store);
sgen_client_wbarrier_generic_nostore_check (ptr);
obj = *(gpointer*)ptr;
if (obj)
sgen_binary_protocol_wbarrier (ptr, obj, (gpointer)LOAD_VTABLE (obj));
......
......@@ -688,7 +688,6 @@ struct _SgenMajorCollector {
GCObject* (*alloc_object) (GCVTable vtable, size_t size, gboolean has_references);
GCObject* (*alloc_object_par) (GCVTable vtable, size_t size, gboolean has_references);
void (*free_pinned_object) (GCObject *obj, size_t size);
/*
* This is used for domain unloading, heap walking from the logging profiler, and
......@@ -696,7 +695,6 @@ struct _SgenMajorCollector {
*/
void (*iterate_objects) (IterateObjectsFlags flags, IterateObjectCallbackFunc callback, void *data);
void (*free_non_pinned_object) (GCObject *obj, size_t size);
void (*pin_objects) (SgenGrayQueue *queue);
void (*pin_major_object) (GCObject *obj, SgenGrayQueue *queue);
void (*scan_card_table) (CardTableScanType scan_type, ScanCopyContext ctx, int job_index, int job_split_count, int block_count);
......@@ -902,10 +900,8 @@ typedef void (*SGenFinalizationProc)(gpointer, gpointer); // same as MonoFinaliz
void sgen_object_register_for_finalization (GCObject *obj, SGenFinalizationProc user_data)
MONO_PERMIT (need (sgen_lock_gc));
void sgen_finalize_if (SgenObjectPredicateFunc predicate, void *user_data)
void sgen_finalize_all (void)
MONO_PERMIT (need (sgen_lock_gc));
void sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, int generation);
void sgen_set_suspend_finalizers (void);
void sgen_wbroots_iterate_live_block_ranges (sgen_cardtable_block_callback cb);
void sgen_wbroots_scan_card_table (ScanCopyContext ctx);
......@@ -1106,7 +1102,6 @@ extern NurseryClearPolicy sgen_nursery_clear_policy;
extern gboolean sgen_try_free_some_memory;
extern mword sgen_total_promoted_size;
extern mword sgen_total_allocated_major;
extern volatile gboolean sgen_suspend_finalizers;
extern MonoCoopMutex sgen_gc_mutex;
#ifndef DISABLE_SGEN_MAJOR_MARKSWEEP_CONC
extern volatile gboolean sgen_concurrent_collection_in_progress;
......@@ -1160,7 +1155,6 @@ void sgen_check_whole_heap_stw (void)
void sgen_check_objref (char *obj);
void sgen_check_heap_marked (gboolean nursery_must_be_pinned);
void sgen_check_nursery_objects_untag (void);
void sgen_check_for_xdomain_refs (void);
GCObject* sgen_find_object_for_ptr (char *ptr);
void mono_gc_scan_for_specific_ref (GCObject *key, gboolean precise);
......
......@@ -772,48 +772,6 @@ get_block:
return (GCObject *)obj;
}
/*
* We're not freeing the block if it's empty. We leave that work for
* the next major collection.
*
* This is just called from the domain clearing code, which runs in a
* single thread and has the GC lock, so we don't need an extra lock.
*/
static void
free_object (GCObject *obj, size_t size, gboolean pinned)
{
MSBlockInfo *block = MS_BLOCK_FOR_OBJ (obj);
int word, bit;
gboolean in_free_list;
SGEN_ASSERT (9, sweep_state == SWEEP_STATE_SWEPT, "Should have waited for sweep to free objects.");
ensure_can_access_block_free_list (block);
SGEN_ASSERT (9, (pinned && block->pinned) || (!pinned && !block->pinned), "free-object pinning mixup object %p pinned %d block %p pinned %d", obj, pinned, block, block->pinned);
SGEN_ASSERT (9, MS_OBJ_ALLOCED (obj, block), "object %p is already free", obj);
MS_CALC_MARK_BIT (word, bit, obj);
SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p has mark bit set", obj);
memset (obj, 0, size);
in_free_list = !!block->free_list;
*(void**)obj = block->free_list;
block->free_list = (void**)obj;
if (!in_free_list) {
MSBlockInfo * volatile *free_blocks = FREE_BLOCKS (pinned, block->has_references);
int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
SGEN_ASSERT (9, !block->next_free, "block %p doesn't have a free-list of object but belongs to a free-list of blocks", block);
add_free_block (free_blocks, size_index, block);
}
}
static void
major_free_non_pinned_object (GCObject *obj, size_t size)
{
free_object (obj, size, FALSE);
}
/* size is a multiple of SGEN_ALLOC_ALIGN */
static GCObject*
major_alloc_small_pinned_obj (GCVTable vtable, size_t size, gboolean has_references)
......@@ -831,12 +789,6 @@ major_alloc_small_pinned_obj (GCVTable vtable, size_t size, gboolean has_referen
return (GCObject *)res;
}
static void
free_pinned_object (GCObject *obj, size_t size)
{
free_object (obj, size, TRUE);
}
/*
* size is already rounded up and we hold the GC lock.
*/
......@@ -2922,9 +2874,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
#ifndef DISABLE_SGEN_MAJOR_MARKSWEEP_CONC
collector->alloc_object_par = major_alloc_object_par;
#endif
collector->free_pinned_object = free_pinned_object;
collector->iterate_objects = major_iterate_objects;
collector->free_non_pinned_object = major_free_non_pinned_object;
collector->pin_objects = major_pin_objects;
collector->pin_major_object = pin_major_object;
collector->scan_card_table = major_scan_card_table;
......
......@@ -25,9 +25,6 @@ static int threads_num;
static MonoNativeThreadId threads [SGEN_THREADPOOL_MAX_NUM_THREADS];
static int threads_context [SGEN_THREADPOOL_MAX_NUM_THREADS];
static volatile gboolean threadpool_shutdown;
static volatile int threads_finished;
static int contexts_num;
static SgenThreadPoolContext pool_contexts [SGEN_THREADPOOL_MAX_NUM_CONTEXTS];
......@@ -129,7 +126,7 @@ has_priority_work (int worker_index, int current_context)
static void
get_work (int worker_index, int *work_context, int *do_idle, SgenThreadPoolJob **job)
{
while (!threadpool_shutdown) {
while (TRUE) {
int i;
for (i = 0; i < contexts_num; i++) {
......@@ -198,10 +195,8 @@ thread_func (void *data)
get_work (worker_index, &current_context, &do_idle, &job);
threads_context [worker_index] = current_context;
if (!threadpool_shutdown) {
context = &pool_contexts [current_context];
thread_data = (context->thread_datas) ? context->thread_datas [worker_index] : NULL;
}
context = &pool_contexts [current_context];
thread_data = (context->thread_datas) ? context->thread_datas [worker_index] : NULL;
mono_os_mutex_unlock (&lock);
......@@ -230,12 +225,7 @@ thread_func (void *data)
if (!do_idle)
mono_os_cond_signal (&done_cond);
} else {
SGEN_ASSERT (0, threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
mono_os_mutex_lock (&lock);
threads_finished++;
mono_os_cond_signal (&done_cond);
mono_os_mutex_unlock (&lock);
return 0;
g_assert_not_reached ();
}
}
......@@ -288,36 +278,11 @@ sgen_thread_pool_start (void)
mono_os_cond_init (&work_cond);
mono_os_cond_init (&done_cond);
threads_finished = 0;
threadpool_shutdown = FALSE;
for (i = 0; i < threads_num; i++) {
mono_native_thread_create (&threads [i], (gpointer)thread_func, (void*)(gsize)i);
}
}
void
sgen_thread_pool_shutdown (void)
{
if (!threads_num)
return;
mono_os_mutex_lock (&lock);
threadpool_shutdown = TRUE;
mono_os_cond_broadcast (&work_cond);
while (threads_finished < threads_num)
mono_os_cond_wait (&done_cond, &lock);
mono_os_mutex_unlock (&lock);
mono_os_mutex_destroy (&lock);
mono_os_cond_destroy (&work_cond);
mono_os_cond_destroy (&done_cond);
for (int i = 0; i < threads_num; i++) {
mono_threads_add_joinable_thread ((gpointer)(gsize)threads [i]);
}
}
SgenThreadPoolJob*
sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
{
......@@ -461,11 +426,6 @@ sgen_thread_pool_start (void)
{
}
void
sgen_thread_pool_shutdown (void)
{
}
SgenThreadPoolJob*
sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
{
......
......@@ -57,8 +57,6 @@ struct _SgenThreadPoolContext {
int sgen_thread_pool_create_context (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, SgenThreadPoolShouldWorkFunc should_work_func, void **thread_datas);
void sgen_thread_pool_start (void);
void sgen_thread_pool_shutdown (void);
SgenThreadPoolJob* sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size);
/* This only needs to be called on jobs that are not enqueued. */
void sgen_thread_pool_job_free (SgenThreadPoolJob *job);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册