case GENERATION_NURSERY:
return FALSE;
case GENERATION_OLD:
- return major_collector.is_concurrent;
+ return concurrent_collection_in_progress;
default:
g_error ("Invalid current generation %d", current_collection_generation);
}
ScanFinalizerEntriesJobData *sfejd_fin_ready, *sfejd_critical_fin;
ScanCopyContext ctx;
- if (major_collector.is_concurrent) {
+ if (concurrent_collection_in_progress) {
/*This cleans up unused fragments */
sgen_nursery_allocator_prepare_for_pinning ();
if (whole_heap_check_before_collection)
sgen_check_whole_heap (finish_up_concurrent_mark);
- if (!major_collector.is_concurrent)
- sgen_cement_reset ();
-
TV_GETTIME (btv);
time_major_pre_collection_fragment_clear += TV_ELAPSED (atv, btv);
check_for_xdomain_refs ();
}
- if (!major_collector.is_concurrent) {
+ if (!concurrent_collection_in_progress) {
/* Remsets are not useful for a major collection */
remset.prepare_for_major_collection ();
}
sgen_init_pinning ();
SGEN_LOG (6, "Collecting pinned addresses");
pin_from_roots ((void*)lowest_heap_address, (void*)highest_heap_address, WORKERS_DISTRIBUTE_GRAY_QUEUE);
+
+ if (!concurrent_collection_in_progress) {
+ if (major_collector.is_concurrent) {
+ /*
+ * The concurrent major collector cannot evict
+ * yet, so we need to pin cemented objects to
+ * not break some asserts.
+ */
+ sgen_cement_iterate (pin_stage_object_callback, NULL);
+ }
+
+ sgen_cement_reset ();
+ }
+
sgen_optimize_pin_queue (0);
/*
* before pinning has finished. For the non-concurrent
* collector we start the workers after pinning.
*/
- if (major_collector.is_concurrent) {
+ if (concurrent_collection_in_progress) {
sgen_workers_start_all_workers ();
sgen_workers_start_marking ();
}
* Non-concurrent mark evacuates from the nursery, so it's
* sufficient to just scan pinned nursery objects.
*/
- if (major_collector.is_concurrent && sgen_minor_collector.is_split) {
+ if (concurrent_collection_in_progress && sgen_minor_collector.is_split) {
scan_nursery_objects (ctx);
} else {
sgen_pin_objects_in_section (nursery_section, ctx);
main_gc_thread = mono_native_thread_self ();
#endif
- if (!major_collector.is_concurrent) {
+ if (!concurrent_collection_in_progress && major_collector.is_parallel) {
sgen_workers_start_all_workers ();
sgen_workers_start_marking ();
}
TV_GETTIME (btv);
time_major_scan_big_objects += TV_ELAPSED (atv, btv);
- if (major_collector.is_concurrent) {
+ if (concurrent_collection_in_progress) {
/* prepare the pin queue for the next collection */
sgen_finish_pinning ();
}
static void
-major_start_collection (int *old_next_pin_slot)
+major_start_collection (gboolean concurrent, int *old_next_pin_slot)
{
MONO_GC_BEGIN (GENERATION_OLD);
binary_protocol_collection_begin (stat_major_gcs, GENERATION_OLD);
g_assert (sgen_section_gray_queue_is_empty (sgen_workers_get_distribute_section_gray_queue ()));
- if (major_collector.is_concurrent) {
+ if (concurrent) {
+ g_assert (major_collector.is_concurrent);
concurrent_collection_in_progress = TRUE;
sgen_cement_concurrent_start ();
static void
wait_for_workers_to_finish (void)
{
- if (major_collector.is_parallel || major_collector.is_concurrent) {
+ if (concurrent_collection_in_progress || major_collector.is_parallel) {
gray_queue_redirect (&gray_queue);
sgen_workers_join ();
}
TV_GETTIME (btv);
- if (major_collector.is_concurrent || major_collector.is_parallel)
+ if (concurrent_collection_in_progress || major_collector.is_parallel)
wait_for_workers_to_finish ();
current_object_ops = major_collector.major_ops;
- if (major_collector.is_concurrent) {
+ if (concurrent_collection_in_progress) {
major_copy_or_mark_from_roots (NULL, TRUE, scan_mod_union);
wait_for_workers_to_finish ();
sgen_workers_reset_data ();
if (objects_pinned) {
- g_assert (!major_collector.is_concurrent);
+ g_assert (!concurrent_collection_in_progress);
/*This is slow, but we just OOM'd*/
sgen_pin_queue_clear_discarded_entries (nursery_section, old_next_pin_slot);
TV_GETTIME (btv);
time_major_sweep += TV_ELAPSED (atv, btv);
- if (!major_collector.is_concurrent) {
+ if (!concurrent_collection_in_progress) {
/* 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.
sgen_pin_stats_reset ();
}
- if (major_collector.is_concurrent)
+ if (concurrent_collection_in_progress)
sgen_cement_concurrent_finish ();
sgen_cement_clear_below_threshold ();
g_assert (sgen_section_gray_queue_is_empty (sgen_workers_get_distribute_section_gray_queue ()));
- if (major_collector.is_concurrent)
+ if (concurrent_collection_in_progress)
concurrent_collection_in_progress = FALSE;
check_scan_starts ();
/* world must be stopped already */
TV_GETTIME (all_atv);
- major_start_collection (&old_next_pin_slot);
+ major_start_collection (FALSE, &old_next_pin_slot);
major_finish_collection (reason, old_next_pin_slot, FALSE);
TV_GETTIME (all_btv);
MONO_GC_CONCURRENT_START_BEGIN (GENERATION_OLD);
// FIXME: store reason and pass it when finishing
- major_start_collection (NULL);
+ major_start_collection (TRUE, NULL);
gray_queue_redirect (&gray_queue);
sgen_workers_wait_for_jobs ();
overflow_reason = "Minor overflow";
}
} else {
- SgenGrayQueue unpin_queue;
- SgenGrayQueue *unpin_queue_ptr;
- memset (&unpin_queue, 0, sizeof (unpin_queue));
-
- if (major_collector.is_concurrent && wait_to_finish)
- unpin_queue_ptr = &unpin_queue;
- else
- unpin_queue_ptr = NULL;
-
if (major_collector.is_concurrent) {
g_assert (!concurrent_collection_in_progress);
- collect_nursery (unpin_queue_ptr, FALSE);
+ if (!wait_to_finish)
+ collect_nursery (NULL, FALSE);
}
if (major_collector.is_concurrent && !wait_to_finish) {
overflow_reason = "Excessive pinning";
}
}
-
- if (unpin_queue_ptr) {
- unpin_objects_from_queue (unpin_queue_ptr);
- sgen_gray_object_queue_deinit (unpin_queue_ptr);
- }
}
TV_GETTIME (gc_end);