X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fsgen%2Fsgen-gc.c;h=f3077a6759c9b59f006c71c62f30cd028d211bcd;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=498abf6b8e9f0818b4bc80bacfc3333b49f0be26;hpb=6ce453f2cf8299a516e818ac287c07c35d8767e5;p=mono.git diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c index 498abf6b8e9..f3077a6759c 100644 --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@ -1158,7 +1158,7 @@ finish_gray_stack (int generation, ScanCopyContext ctx) sgen_client_clear_togglerefs (start_addr, end_addr, ctx); TV_GETTIME (btv); - SGEN_LOG (2, "Finalize queue handling scan for %s generation: %ld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds); + SGEN_LOG (2, "Finalize queue handling scan for %s generation: %lld usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds); /* * handle disappearing links @@ -1550,7 +1550,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) TV_GETTIME (atv); time_minor_pinning += TV_ELAPSED (btv, atv); - SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv)); + SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (btv, atv)); SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ()); sj = (ScanJob*)sgen_thread_pool_job_alloc ("scan remset", job_remembered_set_scan, sizeof (ScanJob)); @@ -1560,7 +1560,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) /* we don't have complete write barrier yet, so we scan all the old generation sections */ TV_GETTIME (btv); time_minor_scan_remsets += TV_ELAPSED (atv, btv); - SGEN_LOG (2, "Old generation scan: %ld usecs", TV_ELAPSED (atv, btv)); + SGEN_LOG (2, "Old generation scan: %lld usecs", TV_ELAPSED (atv, btv)); sgen_pin_stats_print_class_stats (); @@ -1601,7 +1601,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark) sgen_client_binary_protocol_reclaim_end (GENERATION_NURSERY); TV_GETTIME (btv); time_minor_fragment_creation += TV_ELAPSED (atv, btv); - SGEN_LOG (2, "Fragment creation: %ld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total); + SGEN_LOG (2, "Fragment creation: %lld usecs, %lu bytes available", TV_ELAPSED (atv, btv), (unsigned long)fragment_total); if (consistency_check_at_minor_collection) sgen_check_major_refs (); @@ -1702,7 +1702,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod sgen_client_pre_collection_checks (); - if (!concurrent) { + if (mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) { /* Remsets are not useful for a major collection */ remset.clear_cards (); } @@ -1713,8 +1713,20 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod sgen_init_pinning (); SGEN_LOG (6, "Collecting pinned addresses"); pin_from_roots ((void*)lowest_heap_address, (void*)highest_heap_address, ctx); - + if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) { + /* Pin cemented objects that were forced */ + sgen_pin_cemented_objects (); + } sgen_optimize_pin_queue (); + if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) { + /* + * Cemented objects that are in the pinned list will be marked. When + * marking concurrently we won't mark mod-union cards for these objects. + * Instead they will remain cemented until the next major collection, + * when we will recheck if they are still pinned in the roots. + */ + sgen_cement_force_pinned (); + } sgen_client_collecting_major_1 (); @@ -1766,31 +1778,18 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod TV_GETTIME (btv); time_major_pinning += TV_ELAPSED (atv, btv); - SGEN_LOG (2, "Finding pinned pointers: %zd in %ld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv)); + SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), TV_ELAPSED (atv, btv)); SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ()); major_collector.init_to_space (); SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?"); - /* - * The concurrent collector doesn't move objects, neither on - * the major heap nor in the nursery, so we can mark even - * before pinning has finished. For the non-concurrent - * collector we start the workers after pinning. - */ - if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) { - if (precleaning_enabled) { - ScanJob *sj; - /* Mod union preclean job */ - sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob)); - sj->ops = object_ops; - sgen_workers_start_all_workers (object_ops, &sj->job); - } else { - sgen_workers_start_all_workers (object_ops, NULL); - } - gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE); - } else if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) { + if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) { if (sgen_workers_have_idle_work ()) { + /* + * We force the finish of the worker with the new object ops context + * which can also do copying. We need to have finished pinning. + */ sgen_workers_start_all_workers (object_ops, NULL); sgen_workers_join (); } @@ -1807,15 +1806,29 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, CopyOrMarkFromRootsMod sgen_client_collecting_major_3 (&fin_ready_queue, &critical_fin_queue); - /* - * FIXME: is this the right context? It doesn't seem to contain a copy function - * unless we're concurrent. - */ - enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT); + enqueue_scan_from_roots_jobs (heap_start, heap_end, object_ops, FALSE); TV_GETTIME (btv); time_major_scan_roots += TV_ELAPSED (atv, btv); + /* + * We start the concurrent worker after pinning and after we scanned the roots + * in order to make sure that the worker does not finish before handling all + * the roots. + */ + if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) { + if (precleaning_enabled) { + ScanJob *sj; + /* Mod union preclean job */ + sj = (ScanJob*)sgen_thread_pool_job_alloc ("preclean mod union cardtable", job_mod_union_preclean, sizeof (ScanJob)); + sj->ops = object_ops; + sgen_workers_start_all_workers (object_ops, &sj->job); + } else { + sgen_workers_start_all_workers (object_ops, NULL); + } + gray_queue_enable_redirect (WORKERS_DISTRIBUTE_GRAY_QUEUE); + } + if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) { ScanJob *sj; @@ -1839,11 +1852,6 @@ static void major_finish_copy_or_mark (CopyOrMarkFromRootsMode mode) { if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT) { - /* - * Prepare the pin queue for the next collection. Since pinning runs on the worker - * threads we must wait for the jobs to finish before we can reset it. - */ - sgen_workers_wait_for_jobs_finished (); sgen_finish_pinning (); sgen_pin_stats_reset ();