@@ -378,6 +378,33 @@ class WeakCallbackJobTask final : public cppgc::JobTask {
378378 LivenessBroker& broker_;
379379};
380380
381+ class WeakPersistentJobTask final : public cppgc::JobTask {
382+ public:
383+ WeakPersistentJobTask (MarkerBase* marker,
384+ RootMarkingVisitor* root_marking_visitor)
385+ : marker_(marker),
386+ root_marking_visitor_ (root_marking_visitor),
387+ pending_(true ) {}
388+
389+ void Run (JobDelegate* delegate) override {
390+ StatsCollector::EnabledConcurrentScope stats_scope (
391+ marker_->heap ().stats_collector (),
392+ StatsCollector::kConcurrentWeakPersistent );
393+ marker_->heap ().GetWeakPersistentRegion ().Iterate (*root_marking_visitor_);
394+ pending_.store (false );
395+ }
396+
397+ size_t GetMaxConcurrency (size_t worker_count) const override {
398+ return std::min (static_cast <size_t >(1 ),
399+ (pending_.load () ? 1 : 0 ) + worker_count);
400+ }
401+
402+ private:
403+ MarkerBase* marker_;
404+ RootMarkingVisitor* root_marking_visitor_;
405+ std::atomic<bool > pending_;
406+ };
407+
381408void MarkerBase::ProcessWeakness () {
382409 DCHECK_EQ (MarkingConfig::MarkingType::kAtomic , config_.marking_type );
383410
@@ -393,21 +420,43 @@ void MarkerBase::ProcessWeakness() {
393420 heap ().GetWeakCrossThreadPersistentRegion ().Iterate (root_marking_visitor);
394421 g_process_mutex.Pointer ()->Unlock ();
395422
396- // Launch the parallel job before anything else to provide the maximum time
397- // slice for processing.
423+ // Launch two parallel jobs before anything else to provide the maximum time
424+ // slice for processing: one for weak callbacks and one for same-thread weak
425+ // persistents.
398426 LivenessBroker broker = LivenessBrokerFactory::Create ();
399- std::unique_ptr<cppgc::JobHandle> job_handle{nullptr };
427+ std::unique_ptr<cppgc::JobHandle> weak_callback_job_handle{nullptr };
428+ std::unique_ptr<cppgc::JobHandle> weak_persistent_job_handle{nullptr };
400429 if (heap ().marking_support () ==
401430 cppgc::Heap::MarkingType::kIncrementalAndConcurrent ) {
402- job_handle = platform_->PostJob (
431+ weak_callback_job_handle = platform_->PostJob (
403432 cppgc::TaskPriority::kUserBlocking ,
404433 std::make_unique<WeakCallbackJobTask>(
405434 this , marking_worklists_.parallel_weak_callback_worklist (),
406435 broker));
436+ weak_persistent_job_handle = platform_->PostJob (
437+ cppgc::TaskPriority::kUserBlocking ,
438+ std::make_unique<WeakPersistentJobTask>(this , &root_marking_visitor));
439+ }
440+
441+ {
442+ // Process weak container callbacks.
443+ StatsCollector::EnabledScope stats_scope (
444+ heap ().stats_collector (),
445+ StatsCollector::kWeakContainerCallbacksProcessing );
446+ MarkingWorklists::WeakCallbackItem item;
447+ MarkingWorklists::WeakCallbackWorklist::Local& collections_local =
448+ mutator_marking_state_.weak_container_callback_worklist ();
449+ while (collections_local.Pop (&item)) {
450+ item.callback (broker, item.parameter );
451+ }
407452 }
408453
409- // Process same-thread roots.
410- heap ().GetWeakPersistentRegion ().Iterate (root_marking_visitor);
454+ // Finish processing same-thread WeakPersistents.
455+ if (weak_persistent_job_handle) {
456+ weak_persistent_job_handle->Join ();
457+ } else {
458+ heap ().GetWeakPersistentRegion ().Iterate (root_marking_visitor);
459+ }
411460
412461 // Call weak callbacks on objects that may now be pointing to dead objects.
413462#if defined(CPPGC_YOUNG_GENERATION)
@@ -430,19 +479,10 @@ void MarkerBase::ProcessWeakness() {
430479#endif // defined(CPPGC_YOUNG_GENERATION)
431480
432481 {
433- // First, process weak container callbacks.
434- StatsCollector::EnabledScope stats_scope (
435- heap ().stats_collector (),
436- StatsCollector::kWeakContainerCallbacksProcessing );
437- MarkingWorklists::WeakCallbackItem item;
438- MarkingWorklists::WeakCallbackWorklist::Local& collections_local =
439- mutator_marking_state_.weak_container_callback_worklist ();
440- while (collections_local.Pop (&item)) {
441- item.callback (broker, item.parameter );
442- }
443- }
444- {
445- // Then, process custom weak callbacks.
482+ // Process custom weak callbacks.
483+ // Processing same-thread WeakPersistents must be finished before this, as
484+ // custom weak callbacks may allocate new WeakPersistents, thus leading to
485+ // data races.
446486 StatsCollector::EnabledScope stats_scope (
447487 heap ().stats_collector (), StatsCollector::kCustomCallbacksProcessing );
448488 MarkingWorklists::WeakCallbackItem item;
@@ -457,8 +497,9 @@ void MarkerBase::ProcessWeakness() {
457497 }
458498 }
459499
460- if (job_handle) {
461- job_handle->Join ();
500+ // Finish processing parallel weak callbacks.
501+ if (weak_callback_job_handle) {
502+ weak_callback_job_handle->Join ();
462503 } else {
463504 MarkingWorklists::WeakCallbackItem item;
464505 MarkingWorklists::WeakCallbackWorklist::Local& local =
0 commit comments