From: Mark Probst Date: Mon, 26 Apr 2010 23:55:22 +0000 (-0000) Subject: 2010-04-27 Mark Probst X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=f0ac8666464e81a032f0d2db4238407f7312017b;p=mono.git 2010-04-27 Mark Probst * sgen-gc.c, sgen-marksweep.c, sgen-major-copying.c: Don't do a separate pass to scan pinned and large object but use the gray queue like for regular objects. svn path=/trunk/mono/; revision=156151 --- diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 150b98a10c8..2ce2441fd24 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,9 @@ +2010-04-27 Mark Probst + + * sgen-gc.c, sgen-marksweep.c, sgen-major-copying.c: Don't do a + separate pass to scan pinned and large object but use the gray + queue like for regular objects. + 2010-04-26 Zoltan Varga * boehm-gc.c: Applied patch from Robert Nagy (robert@openbsd.org). Include diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 3f41033abe9..3477cfbf77c 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -412,9 +412,8 @@ typedef struct _LOSObject LOSObject; struct _LOSObject { LOSObject *next; mword size; /* this is the object size */ - int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN and data starting at same alignment */ guint16 role; - guint16 scanned; + int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN and data starting at same alignment */ char data [MONO_ZERO_LEN_ARRAY]; }; @@ -981,7 +980,6 @@ static void scan_thread_data (void *start_nursery, void *end_nursery, gboolean p static void scan_from_remsets (void *start_nursery, void *end_nursery); static void scan_from_registered_roots (CopyOrMarkObjectFunc copy_func, char *addr_start, char *addr_end, int root_type); static void scan_finalizer_entries (CopyOrMarkObjectFunc copy_func, FinalizeEntry *list); -static int scan_needed_big_objects (ScanObjectFunc scan_func); static void find_pinning_ref_from_thread (char *obj, size_t size); static void update_current_thread_stack (void *start); static void finalize_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end, int generation); @@ -1003,13 +1001,11 @@ static char* scan_object (char *start); static char* major_scan_object (char *start); static void* copy_object_no_checks (void *obj); static void copy_object (void **obj_slot); -static void scan_from_pinned_objects (void); -static void scan_pinned_objects_in_section (GCMemSection *section, ScanObjectFunc scan_func); -static void scan_pinned_objects_in_nursery (ScanObjectFunc scan_func); static void* get_chunk_freelist (PinnedChunk *chunk, int slot); static PinnedChunk* alloc_pinned_chunk (void); static void free_large_object (LOSObject *obj); static void sort_addresses (void **array, int size); +static void drain_gray_stack (void); static void finish_gray_stack (char *start_addr, char *end_addr, int generation); static void mono_gc_register_disappearing_link (MonoObject *obj, void **link, gboolean track); @@ -2245,23 +2241,6 @@ major_scan_object (char *start) return start; } -static void -scan_pinned_objects_in_section (GCMemSection *section, ScanObjectFunc scan_func) -{ - int i; - for (i = section->pin_queue_start; i < section->pin_queue_end; ++i) { - DEBUG (6, fprintf (gc_debug_file, "Precise object scan %d of pinned %p (%s)\n", - i, pin_queue [i], safe_name (pin_queue [i]))); - scan_func (pin_queue [i]); - } -} - -static void -scan_pinned_objects_in_nursery (ScanObjectFunc scan_func) -{ - scan_pinned_objects_in_section (nursery_section, scan_func); -} - /* * drain_gray_stack: * @@ -2357,6 +2336,7 @@ pin_objects_from_addresses (GCMemSection *section, void **start, void **end, voi DEBUG (4, fprintf (gc_debug_file, "Pinned object %p, vtable %p (%s), count %d\n", search_start, *(void**)search_start, safe_name (search_start), count)); binary_protocol_pin (search_start, (gpointer)LOAD_VTABLE (search_start), safe_object_get_size (search_start)); pin_object (search_start); + GRAY_OBJECT_ENQUEUE (search_start); if (heap_dump_file) pin_stats_register_object (search_start, last_obj_size); definitely_pinned [count] = search_start; @@ -2765,23 +2745,6 @@ add_nursery_frag (size_t frag_size, char* frag_start, char* frag_end) } } -static int -scan_needed_big_objects (ScanObjectFunc scan_func) -{ - LOSObject *big_object; - int count = 0; - for (big_object = los_object_list; big_object; big_object = big_object->next) { - if (!big_object->scanned && object_is_pinned (big_object->data)) { - DEBUG (5, fprintf (gc_debug_file, "Scan of big object: %p (%s), size: %zd\n", big_object->data, safe_name (big_object->data), big_object->size)); - scan_func (big_object->data); - drain_gray_stack (); - big_object->scanned = TRUE; - count++; - } - } - return count; -} - static const char* generation_name (int generation) { @@ -2817,9 +2780,8 @@ finish_gray_stack (char *start_addr, char *end_addr, int generation) { TV_DECLARE (atv); TV_DECLARE (btv); - int fin_ready, bigo_scanned_num; + int fin_ready; CopyOrMarkObjectFunc copy_func = current_collection_generation == GENERATION_NURSERY ? copy_object : major_copy_or_mark_object; - ScanObjectFunc scan_func = current_collection_generation == GENERATION_NURSERY ? scan_object : major_scan_object; /* * We copied all the reachable objects. Now it's the time to copy @@ -2849,12 +2811,11 @@ finish_gray_stack (char *start_addr, char *end_addr, int generation) finalize_in_range (copy_func, start_addr, end_addr, generation); if (generation == GENERATION_OLD) finalize_in_range (copy_func, nursery_start, nursery_real_end, GENERATION_NURSERY); - bigo_scanned_num = scan_needed_big_objects (scan_func); /* drain the new stack that might have been created */ DEBUG (6, fprintf (gc_debug_file, "Precise scan of gray area post fin\n")); drain_gray_stack (); - } while (fin_ready != num_ready_finalizers || bigo_scanned_num); + } while (fin_ready != num_ready_finalizers); TV_GETTIME (btv); DEBUG (2, fprintf (gc_debug_file, "Finalize queue handling scan for %s generation: %d usecs\n", generation_name (generation), TV_ELAPSED (atv, btv))); @@ -3264,8 +3225,8 @@ collect_nursery (size_t requested_size) time_minor_scan_remsets += TV_ELAPSED_MS (atv, btv); DEBUG (2, fprintf (gc_debug_file, "Old generation scan: %d usecs\n", TV_ELAPSED (atv, btv))); - /* the pinned objects are roots */ - scan_pinned_objects_in_nursery (scan_object); + drain_gray_stack (); + TV_GETTIME (atv); time_minor_scan_pinned += TV_ELAPSED_MS (btv, atv); /* registered roots, this includes static fields */ @@ -3711,6 +3672,7 @@ alloc_large_inner (MonoVTable *vtable, size_t size) alloc_size &= ~(pagesize - 1); /* FIXME: handle OOM */ obj = get_os_memory (alloc_size, TRUE); + g_assert (!((mword)obj->data & (ALLOC_ALIGN - 1))); obj->size = size; vtslot = (void**)obj->data; *vtslot = vtable; diff --git a/mono/metadata/sgen-major-copying.c b/mono/metadata/sgen-major-copying.c index c8292b36554..fd817e155ff 100644 --- a/mono/metadata/sgen-major-copying.c +++ b/mono/metadata/sgen-major-copying.c @@ -349,9 +349,12 @@ major_copy_or_mark_object (void **obj_slot) objsize &= ~(ALLOC_ALIGN - 1); if (G_UNLIKELY (objsize > MAX_SMALL_OBJ_SIZE || obj_is_from_pinned_alloc (obj))) { + if (object_is_pinned (obj)) + return; DEBUG (9, fprintf (gc_debug_file, " (marked LOS/Pinned %p (%s), size: %zd)\n", obj, safe_name (obj), objsize)); binary_protocol_pin (obj, (gpointer)LOAD_VTABLE (obj), safe_object_get_size ((MonoObject*)obj)); pin_object (obj); + GRAY_OBJECT_ENQUEUE (obj); HEAVY_STAT (++stat_copy_object_failed_large_pinned); return; } @@ -486,6 +489,7 @@ mark_pinned_from_addresses (PinnedChunk *chunk, void **start, void **end) if (heap_dump_file && !object_is_pinned (addr)) pin_stats_register_object ((char*) addr, safe_object_get_size ((MonoObject*) addr)); pin_object (addr); + GRAY_OBJECT_ENQUEUE (addr); DEBUG (6, fprintf (gc_debug_file, "Marked pinned object %p (%s) from roots\n", addr, safe_name (addr))); } } @@ -509,21 +513,6 @@ sweep_pinned_objects (void) scan_pinned_objects (sweep_pinned_objects_callback, NULL); } -static void -scan_object_callback (char *ptr, size_t size, void *data) -{ - DEBUG (6, fprintf (gc_debug_file, "Precise object scan of alloc_pinned %p (%s)\n", ptr, safe_name (ptr))); - /* FIXME: Put objects without references into separate chunks - which do not need to be scanned */ - major_scan_object (ptr); -} - -static void -scan_from_pinned_objects (void) -{ - scan_pinned_objects ((IterateObjectCallbackFunc)scan_object_callback, NULL); -} - static void major_iterate_objects (gboolean non_pinned, gboolean pinned, IterateObjectCallbackFunc callback, void *data) { @@ -563,6 +552,7 @@ major_do_collection (const char *reason) init_stats (); binary_protocol_collection (GENERATION_OLD); check_scan_starts (); + gray_object_queue_init (); degraded_mode = 0; DEBUG (1, fprintf (gc_debug_file, "Start major collection %d\n", num_major_gcs)); @@ -619,6 +609,7 @@ major_do_collection (const char *reason) find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + bigobj->size, &start, &end); if (start != end) { pin_object (bigobj->data); + GRAY_OBJECT_ENQUEUE (bigobj->data); if (heap_dump_file) pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data)); DEBUG (6, fprintf (gc_debug_file, "Marked large object %p (%s) size: %zd from roots\n", bigobj->data, safe_name (bigobj->data), bigobj->size)); @@ -643,25 +634,9 @@ major_do_collection (const char *reason) DEBUG (4, fprintf (gc_debug_file, "Start scan with %d pinned objects\n", next_pin_slot)); new_to_space_section (); - gray_object_queue_init (); - /* the old generation doesn't need to be scanned (no remembered sets or card - * table needed either): the only objects that must survive are those pinned and - * those referenced by the precise roots. - * mark any section without pinned objects, so we can free it since we will be able to - * move all the objects. - */ - /* the pinned objects are roots (big objects are included in this list, too) */ - scan_pinned_objects_in_nursery (major_scan_object); - for (section = section_list; section; section = section->block.next) - scan_pinned_objects_in_section (section, major_scan_object); - for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) { - if (object_is_pinned (bigobj->data)) { - DEBUG (6, fprintf (gc_debug_file, "Precise object scan pinned LOS object %p (%s)\n", - bigobj->data, safe_name (bigobj->data))); - major_scan_object (bigobj->data); - } - } + drain_gray_stack (); + TV_GETTIME (atv); time_major_scan_pinned += TV_ELAPSED_MS (btv, atv); @@ -678,13 +653,6 @@ major_do_collection (const char *reason) TV_GETTIME (atv); time_major_scan_thread_data += TV_ELAPSED_MS (btv, atv); - /* alloc_pinned objects */ - /* - * FIXME: This should not be necessary - reachable pinned - * objects should have been put in the gray queue and - * non-reachable ones shouldn't be scanned. - */ - scan_from_pinned_objects (); TV_GETTIME (btv); time_major_scan_alloc_pinned += TV_ELAPSED_MS (atv, btv); @@ -695,11 +663,6 @@ major_do_collection (const char *reason) time_major_scan_finalized += TV_ELAPSED_MS (btv, atv); DEBUG (2, fprintf (gc_debug_file, "Root scan: %d usecs\n", TV_ELAPSED (btv, atv))); - /* we need to go over the big object list to see if any was marked and scan it - * And we need to make this in a loop, considering that objects referenced by finalizable - * objects could reference big objects (this happens in finish_gray_stack ()) - */ - scan_needed_big_objects (major_scan_object); TV_GETTIME (btv); time_major_scan_big_objects += TV_ELAPSED_MS (atv, btv); @@ -716,7 +679,6 @@ major_do_collection (const char *reason) for (bigobj = los_object_list; bigobj;) { if (object_is_pinned (bigobj->data)) { unpin_object (bigobj->data); - bigobj->scanned = FALSE; } else { LOSObject *to_free; /* not referenced anywhere, so we can free it */ diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index b6cd160bdf3..ec6b0b9f1de 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -504,8 +504,11 @@ major_copy_or_mark_object (void **ptr) objsize &= ~(ALLOC_ALIGN - 1); if (objsize > MAX_SMALL_OBJ_SIZE) { + if (object_is_pinned (obj)) + return; binary_protocol_pin (obj, (gpointer)LOAD_VTABLE (obj), safe_object_get_size ((MonoObject*)obj)); pin_object (obj); + GRAY_OBJECT_ENQUEUE (obj); return; } @@ -516,23 +519,6 @@ major_copy_or_mark_object (void **ptr) MS_MARK_INDEX_IN_BLOCK_AND_ENQUEUE (obj, block, index); } -static void -scan_object_callback (char *ptr, size_t size, void *data) -{ - major_scan_object (ptr); -} - -/* - * FIXME: This is essentially the same as the corresponding function - * in sgen-major-copying.c. Unify (or eliminate - see comment in - * major_do_collection())! - */ -static void -scan_from_pinned_objects (void) -{ - major_iterate_objects (FALSE, TRUE, scan_object_callback, NULL); -} - static void mark_pinned_objects_in_block (MSBlockInfo *block) { @@ -738,10 +724,8 @@ major_do_collection (const char *reason) int start, end; find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + bigobj->size, &start, &end); if (start != end) { - /* FIXME: just put them in the gray queue, - then we don't have to do the second loop - below */ pin_object (bigobj->data); + GRAY_OBJECT_ENQUEUE (bigobj->data); if (heap_dump_file) pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data)); DEBUG (6, fprintf (gc_debug_file, "Marked large object %p (%s) size: %zd from roots\n", bigobj->data, safe_name (bigobj->data), bigobj->size)); @@ -757,21 +741,8 @@ major_do_collection (const char *reason) DEBUG (2, fprintf (gc_debug_file, "Finding pinned pointers: %d in %d usecs\n", next_pin_slot, TV_ELAPSED (atv, btv))); DEBUG (4, fprintf (gc_debug_file, "Start scan with %d pinned objects\n", next_pin_slot)); - /* the old generation doesn't need to be scanned (no remembered sets or card - * table needed either): the only objects that must survive are those pinned and - * those referenced by the precise roots. - * mark any section without pinned objects, so we can free it since we will be able to - * move all the objects. - */ - /* the pinned objects are roots (big objects are included in this list, too) */ - scan_pinned_objects_in_nursery (major_scan_object); - for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) { - if (object_is_pinned (bigobj->data)) { - DEBUG (6, fprintf (gc_debug_file, "Precise object scan pinned LOS object %p (%s)\n", - bigobj->data, safe_name (bigobj->data))); - major_scan_object (bigobj->data); - } - } + drain_gray_stack (); + TV_GETTIME (atv); time_major_scan_pinned += TV_ELAPSED_MS (btv, atv); @@ -788,13 +759,6 @@ major_do_collection (const char *reason) TV_GETTIME (atv); time_major_scan_thread_data += TV_ELAPSED_MS (btv, atv); - /* alloc_pinned objects */ - /* - * FIXME: This should not be necessary - reachable pinned - * objects should have been put in the gray queue and - * non-reachable ones shouldn't be scanned. - */ - scan_from_pinned_objects (); TV_GETTIME (btv); time_major_scan_alloc_pinned += TV_ELAPSED_MS (atv, btv); @@ -805,11 +769,6 @@ major_do_collection (const char *reason) time_major_scan_finalized += TV_ELAPSED_MS (btv, atv); DEBUG (2, fprintf (gc_debug_file, "Root scan: %d usecs\n", TV_ELAPSED (btv, atv))); - /* we need to go over the big object list to see if any was marked and scan it - * And we need to make this in a loop, considering that objects referenced by finalizable - * objects could reference big objects (this happens in finish_gray_stack ()) - */ - scan_needed_big_objects (major_scan_object); TV_GETTIME (btv); time_major_scan_big_objects += TV_ELAPSED_MS (atv, btv); @@ -823,7 +782,6 @@ major_do_collection (const char *reason) for (bigobj = los_object_list; bigobj;) { if (object_is_pinned (bigobj->data)) { unpin_object (bigobj->data); - bigobj->scanned = FALSE; } else { LOSObject *to_free; /* not referenced anywhere, so we can free it */