[sgen] Dynamic nursery sizing
authorVlad Brezae <brezaevlad@gmail.com>
Wed, 5 Apr 2017 10:11:01 +0000 (13:11 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Mon, 15 May 2017 09:52:51 +0000 (12:52 +0300)
We attempt to have a nursery that is as large as possible, while keeping a relative limit to the heap size.

mono/sgen/sgen-conf.h
mono/sgen/sgen-debug.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-marksweep.c
mono/sgen/sgen-memory-governor.c
mono/sgen/sgen-nursery-allocator.c
mono/sgen/sgen-simple-nursery.c
mono/tests/Makefile.am

index 64bdac2f8a9ea8fe123e85694e6955e9f03cd669..324009cc2951b2fc482d09f79122907bf41193bd 100644 (file)
@@ -204,4 +204,11 @@ typedef mword SgenDescriptor;
 #define SGEN_CEMENT_HASH(hv)   (((hv) ^ ((hv) >> SGEN_CEMENT_HASH_SHIFT)) & (SGEN_CEMENT_HASH_SIZE - 1))
 #define SGEN_CEMENT_THRESHOLD  1000
 
+/*
+ * Default values for the nursery size
+ */
+#define SGEN_DEFAULT_NURSERY_MIN_SIZE  (1 << 19)
+#define SGEN_DEFAULT_NURSERY_SIZE      (1 << 22)
+#define SGEN_DEFAULT_NURSERY_MAX_SIZE  (1 << 25)
+
 #endif
index 93ab45e7a8d3b4895af652d53acdf86b5609206a..b4da324df1f4bc10ba51959c8fb21f32e4f808ed 100644 (file)
@@ -325,7 +325,7 @@ static void
 setup_valid_nursery_objects (void)
 {
        if (!valid_nursery_objects)
-               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (sgen_nursery_size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data", MONO_MEM_ACCOUNT_SGEN_DEBUGGING);
+               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (sgen_nursery_max_size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data", MONO_MEM_ACCOUNT_SGEN_DEBUGGING);
        valid_nursery_object_count = 0;
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE);
 }
index 8662ffbc1e4bd41188bdd27957ec4f9851008a40..9f8a8aa63ffe9aa0c9e8af0cd8d54940a8e3dbe6 100644 (file)
@@ -946,40 +946,51 @@ sgen_update_heap_boundaries (mword low, mword high)
  * in the nursery. The nursery is stored in nursery_section.
  */
 static void
-alloc_nursery (void)
+alloc_nursery (gboolean dynamic, size_t min_size, size_t max_size)
 {
-       GCMemSection *section;
        char *data;
        size_t scan_starts;
-       size_t alloc_size;
 
-       if (nursery_section)
-               return;
-       SGEN_LOG (2, "Allocating nursery size: %zu", (size_t)sgen_nursery_size);
-       /* later we will alloc a larger area for the nursery but only activate
-        * what we need. The rest will be used as expansion if we have too many pinned
-        * objects in the existing nursery.
-        */
-       /* FIXME: handle OOM */
-       section = (GCMemSection *)sgen_alloc_internal (INTERNAL_MEM_SECTION);
+       if (dynamic) {
+               if (!min_size)
+                       min_size = SGEN_DEFAULT_NURSERY_MIN_SIZE;
+               if (!max_size)
+                       max_size = SGEN_DEFAULT_NURSERY_MAX_SIZE;
+       } else {
+               SGEN_ASSERT (0, min_size == max_size, "We can't have nursery ranges for static configuration.");
+               if (!min_size)
+                       min_size = max_size = SGEN_DEFAULT_NURSERY_SIZE;
+       }
 
-       alloc_size = sgen_nursery_size;
+       SGEN_ASSERT (0, !nursery_section, "Why are we allocating the nursery twice?");
+       SGEN_LOG (2, "Allocating nursery size: %zu, initial %zu", max_size, min_size);
 
-       /* If there isn't enough space even for the nursery we should simply abort. */
-       g_assert (sgen_memgov_try_alloc_space (alloc_size, SPACE_NURSERY));
+       /* FIXME: handle OOM */
+       nursery_section = (GCMemSection *)sgen_alloc_internal (INTERNAL_MEM_SECTION);
 
-       data = (char *)major_collector.alloc_heap (alloc_size, alloc_size, sgen_nursery_bits);
-       sgen_update_heap_boundaries ((mword)data, (mword)(data + sgen_nursery_size));
-       SGEN_LOG (4, "Expanding nursery size (%p-%p): %lu, total: %lu", data, data + alloc_size, (unsigned long)sgen_nursery_size, (unsigned long)sgen_gc_get_total_heap_allocation ());
-       section->data = data;
-       section->end_data = data + sgen_nursery_size;
-       scan_starts = (alloc_size + SCAN_START_SIZE - 1) / SCAN_START_SIZE;
-       section->scan_starts = (char **)sgen_alloc_internal_dynamic (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS, TRUE);
-       section->num_scan_start = scan_starts;
+       /* If there isn't enough space even for the nursery we should simply abort. */
+       g_assert (sgen_memgov_try_alloc_space (max_size, SPACE_NURSERY));
 
-       nursery_section = section;
+       /*
+        * The nursery section range represents the memory section where objects
+        * can be found. This is used when iterating for objects in the nursery,
+        * pinning etc. sgen_nursery_max_size represents the total allocated space
+        * for the nursery. sgen_nursery_size represents the current size of the
+        * nursery and it is used for allocation limits, heuristics etc. The
+        * nursery section is not always identical to the current nursery size
+        * because it can contain pinned objects from when the nursery was larger.
+        *
+        * sgen_nursery_size <= nursery_section size <= sgen_nursery_max_size
+        */
+       data = (char *)major_collector.alloc_heap (max_size, max_size);
+       sgen_update_heap_boundaries ((mword)data, (mword)(data + max_size));
+       nursery_section->data = data;
+       nursery_section->end_data = data + min_size;
+       scan_starts = (max_size + SCAN_START_SIZE - 1) / SCAN_START_SIZE;
+       nursery_section->scan_starts = (char **)sgen_alloc_internal_dynamic (sizeof (char*) * scan_starts, INTERNAL_MEM_SCAN_STARTS, TRUE);
+       nursery_section->num_scan_start = scan_starts;
 
-       sgen_nursery_allocator_set_nursery_bounds (data, data + sgen_nursery_size);
+       sgen_nursery_allocator_set_nursery_bounds (data, min_size, max_size);
 }
 
 FILE *
@@ -1732,6 +1743,8 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
        if (remset_consistency_checks)
                sgen_check_remset_consistency ();
 
+       sgen_resize_nursery ();
+
        /* walk the pin_queue, build up the fragment list of free memory, unmark
         * pinned objects as we go, memzero() the empty fragments so they are ready for the
         * next allocations.
@@ -2984,6 +2997,8 @@ sgen_gc_init (void)
        gboolean debug_print_allowance = FALSE;
        double allowance_ratio = 0, save_target = 0;
        gboolean cement_enabled = TRUE;
+       gboolean dynamic_nursery = FALSE;
+       size_t min_nursery_size = 0, max_nursery_size = 0;
 
        do {
                result = InterlockedCompareExchange (&gc_initialized, -1, 0);
@@ -3132,10 +3147,8 @@ sgen_gc_init (void)
                                                continue;
                                        }
 
-                                       sgen_nursery_size = val;
-                                       sgen_nursery_bits = 0;
-                                       while (ONE_P << (++ sgen_nursery_bits) != sgen_nursery_size)
-                                               ;
+                                       min_nursery_size = max_nursery_size = val;
+                                       dynamic_nursery = FALSE;
                                } else {
                                        sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`nursery-size` must be an integer.");
                                        continue;
@@ -3179,6 +3192,19 @@ sgen_gc_init (void)
                                continue;
                        }
 
+                       if (!strcmp (opt, "dynamic-nursery")) {
+                               if (sgen_minor_collector.is_split)
+                                       sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.",
+                                                       "dynamic-nursery not supported with split-nursery.");
+                               else
+                                       dynamic_nursery = TRUE;
+                               continue;
+                       }
+                       if (!strcmp (opt, "no-dynamic-nursery")) {
+                               dynamic_nursery = FALSE;
+                               continue;
+                       }
+
                        if (major_collector.handle_gc_param && major_collector.handle_gc_param (opt))
                                continue;
 
@@ -3201,6 +3227,7 @@ sgen_gc_init (void)
                        fprintf (stderr, "  minor=COLLECTOR (where COLLECTOR is `simple' or `split')\n");
                        fprintf (stderr, "  wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n");
                        fprintf (stderr, "  [no-]cementing\n");
+                       fprintf (stderr, "  [no-]dynamic-nursery\n");
                        if (major_collector.print_gc_param_usage)
                                major_collector.print_gc_param_usage ();
                        if (sgen_minor_collector.print_gc_param_usage)
@@ -3225,7 +3252,7 @@ sgen_gc_init (void)
        if (params_opts)
                g_free (params_opts);
 
-       alloc_nursery ();
+       alloc_nursery (dynamic_nursery, min_nursery_size, max_nursery_size);
 
        sgen_pinning_init ();
        sgen_cement_init (cement_enabled);
index a0b681cbed0410c27b88eb03272e1718510d82ba..1a727a6d3338b8efcd4fa89a36b2b1a179a74e35 100644 (file)
@@ -184,6 +184,7 @@ sgen_aligned_addr_hash (gconstpointer ptr)
 #define SGEN_PTR_IN_NURSERY(p,bits,start,end)  (((mword)(p) & ~(((mword)1 << (bits)) - 1)) == (mword)(start))
 
 extern size_t sgen_nursery_size;
+extern size_t sgen_nursery_max_size;
 extern int sgen_nursery_bits;
 
 extern char *sgen_nursery_start;
@@ -623,7 +624,7 @@ struct _SgenMajorCollector {
        gboolean supports_cardtable;
        gboolean sweeps_lazily;
 
-       void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
+       void* (*alloc_heap) (mword nursery_size, mword nursery_align);
        gboolean (*is_object_live) (GCObject *obj);
        GCObject* (*alloc_small_pinned_obj) (GCVTable vtable, size_t size, gboolean has_references);
        GCObject* (*alloc_degraded) (GCVTable vtable, size_t size);
@@ -895,7 +896,8 @@ void sgen_los_mark_mod_union_card (GCObject *mono_obj, void **ptr);
 
 void sgen_clear_nursery_fragments (void);
 void sgen_nursery_allocator_prepare_for_pinning (void);
-void sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, char *nursery_end);
+void sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, size_t min_size, size_t max_size);
+void sgen_resize_nursery (void);
 mword sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue);
 void sgen_init_nursery_allocator (void);
 void sgen_nursery_allocator_init_heavy_stats (void);
index 04ab32dab84a0dbc96e64bf00e7293ed6eee2e8d..12b06055affe554380a649ef0085072f8e4a85c5 100644 (file)
@@ -306,7 +306,7 @@ ms_find_block_obj_size_index (size_t size)
         ms_find_block_obj_size_index ((s)))
 
 static void*
-major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
+major_alloc_heap (mword nursery_size, mword nursery_align)
 {
        char *start;
        if (nursery_align)
index 9be31ad76e64951b01085b320406db824cdb2878..17fed16754ba8ba61a0e67f5c88f5c8c79870cc0 100644 (file)
@@ -23,7 +23,7 @@
 #include "mono/sgen/sgen-workers.h"
 #include "mono/sgen/sgen-client.h"
 
-#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(sgen_nursery_size * default_allowance_nursery_size_ratio))
+#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(SGEN_DEFAULT_NURSERY_SIZE * default_allowance_nursery_size_ratio))
 
 static SgenPointerQueue log_entries = SGEN_POINTER_QUEUE_INIT (INTERNAL_MEM_TEMPORARY);
 static MonoCoopMutex log_entries_mutex;
@@ -492,11 +492,11 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
                max_heap = soft_limit;
        }
 
-       if (max_heap < sgen_nursery_size * 4) {
+       if (max_heap < SGEN_DEFAULT_NURSERY_SIZE * 4) {
                sgen_env_var_error (MONO_GC_PARAMS_NAME, "Setting to minimum.", "`max-heap-size` must be at least 4 times as large as `nursery size`.");
-               max_heap = sgen_nursery_size * 4;
+               max_heap = SGEN_DEFAULT_NURSERY_SIZE * 4;
        }
-       max_heap_size = max_heap - sgen_nursery_size;
+       max_heap_size = max_heap - SGEN_DEFAULT_NURSERY_SIZE;
 
        if (allowance_ratio)
                default_allowance_nursery_size_ratio = allowance_ratio;
index 2c192f0e904ab298cbe3b6effa7919badd391aa3..1452b6b7d79b5e995472a55cc1e1a179b9ec525d 100644 (file)
@@ -66,16 +66,21 @@ static SgenFragmentAllocator mutator_allocator;
 /* freeelist of fragment structures */
 static SgenFragment *fragment_freelist = NULL;
 
-/* Allocator cursors */
-static char *nursery_last_pinned_end = NULL;
-
 char *sgen_nursery_start;
 char *sgen_nursery_end;
 
 /* good sizes are 512KB-1MB: larger ones increase a lot memzeroing time */
-size_t sgen_nursery_size = (1 << 22);
-/* The number of trailing 0 bits in sgen_nursery_size */
-int sgen_nursery_bits = 22;
+size_t sgen_nursery_size;
+/*
+ * Maximum size that we can resize the nursery to.
+ * If sgen_nursery_default_size == sgen_nursery_max_size then we are not
+ * dynamically resizing the nursery
+ */
+size_t sgen_nursery_max_size;
+size_t sgen_nursery_min_size;
+/* The number of trailing 0 bits in sgen_nursery_max_size */
+int sgen_nursery_bits;
+
 
 char *sgen_space_bitmap;
 size_t sgen_space_bitmap_size;
@@ -345,7 +350,7 @@ par_alloc_from_fragment (SgenFragmentAllocator *allocator, SgenFragment *frag, s
        char *p = frag->fragment_next;
        char *end = p + size;
 
-       if (end > frag->fragment_end)
+       if (end > frag->fragment_end || end > (sgen_nursery_start + sgen_nursery_size))
                return NULL;
 
        /* p = frag->fragment_next must happen before */
@@ -439,9 +444,14 @@ sgen_fragment_allocator_par_alloc (SgenFragmentAllocator *allocator, size_t size
 
 restart:
        for (frag = (SgenFragment *)unmask (allocator->alloc_head); unmask (frag); frag = (SgenFragment *)unmask (frag->next)) {
+               size_t frag_size = frag->fragment_end - frag->fragment_next;
+
+               if (frag->fragment_next >= (sgen_nursery_start + sgen_nursery_size))
+                       continue;
+
                HEAVY_STAT (++stat_alloc_iterations);
 
-               if (size <= (size_t)(frag->fragment_end - frag->fragment_next)) {
+               if (size <= frag_size) {
                        void *p = par_alloc_from_fragment (allocator, frag, size);
                        if (!p) {
                                HEAVY_STAT (++stat_alloc_retries);
@@ -524,6 +534,9 @@ restart:
        for (frag = (SgenFragment *)unmask (allocator->alloc_head); frag; frag = (SgenFragment *)unmask (frag->next)) {
                size_t frag_size = frag->fragment_end - frag->fragment_next;
 
+               if (frag->fragment_next >= (sgen_nursery_start + sgen_nursery_size))
+                       continue;
+
                HEAVY_STAT (++stat_alloc_range_iterations);
 
                if (desired_size <= frag_size) {
@@ -551,9 +564,8 @@ restart:
 
        if (min_frag) {
                void *p;
-               size_t frag_size;
+               size_t frag_size = min_frag->fragment_end - min_frag->fragment_next;
 
-               frag_size = min_frag->fragment_end - min_frag->fragment_next;
                if (frag_size < minimum_size)
                        goto restart;
 
@@ -678,6 +690,26 @@ fragment_list_reverse (SgenFragmentAllocator *allocator)
        allocator->region_head = allocator->alloc_head = prev;
 }
 
+/*
+ * We split fragments at the border of the current nursery limit. When we
+ * allocate from the nursery we only consider fragments that start in the
+ * current nursery section. We build fragments for the entire nursery in
+ * order to facilitate scanning it for objects (adding a nursery frag also
+ * marks a region in the nursery as being free)
+ */
+static void
+add_nursery_frag_checks (SgenFragmentAllocator *allocator, char *frag_start, char *frag_end)
+{
+       char *nursery_limit = sgen_nursery_start + sgen_nursery_size;
+
+       if (frag_start < nursery_limit && frag_end > nursery_limit) {
+               add_nursery_frag (allocator, nursery_limit - frag_start, frag_start, nursery_limit);
+               add_nursery_frag (allocator, frag_end - nursery_limit, nursery_limit, frag_end);
+       } else {
+               add_nursery_frag (allocator, frag_end - frag_start, frag_start, frag_end);
+       }
+}
+
 mword
 sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue)
 {
@@ -738,7 +770,7 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpi
                g_assert (frag_size >= 0);
                g_assert (size > 0);
                if (frag_size && size)
-                       add_nursery_frag (&mutator_allocator, frag_size, frag_start, frag_end); 
+                       add_nursery_frag_checks (&mutator_allocator, frag_start, frag_end);
 
                frag_size = size;
 #ifdef NALLOC_DEBUG
@@ -747,11 +779,10 @@ sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpi
                frag_start = frag_end + frag_size;
        }
 
-       nursery_last_pinned_end = frag_start;
        frag_end = sgen_nursery_end;
        frag_size = frag_end - frag_start;
        if (frag_size)
-               add_nursery_frag (&mutator_allocator, frag_size, frag_start, frag_end);
+               add_nursery_frag_checks (&mutator_allocator, frag_start, frag_end);
 
        /* Now it's safe to release the fragments exclude list. */
        sgen_minor_collector.build_fragments_release_exclude_head ();
@@ -863,21 +894,59 @@ sgen_nursery_alloc_prepare_for_major (void)
 }
 
 void
-sgen_nursery_allocator_set_nursery_bounds (char *start, char *end)
+sgen_nursery_allocator_set_nursery_bounds (char *start, size_t min_size, size_t max_size)
 {
        sgen_nursery_start = start;
-       sgen_nursery_end = end;
+       sgen_nursery_end = start + max_size;
+
+       sgen_nursery_size = min_size;
+       sgen_nursery_min_size = min_size;
+       sgen_nursery_max_size = max_size;
+
+       sgen_nursery_bits = 0;
+       while (ONE_P << (++ sgen_nursery_bits) != sgen_nursery_max_size)
+               ;
 
        /*
         * This will not divide evenly for tiny nurseries (<4kb), so we make sure to be on
         * the right side of things and round up.  We could just do a MIN(1,x) instead,
         * since the nursery size must be a power of 2.
         */
-       sgen_space_bitmap_size = (end - start + SGEN_TO_SPACE_GRANULE_IN_BYTES * 8 - 1) / (SGEN_TO_SPACE_GRANULE_IN_BYTES * 8);
+       sgen_space_bitmap_size = (sgen_nursery_end - sgen_nursery_start + SGEN_TO_SPACE_GRANULE_IN_BYTES * 8 - 1) / (SGEN_TO_SPACE_GRANULE_IN_BYTES * 8);
        sgen_space_bitmap = (char *)g_malloc0 (sgen_space_bitmap_size);
 
        /* Setup the single first large fragment */
-       sgen_minor_collector.init_nursery (&mutator_allocator, start, end);
+       sgen_minor_collector.init_nursery (&mutator_allocator, sgen_nursery_start, sgen_nursery_end);
 }
 
+void
+sgen_resize_nursery (void)
+{
+       size_t major_size;
+
+       if (sgen_nursery_min_size == sgen_nursery_max_size)
+               return;
+
+       major_size = major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
+       /*
+        * We attempt to use a larger nursery size, as long as it doesn't
+        * exceed a certain percentage of the major heap.
+        *
+        * FIXME
+        * Commit memory when expanding and release it when shrinking (which
+        * would only be possible if there aren't any pinned objects in the
+        * section).
+        */
+       if ((sgen_nursery_size * 2) < (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) &&
+                       (sgen_nursery_size * 2) <= sgen_nursery_max_size) {
+               if ((nursery_section->end_data - nursery_section->data) == sgen_nursery_size)
+                       nursery_section->end_data += sgen_nursery_size;
+               sgen_nursery_size *= 2;
+       } else if (sgen_nursery_size > (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) &&
+                       (sgen_nursery_size / 2) >= sgen_nursery_min_size) {
+               sgen_nursery_size /= 2;
+       }
+}
+
+
 #endif
index 4234559e9e8cec8ced5617f60fe64e9e9e862c38..ee72408b76f273ace13978c6ea126cc1af7fe032 100644 (file)
@@ -57,7 +57,14 @@ clear_fragments (void)
 static void
 init_nursery (SgenFragmentAllocator *allocator, char *start, char *end)
 {
-       sgen_fragment_allocator_add (allocator, start, end);
+       char *nursery_limit = sgen_nursery_start + sgen_nursery_size;
+
+       if (start < nursery_limit && end > nursery_limit) {
+               sgen_fragment_allocator_add (allocator, start, nursery_limit);
+               sgen_fragment_allocator_add (allocator, nursery_limit, end);
+       } else {
+               sgen_fragment_allocator_add (allocator, start, end);
+       }
 }
 
 
index dc2bb937cbe4d8905aa01f5230114fc243121aff..9aa3eec732a5513af0c2092e62b0f526f299ba74 100644 (file)
@@ -1445,10 +1445,10 @@ test-stress-sgen-regular: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR)
        $(MAKE) test-sgen-regular-ms-conc-par-simple MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-regular-ms-conc-split MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-regular-ms-conc-split-95-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-regular-ms-conc-par-simple-par MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-regular-ms-conc-par-simple-par-dyn MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-regular-ms-conc-par-simple-par-512k MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-regular-ms-conc-par-simple-par-32m MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-regular-ms-conc-par-simple-par-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-regular-ms-conc-par-simple-par-dyn-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
        $$ok
 
 test-sgen-regular-ms-simple: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
@@ -1461,14 +1461,14 @@ test-sgen-regular-ms-conc-split: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR)
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=major=marksweep-conc,minor=split" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
 test-sgen-regular-ms-conc-split-95-clear-at-gc: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=major=marksweep-conc,minor=split,alloc-ratio=95" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
-test-sgen-regular-ms-conc-par-simple-par: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=major=marksweep-conc-par,minor=simple-par" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
+test-sgen-regular-ms-conc-par-simple-par-dyn: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=major=marksweep-conc-par,minor=simple-par,dynamic-nursery" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
 test-sgen-regular-ms-conc-par-simple-par-512k: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=major=marksweep-conc-par,minor=simple-par,nursery-size=512k" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
 test-sgen-regular-ms-conc-par-simple-par-32m: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=major=marksweep-conc-par,minor=simple-par,nursery-size=32m" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
-test-sgen-regular-ms-conc-par-simple-par-clear-at-gc: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=major=marksweep-conc-par,minor=simple-par" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
+test-sgen-regular-ms-conc-par-simple-par-dyn-clear-at-gc: $(TESTS_SGEN_REGULAR) $(TESTSAOT_SGEN_REGULAR) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=major=marksweep-conc-par,minor=simple-par,dynamic-nursery" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_REGULAR)
 
 TESTS_SGEN_TOGGLEREF_SRC=      \
        sgen-toggleref.cs
@@ -1496,10 +1496,10 @@ test-stress-sgen-toggleref: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF)
        $(MAKE) test-sgen-toggleref-ms-conc-par-simple MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-toggleref-ms-conc-split MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-toggleref-ms-conc-split-95-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par-dyn MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par-512k MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par-32m MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-toggleref-ms-conc-par-simple-par-dyn-clear-at-gc MONO_TESTS_STRESS=1 || ok=false; \
        $$ok
 
 test-sgen-toggleref-ms-simple: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
@@ -1512,14 +1512,14 @@ test-sgen-toggleref-ms-conc-split: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGL
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=toggleref-test,major=marksweep-conc,minor=split" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
 test-sgen-toggleref-ms-conc-split-95-clear-at-gc: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=toggleref-test,major=marksweep-conc,minor=split,alloc-ratio=95" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
-test-sgen-toggleref-ms-conc-par-simple-par: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
+test-sgen-toggleref-ms-conc-par-simple-par-dyn: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par,dynamic-nursery" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
 test-sgen-toggleref-ms-conc-par-simple-par-512k: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par,nursery-size=512k" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
 test-sgen-toggleref-ms-conc-par-simple-par-32m: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug= --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par,nursery-size=32m" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
-test-sgen-toggleref-ms-conc-par-simple-par-clear-at-gc: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
+test-sgen-toggleref-ms-conc-par-simple-par-dyn-clear-at-gc: $(TESTS_SGEN_TOGGLEREF) $(TESTSAOT_SGEN_TOGGLEREF) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=clear-at-gc --gc-params=toggleref-test,major=marksweep-conc-par,minor=simple-par,dynamic-nursery" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_TOGGLEREF)
 
 TESTS_SGEN_BRIDGE_SRC= \
        sgen-bridge.cs  \
@@ -1548,7 +1548,7 @@ test-stress-sgen-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE)
        $(MAKE) test-sgen-bridge-ms-conc-split-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge-ms-conc-simple-new-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge-ms-conc-simple-old-bridge MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-bridge-ms-conc-par-simple-par-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-bridge-ms-conc-par-simple-par-dyn-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge-ms-conc-par-simple-par-512k-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge-ms-conc-par-simple-par-32m-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $$ok
@@ -1563,8 +1563,8 @@ test-sgen-bridge-ms-conc-simple-new-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=new" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
 test-sgen-bridge-ms-conc-simple-old-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=old" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-conc-par-simple-par-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
+test-sgen-bridge-ms-conc-par-simple-par-dyn-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,dynamic-nursery,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
 test-sgen-bridge-ms-conc-par-simple-par-512k-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,nursery-size=512k,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
 test-sgen-bridge-ms-conc-par-simple-par-32m-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
@@ -1611,7 +1611,7 @@ test-stress-sgen-bridge2: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2)
        $(MAKE) test-sgen-bridge2-ms-conc-split-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge2-ms-conc-simple-new-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge2-ms-conc-simple-old-bridge MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-bridge2-ms-conc-par-simple-par-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-bridge2-ms-conc-par-simple-par-dyn-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge2-ms-conc-par-simple-par-512k-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge2-ms-conc-par-simple-par-32m-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $$ok
@@ -1626,8 +1626,8 @@ test-sgen-bridge2-ms-conc-simple-new-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SG
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=2Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=new" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE2)
 test-sgen-bridge2-ms-conc-simple-old-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=2Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=old" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE2)
-test-sgen-bridge2-ms-conc-par-simple-par-tarjan-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=2Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE2)
+test-sgen-bridge2-ms-conc-par-simple-par-dyn-tarjan-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=2Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,dynamic-nursery,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE2)
 test-sgen-bridge2-ms-conc-par-simple-par-512k-tarjan-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=2Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,nursery-size=512k,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE2)
 test-sgen-bridge2-ms-conc-par-simple-par-32m-tarjan-bridge: $(TESTS_SGEN_BRIDGE2) $(TESTSAOT_SGEN_BRIDGE2) test-runner.exe
