From 820988907cd3b4868c720b76daed49dd4dd216bd Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 13 Apr 2017 01:20:07 +0300 Subject: [PATCH] [sgen] Use the idle object ops for worker jobs We had the object ops set in the job when allocating the job (typically by the main gc thread). When enqueueing jobs, we leave their ops NULL, and when the worker actually executes the job, it will use the idle object ops, which can get dynamically optimized over the work cycle. --- mono/sgen/sgen-gc.c | 21 ++++++++++++++------- mono/sgen/sgen-workers.c | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c index 2c0337d6a35..66eb9ab194b 100644 --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@ -1346,6 +1346,16 @@ scan_copy_context_for_scan_job (void *worker_data_untyped, ScanJob *job) { 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)); } @@ -1494,7 +1504,6 @@ workers_finish_callback (void) /* 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); @@ -1502,14 +1511,12 @@ workers_finish_callback (void) 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); } @@ -1703,7 +1710,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ 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); @@ -1718,7 +1725,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_ TV_GETTIME (atv); time_minor_scan_pinned += TV_ELAPSED (btv, atv); - enqueue_scan_from_roots_jobs (&gc_thread_gray_queue, nursery_section->data, nursery_section->end_data, 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); @@ -2001,13 +2008,13 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_ 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); diff --git a/mono/sgen/sgen-workers.c b/mono/sgen/sgen-workers.c index 73691061643..82d637d2b26 100644 --- a/mono/sgen/sgen-workers.c +++ b/mono/sgen/sgen-workers.c @@ -536,7 +536,8 @@ sgen_workers_take_from_queue (SgenGrayQueue *queue) 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; } /* -- 2.25.1