mono_gc_get_nursery (int *shift_bits, size_t *size)
{
*size = sgen_nursery_size;
- *shift_bits = DEFAULT_NURSERY_BITS;
+ *shift_bits = sgen_nursery_bits;
return sgen_get_nursery_start ();
}
/* when running in degraded mode, we continue allocing that way
* for a while, to decrease the number of useless nursery collections.
*/
- if (degraded_mode && degraded_mode < DEFAULT_NURSERY_SIZE)
+ if (degraded_mode && degraded_mode < sgen_nursery_size)
return alloc_degraded (vtable, size, FALSE);
available_in_tlab = (int)(TLAB_REAL_END - TLAB_NEXT);//We'll never have tlabs > 2Gb
GCObject **dest = (GCObject **)_dest;
GCObject **src = (GCObject **)_src;
- size_t nursery_bits = DEFAULT_NURSERY_BITS;
+ size_t nursery_bits = sgen_nursery_bits;
char *start = sgen_nursery_start;
G_GNUC_UNUSED char *end = sgen_nursery_end;
#define HEAVY_STAT(x)
#endif
-/*
- * Define this to allow the user to change the nursery size by
- * specifying its value in the MONO_GC_PARAMS environmental
- * variable. See mono_gc_base_init for details.
- */
-#define USER_CONFIG 1
-
/*
* The binary protocol enables logging a lot of the GC ativity in a way that is not very
* intrusive and produces a compact file that can be searched using a custom tool. This
#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)
+
+/*
+ * We are trying to keep pauses lower than this (ms). We use it for dynamic nursery
+ * sizing heuristics. We are keeping leeway in order to be prepared for work-load
+ * variations.
+ */
+#define SGEN_MAX_PAUSE_TIME 30
+#define SGEN_MAX_PAUSE_MARGIN 0.66f
+
#endif
*/
gboolean has_references = SGEN_VTABLE_HAS_REFERENCES (vt);
mword objsize = SGEN_ALIGN_UP (sgen_client_par_object_get_size (vt, obj));
- destination = major_collector.alloc_object_par (vt, objsize, has_references);
+ destination = COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references);
par_copy_object_no_checks ((char*)destination, vt, obj, objsize);
#endif
#undef COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION
+#undef COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION
#undef collector_pin_object
#undef COPY_OR_MARK_PARALLEL
setup_valid_nursery_objects (void)
{
if (!valid_nursery_objects)
- valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (DEFAULT_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);
}
sgen_dump_section (GCMemSection *section, const char *type)
{
char *start = section->data;
- char *end = section->data + section->size;
+ char *end = section->end_data;
char *occ_start = NULL;
- fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)section->size);
+ fprintf (heap_dump_file, "<section type=\"%s\" size=\"%lu\">\n", type, (unsigned long)(section->end_data - section->data));
while (start < end) {
guint size;
start += sizeof (void*); /* should be ALLOC_ALIGN, really */
continue;
}
- g_assert (start < section->next_data);
if (!occ_start)
occ_start = start;
static guint64 time_max = 0;
+static int sgen_max_pause_time = SGEN_MAX_PAUSE_TIME;
+static float sgen_max_pause_margin = SGEN_MAX_PAUSE_MARGIN;
+
static SGEN_TV_DECLARE (time_major_conc_collection_start);
static SGEN_TV_DECLARE (time_major_conc_collection_end);
void **start = sgen_pinning_get_entry (section->pin_queue_first_entry);
void **end = sgen_pinning_get_entry (section->pin_queue_last_entry);
void *start_nursery = section->data;
- void *end_nursery = section->next_data;
+ void *end_nursery = section->end_data;
void *last = NULL;
int count = 0;
void *search_start;
* 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, DEFAULT_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 = section->next_data = data;
- section->size = alloc_size;
- 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 *
{
WorkerData *worker_data = (WorkerData *)worker_data_untyped;
+ if (!job->ops) {
+ /*
+ * For jobs enqueued on workers we set the ops at job runtime in order
+ * to be able to profit from on the fly optimized object ops or other
+ * object ops changes, like forced concurrent finish.
+ */
+ SGEN_ASSERT (0, sgen_workers_is_worker_thread (mono_native_thread_id_get ()), "We need a context for the scan job");
+ job->ops = sgen_workers_get_idle_func_object_ops ();
+ }
+
return CONTEXT_FROM_OBJECT_OPERATIONS (job->ops, sgen_workers_get_job_gray_queue (worker_data, job->gc_thread_gray_queue));
}
/* Mod union preclean jobs */
for (i = 0; i < split_count; i++) {
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("preclean major mod union cardtable", job_major_mod_union_preclean, sizeof (ParallelScanJob));
- psj->scan_job.ops = sgen_workers_get_idle_func_object_ops ();
psj->scan_job.gc_thread_gray_queue = NULL;
psj->job_index = i;
sgen_workers_enqueue_job (&psj->scan_job.job, TRUE);
for (i = 0; i < split_count; i++) {
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("preclean los mod union cardtable", job_los_mod_union_preclean, sizeof (ParallelScanJob));
- psj->scan_job.ops = sgen_workers_get_idle_func_object_ops ();
psj->scan_job.gc_thread_gray_queue = NULL;
psj->job_index = i;
sgen_workers_enqueue_job (&psj->scan_job.job, TRUE);
}
sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan last pinned", job_scan_last_pinned, sizeof (ScanJob));
- sj->ops = sgen_workers_get_idle_func_object_ops ();
sj->gc_thread_gray_queue = NULL;
sgen_workers_enqueue_job (&sj->job, TRUE);
}
collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_queue)
{
gboolean needs_major, is_parallel = FALSE;
- size_t max_garbage_amount;
- char *nursery_next;
mword fragment_total;
SgenGrayQueue gc_thread_gray_queue;
SgenObjectOperations *object_ops_nopar, *object_ops_par = NULL;
ScanCopyContext ctx;
+ int duration;
TV_DECLARE (atv);
TV_DECLARE (btv);
SGEN_TV_DECLARE (last_minor_collection_start_tv);
degraded_mode = 0;
objects_pinned = 0;
- nursery_next = sgen_nursery_alloc_get_upper_alloc_bound ();
- /* FIXME: optimize later to use the higher address where an object can be present */
- nursery_next = MAX (nursery_next, sgen_get_nursery_end ());
- SGEN_LOG (1, "Start nursery collection %d %p-%p, size: %d", gc_stats.minor_gc_count, sgen_get_nursery_start (), nursery_next, (int)(nursery_next - sgen_get_nursery_start ()));
- max_garbage_amount = nursery_next - sgen_get_nursery_start ();
- g_assert (nursery_section->size >= max_garbage_amount);
+ SGEN_LOG (1, "Start nursery collection %d %p-%p, size: %d", gc_stats.minor_gc_count, nursery_section->data, nursery_section->end_data, (int)(nursery_section->end_data - nursery_section->data));
/* world must be stopped already */
TV_GETTIME (btv);
sgen_client_pre_collection_checks ();
- nursery_section->next_data = nursery_next;
-
major_collector.start_nursery_collection ();
sgen_memgov_minor_collection_start ();
/* pin from pinned handles */
sgen_init_pinning ();
sgen_client_binary_protocol_mark_start (GENERATION_NURSERY);
- pin_from_roots (sgen_get_nursery_start (), nursery_next, ctx);
+ pin_from_roots (nursery_section->data, nursery_section->end_data, ctx);
/* pin cemented objects */
sgen_pin_cemented_objects ();
/* identify pinned objects */
remset.start_scan_remsets ();
- enqueue_scan_remembered_set_jobs (&gc_thread_gray_queue, is_parallel ? object_ops_par : object_ops_nopar, is_parallel);
+ enqueue_scan_remembered_set_jobs (&gc_thread_gray_queue, is_parallel ? NULL : object_ops_nopar, is_parallel);
/* we don't have complete write barrier yet, so we scan all the old generation sections */
TV_GETTIME (btv);
TV_GETTIME (atv);
time_minor_scan_pinned += TV_ELAPSED (btv, atv);
- enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, sgen_get_nursery_start (), nursery_next, is_parallel ? object_ops_par : object_ops_nopar, is_parallel);
+ enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, nursery_section->data, nursery_section->end_data, is_parallel ? NULL : object_ops_nopar, is_parallel);
if (is_parallel) {
gray_queue_redirect (&gc_thread_gray_queue);
if (remset_consistency_checks)
sgen_check_remset_consistency ();
+
+ TV_GETTIME (btv);
+ duration = (int)(TV_ELAPSED (last_minor_collection_start_tv, btv) / 10000);
+ if (duration > (sgen_max_pause_time * sgen_max_pause_margin))
+ sgen_resize_nursery (TRUE);
+ else
+ sgen_resize_nursery (FALSE);
+
/* 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.
TV_GETTIME (btv);
time_major_pre_collection_fragment_clear += TV_ELAPSED (atv, btv);
- if (!sgen_collection_is_concurrent ())
- nursery_section->next_data = sgen_get_nursery_end ();
- /* we should also coalesce scanning from sections close to each other
- * and deal with pointers outside of the sections later.
- */
-
objects_pinned = 0;
sgen_client_pre_collection_checks ();
ParallelScanJob *psj;
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan mod union cardtable", job_scan_major_mod_union_card_table, sizeof (ParallelScanJob));
- psj->scan_job.ops = object_ops_par ? object_ops_par : object_ops_nopar;
+ psj->scan_job.ops = parallel ? NULL : object_ops_nopar;
psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
psj->job_index = i;
sgen_workers_enqueue_job (&psj->scan_job.job, parallel);
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan LOS mod union cardtable", job_scan_los_mod_union_card_table, sizeof (ParallelScanJob));
- psj->scan_job.ops = object_ops_par ? object_ops_par : object_ops_nopar;
+ psj->scan_job.ops = parallel ? NULL : object_ops_nopar;
psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
psj->job_index = i;
sgen_workers_enqueue_job (&psj->scan_job.job, parallel);
gint64 tot = 0;
LOCK_GC;
tot = los_memory_usage;
- tot += nursery_section->next_data - nursery_section->data;
+ tot += nursery_section->end_data - nursery_section->data;
tot += major_collector.get_used_size ();
/* FIXME: account for pinned objects */
UNLOCK_GC;
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);
goto use_default_major;
}
- sgen_nursery_size = DEFAULT_NURSERY_SIZE;
-
if (opts) {
gboolean usage_printed = FALSE;
}
continue;
}
-
-#ifdef USER_CONFIG
if (g_str_has_prefix (opt, "nursery-size=")) {
size_t val;
opt = strchr (opt, '=') + 1;
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;
}
continue;
}
-#endif
if (g_str_has_prefix (opt, "save-target-ratio=")) {
double val;
opt = strchr (opt, '=') + 1;
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;
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)
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);
typedef struct _GCMemSection GCMemSection;
struct _GCMemSection {
char *data;
- mword size;
- /* pointer where more data could be allocated if it fits */
- char *next_data;
char *end_data;
/*
* scan starts is an array of pointers to objects equally spaced in the allocation area
#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~(((mword)1 << (bits)) - 1)) == (mword)(start))
-#ifdef USER_CONFIG
-
-/* good sizes are 512KB-1MB: larger ones increase a lot memzeroing time */
-#define DEFAULT_NURSERY_SIZE (sgen_nursery_size)
extern size_t sgen_nursery_size;
-/* The number of trailing 0 bits in DEFAULT_NURSERY_SIZE */
-#define DEFAULT_NURSERY_BITS (sgen_nursery_bits)
+extern size_t sgen_nursery_max_size;
extern int sgen_nursery_bits;
-#else
-
-#define DEFAULT_NURSERY_SIZE (4*1024*1024)
-#define DEFAULT_NURSERY_BITS 22
-
-#endif
-
extern char *sgen_nursery_start;
extern char *sgen_nursery_end;
static inline MONO_ALWAYS_INLINE gboolean
sgen_ptr_in_nursery (void *p)
{
- return SGEN_PTR_IN_NURSERY ((p), DEFAULT_NURSERY_BITS, sgen_nursery_start, sgen_nursery_end);
+ return SGEN_PTR_IN_NURSERY ((p), sgen_nursery_bits, sgen_nursery_start, sgen_nursery_end);
}
static inline MONO_ALWAYS_INLINE char*
void sgen_fragment_allocator_add (SgenFragmentAllocator *allocator, char *start, char *end);
void sgen_fragment_allocator_release (SgenFragmentAllocator *allocator);
-void* sgen_fragment_allocator_serial_alloc (SgenFragmentAllocator *allocator, size_t size);
void* sgen_fragment_allocator_par_alloc (SgenFragmentAllocator *allocator, size_t size);
void* sgen_fragment_allocator_serial_range_alloc (SgenFragmentAllocator *allocator, size_t desired_size, size_t minimum_size, size_t *out_alloc_size);
void* sgen_fragment_allocator_par_range_alloc (SgenFragmentAllocator *allocator, size_t desired_size, size_t minimum_size, size_t *out_alloc_size);
gboolean is_parallel;
GCObject* (*alloc_for_promotion) (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references);
+ GCObject* (*alloc_for_promotion_par) (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references);
SgenObjectOperations serial_ops;
SgenObjectOperations serial_ops_with_concurrent_major;
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);
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 (gboolean need_shrink);
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);
void sgen_init_allocator (void);
-char* sgen_nursery_alloc_get_upper_alloc_bound (void);
void* sgen_nursery_alloc (size_t size);
void* sgen_nursery_alloc_range (size_t size, size_t min_size, size_t *out_alloc_size);
gboolean sgen_can_alloc_size (size_t size);
} while (0)
#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION sgen_minor_collector.alloc_for_promotion
+#define COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION sgen_minor_collector.alloc_for_promotion_par
#include "sgen-copy-object.h"
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)
#include "mono/sgen/sgen-workers.h"
#include "mono/sgen/sgen-client.h"
-#define MIN_MINOR_COLLECTION_ALLOWANCE ((mword)(DEFAULT_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;
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;
/* 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;
-#ifdef USER_CONFIG
-size_t sgen_nursery_size = (1 << 22);
-int sgen_nursery_bits = 22;
-#endif
+/* good sizes are 512KB-1MB: larger ones increase a lot memzeroing time */
+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;
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 */
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);
return NULL;
}
-void*
-sgen_fragment_allocator_serial_alloc (SgenFragmentAllocator *allocator, size_t size)
-{
- SgenFragment *frag;
- SgenFragment **previous;
-#ifdef NALLOC_DEBUG
- InterlockedIncrement (&alloc_count);
-#endif
-
- previous = &allocator->alloc_head;
-
- for (frag = *previous; frag; frag = *previous) {
- char *p = (char *)serial_alloc_from_fragment (previous, frag, size);
-
- HEAVY_STAT (++stat_alloc_iterations);
-
- if (p) {
-#ifdef NALLOC_DEBUG
- add_alloc_record (p, size, FIXED_ALLOC);
-#endif
- return p;
- }
- previous = &frag->next;
- }
- return NULL;
-}
-
void*
sgen_fragment_allocator_serial_range_alloc (SgenFragmentAllocator *allocator, size_t desired_size, size_t minimum_size, size_t *out_alloc_size)
{
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) {
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;
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)
{
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
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 ();
return fragment_total;
}
-char *
-sgen_nursery_alloc_get_upper_alloc_bound (void)
-{
- /*FIXME we need to calculate the collector upper bound as well, but this must be done in the previous GC. */
- return sgen_nursery_end;
-}
-
/*** Nursery memory allocation ***/
void
sgen_nursery_retire_region (void *address, ptrdiff_t size)
}
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 (gboolean need_shrink)
+{
+ 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 && !need_shrink) {
+ 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) || need_shrink) &&
+ (sgen_nursery_size / 2) >= sgen_nursery_min_size) {
+ sgen_nursery_size /= 2;
+ }
+}
+
+
#endif
return major_collector.alloc_object (vtable, objsize, has_references);
}
+static inline GCObject*
+alloc_for_promotion_par (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references)
+{
+ /*
+ * FIXME
+ * Note that the stat is not precise. total_promoted_size incrementing is not atomic and
+ * even in that case, the same object might be promoted simultaneously by different workers
+ * leading to one of the allocated major object to be discarded.
+ */
+ total_promoted_size += objsize;
+ return major_collector.alloc_object_par (vtable, objsize, has_references);
+}
+
static SgenFragment*
build_fragments_get_exclude_head (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);
+ }
}
#define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
#define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+#define COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION alloc_for_promotion_par
#define COPY_OR_MARK_PARALLEL
#include "sgen-copy-object.h"
collector->is_parallel = parallel;
collector->alloc_for_promotion = alloc_for_promotion;
+ collector->alloc_for_promotion_par = alloc_for_promotion_par;
collector->prepare_to_space = prepare_to_space;
collector->clear_fragments = clear_fragments;
static int workers_num;
static int active_workers_num;
+static volatile gboolean started;
static volatile gboolean forced_stop;
static WorkerData *workers_data;
static SgenWorkerCallback worker_init_cb;
WorkerData *data = (WorkerData*)data_untyped;
int current_worker = (int) (data - workers_data);
- return current_worker < active_workers_num;
+ return started && current_worker < active_workers_num;
}
static void
sgen_thread_pool_wait_for_all_jobs (pool);
sgen_thread_pool_idle_wait (pool);
SGEN_ASSERT (0, sgen_workers_all_done (), "Can only signal enqueue work when in no work state");
+
+ started = FALSE;
}
void
void
sgen_workers_start_all_workers (SgenObjectOperations *object_ops_nopar, SgenObjectOperations *object_ops_par, SgenWorkersFinishCallback callback)
{
+ SGEN_ASSERT (0, !started, "Why are we starting to work without finishing previous cycle");
+
idle_func_object_ops_par = object_ops_par;
idle_func_object_ops_nopar = object_ops_nopar;
forced_stop = FALSE;
finish_callback = callback;
worker_awakenings = 0;
+ started = TRUE;
mono_memory_write_barrier ();
/*
SGEN_ASSERT (0, sgen_section_gray_queue_is_empty (&workers_distribute_gray_queue), "Why is there still work left to do?");
for (i = 0; i < active_workers_num; ++i)
SGEN_ASSERT (0, sgen_gray_object_queue_is_empty (&workers_data [i].private_gray_queue), "Why is there still work left to do?");
+
+ started = FALSE;
}
/*
SgenObjectOperations*
sgen_workers_get_idle_func_object_ops (void)
{
- return (idle_func_object_ops_par) ? idle_func_object_ops_par : idle_func_object_ops_nopar;
+ g_assert (idle_func_object_ops);
+ return idle_func_object_ops;
}
/*
$(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
$(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
$(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
$(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 \
$(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
$(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
$(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=32m,bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-conc: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=major=marksweep-conc" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-new-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=bridge-implementation=new" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-conc-new-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=bridge-implementation=new,major=marksweep-conc" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-split-new-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=bridge-implementation=new,minor=split" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=bridge-implementation=tarjan" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-test-sgen-bridge-ms-split-tarjan-bridge: $(TESTS_SGEN_BRIDGE) $(TESTSAOT_SGEN_BRIDGE) test-runner.exe
- $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ --runtime-args "--gc=sgen --gc-debug=Bridge --gc-params=bridge-implementation=tarjan,minor=split" --disabled "$(DISABLED_TESTS)" --timeout 900 $(TESTS_SGEN_BRIDGE)
-
TESTS_SGEN_BRIDGE2_SRC= \
sgen-bridge-xref.cs
$(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
$(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
$(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
$(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