diff options
Diffstat (limited to 'deps/v8/src/heap/array-buffer-sweeper.cc')
-rw-r--r-- | deps/v8/src/heap/array-buffer-sweeper.cc | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/deps/v8/src/heap/array-buffer-sweeper.cc b/deps/v8/src/heap/array-buffer-sweeper.cc index 088e9e4ac5..370ed0aa81 100644 --- a/deps/v8/src/heap/array-buffer-sweeper.cc +++ b/deps/v8/src/heap/array-buffer-sweeper.cc @@ -7,10 +7,12 @@ #include <atomic> #include <memory> +#include "src/base/logging.h" #include "src/heap/gc-tracer-inl.h" #include "src/heap/gc-tracer.h" #include "src/heap/heap-inl.h" #include "src/heap/heap.h" +#include "src/heap/remembered-set.h" #include "src/objects/js-array-buffer.h" #include "src/tasks/cancelable-task.h" #include "src/tasks/task-utils.h" @@ -76,11 +78,13 @@ bool ArrayBufferList::IsEmpty() const { } struct ArrayBufferSweeper::SweepingJob final { - SweepingJob(ArrayBufferList young, ArrayBufferList old, SweepingType type) + SweepingJob(ArrayBufferList young, ArrayBufferList old, SweepingType type, + TreatAllYoungAsPromoted treat_all_young_as_promoted) : state_(SweepingState::kInProgress), young_(std::move(young)), old_(std::move(old)), - type_(type) {} + type_(type), + treat_all_young_as_promoted_(treat_all_young_as_promoted) {} void Sweep(); void SweepYoung(); @@ -93,12 +97,14 @@ struct ArrayBufferSweeper::SweepingJob final { ArrayBufferList young_; ArrayBufferList old_; const SweepingType type_; - std::atomic<size_t> freed_bytes_{0}; + size_t freed_bytes_{0}; + TreatAllYoungAsPromoted treat_all_young_as_promoted_; friend class ArrayBufferSweeper; }; -ArrayBufferSweeper::ArrayBufferSweeper(Heap* heap) : heap_(heap) {} +ArrayBufferSweeper::ArrayBufferSweeper(Heap* heap) + : heap_(heap), local_sweeper_(heap_->sweeper()) {} ArrayBufferSweeper::~ArrayBufferSweeper() { EnsureFinished(); @@ -115,7 +121,7 @@ void ArrayBufferSweeper::EnsureFinished() { switch (abort_result) { case TryAbortResult::kTaskAborted: // Task has not run, so we need to run it synchronously here. - job_->Sweep(); + DoSweep(); break; case TryAbortResult::kTaskRemoved: // Task was removed, but did actually run, just ensure we are in the right @@ -146,13 +152,15 @@ void ArrayBufferSweeper::FinishIfDone() { } } -void ArrayBufferSweeper::RequestSweep(SweepingType type) { +void ArrayBufferSweeper::RequestSweep( + SweepingType type, TreatAllYoungAsPromoted treat_all_young_as_promoted) { DCHECK(!sweeping_in_progress()); + DCHECK(local_sweeper_.IsEmpty()); if (young_.IsEmpty() && (old_.IsEmpty() || type == SweepingType::kYoung)) return; - Prepare(type); + Prepare(type, treat_all_young_as_promoted); if (!heap_->IsTearingDown() && !heap_->ShouldReduceMemory() && v8_flags.concurrent_array_buffer_sweeping) { auto task = MakeCancelableTask(heap_->isolate(), [this, type] { @@ -162,28 +170,46 @@ void ArrayBufferSweeper::RequestSweep(SweepingType type) { : GCTracer::Scope::BACKGROUND_FULL_ARRAY_BUFFER_SWEEP; TRACE_GC_EPOCH(heap_->tracer(), scope_id, ThreadKind::kBackground); base::MutexGuard guard(&sweeping_mutex_); - job_->Sweep(); + DoSweep(); job_finished_.NotifyAll(); }); job_->id_ = task->id(); V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task)); } else { - job_->Sweep(); + GCTracer::Scope::ScopeId scope_id = + type == SweepingType::kYoung ? GCTracer::Scope::YOUNG_ARRAY_BUFFER_SWEEP + : GCTracer::Scope::FULL_ARRAY_BUFFER_SWEEP; + TRACE_GC_EPOCH(heap_->tracer(), scope_id, ThreadKind::kMain); + DoSweep(); Finalize(); } } -void ArrayBufferSweeper::Prepare(SweepingType type) { +void ArrayBufferSweeper::DoSweep() { + DCHECK_NOT_NULL(job_); + if (job_->treat_all_young_as_promoted_ == TreatAllYoungAsPromoted::kNo) { + // Waiting for promoted page iteration is only needed when not all young + // array buffers are promoted. + local_sweeper_.ContributeAndWaitForPromotedPagesIteration(); + DCHECK(!heap_->sweeper()->IsIteratingPromotedPages()); + } + job_->Sweep(); +} + +void ArrayBufferSweeper::Prepare( + SweepingType type, TreatAllYoungAsPromoted treat_all_young_as_promoted) { DCHECK(!sweeping_in_progress()); + DCHECK_IMPLIES(type == SweepingType::kFull, + treat_all_young_as_promoted == TreatAllYoungAsPromoted::kYes); switch (type) { case SweepingType::kYoung: { job_ = std::make_unique<SweepingJob>(std::move(young_), ArrayBufferList(), - type); + type, treat_all_young_as_promoted); young_ = ArrayBufferList(); } break; case SweepingType::kFull: { job_ = std::make_unique<SweepingJob>(std::move(young_), std::move(old_), - type); + type, treat_all_young_as_promoted); young_ = ArrayBufferList(); old_ = ArrayBufferList(); } break; @@ -196,9 +222,10 @@ void ArrayBufferSweeper::Finalize() { CHECK_EQ(job_->state_, SweepingState::kDone); young_.Append(&job_->young_); old_.Append(&job_->old_); - const size_t freed_bytes = - job_->freed_bytes_.exchange(0, std::memory_order_relaxed); - DecrementExternalMemoryCounters(freed_bytes); + DecrementExternalMemoryCounters(job_->freed_bytes_); + + local_sweeper_.Finalize(); + job_.reset(); DCHECK(!sweeping_in_progress()); } @@ -230,16 +257,18 @@ void ArrayBufferSweeper::Append(JSArrayBuffer object, void ArrayBufferSweeper::Detach(JSArrayBuffer object, ArrayBufferExtension* extension) { + // Finish sweeping here first such that the code below is guaranteed to + // observe the same sweeping state. + FinishIfDone(); + size_t bytes = extension->ClearAccountingLength(); // We cannot free the extension eagerly here, since extensions are tracked in // a singly linked list. The next GC will remove it automatically. - FinishIfDone(); - if (!sweeping_in_progress()) { // If concurrent sweeping isn't running at the moment, we can also adjust - // the respective bytes in the corresponding ArraybufferLists as they are + // the respective bytes in the corresponding ArrayBufferLists as they are // only approximate. if (Heap::InYoungGeneration(object)) { DCHECK_GE(young_.bytes_, bytes); @@ -303,7 +332,7 @@ ArrayBufferList ArrayBufferSweeper::SweepingJob::SweepListFull( if (!current->IsMarked()) { const size_t bytes = current->accounting_length(); delete current; - if (bytes) freed_bytes_.fetch_add(bytes, std::memory_order_relaxed); + if (bytes) freed_bytes_ += bytes; } else { current->Unmark(); survivor_list.Append(current); @@ -329,8 +358,10 @@ void ArrayBufferSweeper::SweepingJob::SweepYoung() { if (!current->IsYoungMarked()) { size_t bytes = current->accounting_length(); delete current; - if (bytes) freed_bytes_.fetch_add(bytes, std::memory_order_relaxed); - } else if (current->IsYoungPromoted()) { + if (bytes) freed_bytes_ += bytes; + } else if ((treat_all_young_as_promoted_ == + TreatAllYoungAsPromoted::kYes) || + current->IsYoungPromoted()) { current->YoungUnmark(); new_old.Append(current); } else { |