Skip to content

Commit 9144af8

Browse files
nickieV8 LUCI CQ
authored andcommitted
[cppgc] Make clearing of weak persistents concurrent
Oilpan's weakness clearing phase often takes around 10% of the overall mark-compact pause. A small portion is taken by the clearing of same-thread WeakPersistent handles. This CL introduces a concurrent job for clearing such handles, in parallel to weak container callbacks. Bug: 349952799 Change-Id: I497b199edd674379d552281125cdca65bc766bd3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5822092 Reviewed-by: Anton Bikineev <[email protected]> Reviewed-by: Michael Lippautz <[email protected]> Commit-Queue: Nikolaos Papaspyrou <[email protected]> Cr-Commit-Position: refs/heads/main@{#95872}
1 parent 47bc5fa commit 9144af8

File tree

4 files changed

+71
-23
lines changed

4 files changed

+71
-23
lines changed

include/cppgc/internal/persistent-node.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ class V8_EXPORT PersistentRegion final : public PersistentRegionBase {
158158
PersistentRegionBase::FreeNode(node);
159159
}
160160

161+
// During GC, nodes can be freed from a concurrent thread, so no thread check
162+
// takes place here.
163+
V8_INLINE void FreeNodeFromGC(PersistentNode* node) {
164+
PersistentRegionBase::FreeNode(node);
165+
}
166+
161167
private:
162168
bool IsCreationThread();
163169

include/cppgc/persistent.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class BasicPersistent final : public PersistentBase,
256256

257257
void ClearFromGC() const {
258258
if (IsValid()) {
259-
WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
259+
WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNodeFromGC(GetNode());
260260
PersistentBase::ClearFromGC();
261261
}
262262
}

src/heap/cppgc/marker.cc

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
381408
void 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 =

src/heap/cppgc/stats-collector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ namespace internal {
6767
#define CPPGC_FOR_ALL_HISTOGRAM_CONCURRENT_SCOPES(V) \
6868
V(ConcurrentMark) \
6969
V(ConcurrentSweep) \
70-
V(ConcurrentWeakCallback)
70+
V(ConcurrentWeakCallback) \
71+
V(ConcurrentWeakPersistent)
7172

7273
#define CPPGC_FOR_ALL_CONCURRENT_SCOPES(V) V(ConcurrentMarkProcessEphemerons)
7374

0 commit comments

Comments
 (0)