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.
{
WorkerData *worker_data = (WorkerData *)worker_data_untyped;
{
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));
}
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));
/* 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);
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));
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));
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);
}
sj->gc_thread_gray_queue = NULL;
sgen_workers_enqueue_job (&sj->job, TRUE);
}
remset.start_scan_remsets ();
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);
/* 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);
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);
if (is_parallel) {
gray_queue_redirect (&gc_thread_gray_queue);
ParallelScanJob *psj;
psj = (ParallelScanJob*)sgen_thread_pool_job_alloc ("scan mod union cardtable", job_scan_major_mod_union_card_table, sizeof (ParallelScanJob));
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.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);
psj->scan_job.gc_thread_gray_queue = gc_thread_gray_queue;
psj->job_index = i;
sgen_workers_enqueue_job (&psj->scan_job.job, parallel);
SgenObjectOperations*
sgen_workers_get_idle_func_object_ops (void)
{
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;