@@ -1659,7 +1659,7 @@ test-stress-sgen-bridge3: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3)
        $(MAKE) test-sgen-bridge3-ms-conc-split-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge3-ms-conc-simple-new-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge3-ms-conc-simple-old-bridge MONO_TESTS_STRESS=1 || ok=false; \
-       $(MAKE) test-sgen-bridge3-ms-conc-par-simple-par-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
+       $(MAKE) test-sgen-bridge3-ms-conc-par-simple-par-dyn-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge3-ms-conc-par-simple-par-512k-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $(MAKE) test-sgen-bridge3-ms-conc-par-simple-par-32m-tarjan-bridge MONO_TESTS_STRESS=1 || ok=false; \
        $$ok
@@ -1674,8 +1674,8 @@ test-sgen-bridge3-ms-conc-simple-new-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SG
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=3Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=new" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE3)
 test-sgen-bridge3-ms-conc-simple-old-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=3Bridge --gc-params=major=marksweep-conc,minor=simple,bridge-implementation=old" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE3)
-test-sgen-bridge3-ms-conc-par-simple-par-tarjan-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3) test-runner.exe
-       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=3Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE3)
+test-sgen-bridge3-ms-conc-par-simple-par-dyn-tarjan-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3) test-runner.exe
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=3Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,dynamic-nursery,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE3)
 test-sgen-bridge3-ms-conc-par-simple-par-512k-tarjan-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3) test-runner.exe
        $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=bridge=3Bridge --gc-params=major=marksweep-conc-par,minor=simple-par,nursery-size=512k,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE3)
 test-sgen-bridge3-ms-conc-par-simple-par-32m-tarjan-bridge: $(TESTS_SGEN_BRIDGE3) $(TESTSAOT_SGEN_BRIDGE3) test-runner.exe