2010-04-27 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Mon, 26 Apr 2010 23:55:22 +0000 (23:55 -0000)
committerMark Probst <mark.probst@gmail.com>
Mon, 26 Apr 2010 23:55:22 +0000 (23:55 -0000)
        * 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

mono/metadata/ChangeLog
mono/metadata/sgen-gc.c
mono/metadata/sgen-major-copying.c
mono/metadata/sgen-marksweep.c

index 150b98a10c85eccb6d1cc250a9afb49ae72f00bd..2ce2441fd24915d3a946bec391ffaddef8916b6c 100644 (file)
@@ -1,3 +1,9 @@
+2010-04-27  Mark Probst  <mark.probst@gmail.com>
+
+       * 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  <vargaz@gmail.com>
 
        * boehm-gc.c: Applied patch from Robert Nagy (robert@openbsd.org). Include
index 3f41033abe9d50c11ab473a115f2f07ff2b045ca..3477cfbf77ccc1a78ded63886d4411b952555cab 100644 (file)
@@ -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;
index c8292b36554e41ea2261c0a7485d9519adc40fe0..fd817e155ff05ae82cbf1ead876f3c2081fb58ff 100644 (file)
@@ -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 */
index b6cd160bdf3b628cd8d55d06ec5a246dfbcc665e..ec6b0b9f1de4a7f505ff5970b0934be4bc5ce348 100644 (file)
@@ -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 */