Commit 48e93e20 authored by Dominik Inführ's avatar Dominik Inführ Committed by Commit Bot

[heap] Update array buffer byte counters sooner

Before this CL array buffer counters were only decremented at the next
GC. This CL makes freed_bytes_ an atomic variable which is incremented
by the concurrent sweeping task. The main thread now also inspects this
value when adding new JSArrayBuffers to update counters sooner.

Bug: v8:10064
Change-Id: Ibcb245b541e806b95a3c2c42d3cc3affe7739e4d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2047043
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66221}
parent 2afe890d
...@@ -74,14 +74,14 @@ void ArrayBufferSweeper::EnsureFinished() { ...@@ -74,14 +74,14 @@ void ArrayBufferSweeper::EnsureFinished() {
switch (abort_result) { switch (abort_result) {
case TryAbortResult::kTaskAborted: { case TryAbortResult::kTaskAborted: {
job_.Sweep(); Sweep();
Merge(); Merge();
break; break;
} }
case TryAbortResult::kTaskRemoved: { case TryAbortResult::kTaskRemoved: {
CHECK_NE(job_.state, SweepingState::Uninitialized); CHECK_NE(job_.state, SweepingState::Uninitialized);
if (job_.state == SweepingState::Prepared) job_.Sweep(); if (job_.state == SweepingState::Prepared) Sweep();
Merge(); Merge();
break; break;
} }
...@@ -106,9 +106,18 @@ void ArrayBufferSweeper::EnsureFinished() { ...@@ -106,9 +106,18 @@ void ArrayBufferSweeper::EnsureFinished() {
} }
void ArrayBufferSweeper::DecrementExternalMemoryCounters() { void ArrayBufferSweeper::DecrementExternalMemoryCounters() {
size_t bytes = freed_bytes_.load(std::memory_order_relaxed);
if (bytes == 0) return;
while (!freed_bytes_.compare_exchange_weak(bytes, 0)) {
// empty body
}
if (bytes == 0) return;
heap_->DecrementExternalBackingStoreBytes( heap_->DecrementExternalBackingStoreBytes(
ExternalBackingStoreType::kArrayBuffer, job_.freed_bytes); ExternalBackingStoreType::kArrayBuffer, bytes);
heap_->update_external_memory(-static_cast<int64_t>(job_.freed_bytes)); heap_->update_external_memory(-static_cast<int64_t>(bytes));
} }
void ArrayBufferSweeper::RequestSweepYoung() { void ArrayBufferSweeper::RequestSweepYoung() {
...@@ -132,7 +141,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) { ...@@ -132,7 +141,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) {
CHECK(V8_ARRAY_BUFFER_EXTENSION_BOOL); CHECK(V8_ARRAY_BUFFER_EXTENSION_BOOL);
if (!heap_->IsTearingDown() && !heap_->ShouldReduceMemory() && if (!heap_->IsTearingDown() && !heap_->ShouldReduceMemory() &&
!heap_->is_current_gc_forced() && FLAG_concurrent_array_buffer_sweeping) { FLAG_concurrent_array_buffer_sweeping) {
Prepare(scope); Prepare(scope);
auto task = MakeCancelableTask(heap_->isolate(), [this] { auto task = MakeCancelableTask(heap_->isolate(), [this] {
...@@ -140,7 +149,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) { ...@@ -140,7 +149,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) {
heap_->tracer(), heap_->tracer(),
GCTracer::BackgroundScope::BACKGROUND_ARRAY_BUFFER_SWEEP); GCTracer::BackgroundScope::BACKGROUND_ARRAY_BUFFER_SWEEP);
base::MutexGuard guard(&sweeping_mutex_); base::MutexGuard guard(&sweeping_mutex_);
job_.Sweep(); Sweep();
job_finished_.NotifyAll(); job_finished_.NotifyAll();
}); });
job_.id = task->id(); job_.id = task->id();
...@@ -148,7 +157,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) { ...@@ -148,7 +157,7 @@ void ArrayBufferSweeper::RequestSweep(SweepingScope scope) {
sweeping_in_progress_ = true; sweeping_in_progress_ = true;
} else { } else {
Prepare(scope); Prepare(scope);
job_.Sweep(); Sweep();
Merge(); Merge();
DecrementExternalMemoryCounters(); DecrementExternalMemoryCounters();
} }
...@@ -210,6 +219,7 @@ void ArrayBufferSweeper::Append(JSArrayBuffer object, ...@@ -210,6 +219,7 @@ void ArrayBufferSweeper::Append(JSArrayBuffer object,
old_bytes_ += bytes; old_bytes_ += bytes;
} }
DecrementExternalMemoryCounters();
IncrementExternalMemoryCounters(bytes); IncrementExternalMemoryCounters(bytes);
} }
...@@ -231,44 +241,41 @@ ArrayBufferSweeper::SweepingJob ArrayBufferSweeper::SweepingJob::Prepare( ...@@ -231,44 +241,41 @@ ArrayBufferSweeper::SweepingJob ArrayBufferSweeper::SweepingJob::Prepare(
job.scope = scope; job.scope = scope;
job.id = 0; job.id = 0;
job.state = SweepingState::Prepared; job.state = SweepingState::Prepared;
job.freed_bytes = 0;
return job; return job;
} }
void ArrayBufferSweeper::SweepingJob::Sweep() { void ArrayBufferSweeper::Sweep() {
CHECK_EQ(state, SweepingState::Prepared); CHECK_EQ(job_.state, SweepingState::Prepared);
if (scope == SweepingScope::Young) { if (job_.scope == SweepingScope::Young) {
SweepYoung(); SweepYoung();
} else { } else {
CHECK_EQ(scope, SweepingScope::Full); CHECK_EQ(job_.scope, SweepingScope::Full);
SweepFull(); SweepFull();
} }
state = SweepingState::Swept; job_.state = SweepingState::Swept;
} }
void ArrayBufferSweeper::SweepingJob::SweepFull() { void ArrayBufferSweeper::SweepFull() {
CHECK_EQ(scope, SweepingScope::Full); CHECK_EQ(job_.scope, SweepingScope::Full);
ArrayBufferList promoted = SweepListFull(&young); ArrayBufferList promoted = SweepListFull(&job_.young);
ArrayBufferList survived = SweepListFull(&old); ArrayBufferList survived = SweepListFull(&job_.old);
old = promoted; job_.old = promoted;
old.Append(&survived); job_.old.Append(&survived);
} }
ArrayBufferList ArrayBufferSweeper::SweepingJob::SweepListFull( ArrayBufferList ArrayBufferSweeper::SweepListFull(ArrayBufferList* list) {
ArrayBufferList* list) {
ArrayBufferExtension* current = list->head_; ArrayBufferExtension* current = list->head_;
ArrayBufferList survivor_list; ArrayBufferList survivor_list;
size_t freed_bytes = 0;
while (current) { while (current) {
ArrayBufferExtension* next = current->next(); ArrayBufferExtension* next = current->next();
if (!current->IsMarked()) { if (!current->IsMarked()) {
freed_bytes += current->accounting_length(); size_t bytes = current->accounting_length();
delete current; delete current;
IncrementFreedBytes(bytes);
} else { } else {
current->Unmark(); current->Unmark();
survivor_list.Append(current); survivor_list.Append(current);
...@@ -277,27 +284,24 @@ ArrayBufferList ArrayBufferSweeper::SweepingJob::SweepListFull( ...@@ -277,27 +284,24 @@ ArrayBufferList ArrayBufferSweeper::SweepingJob::SweepListFull(
current = next; current = next;
} }
this->freed_bytes += freed_bytes;
list->Reset(); list->Reset();
return survivor_list; return survivor_list;
} }
void ArrayBufferSweeper::SweepingJob::SweepYoung() { void ArrayBufferSweeper::SweepYoung() {
CHECK_EQ(scope, SweepingScope::Young); CHECK_EQ(job_.scope, SweepingScope::Young);
ArrayBufferExtension* current = young.head_; ArrayBufferExtension* current = job_.young.head_;
ArrayBufferList new_young; ArrayBufferList new_young;
ArrayBufferList new_old; ArrayBufferList new_old;
size_t freed_bytes = 0;
while (current) { while (current) {
ArrayBufferExtension* next = current->next(); ArrayBufferExtension* next = current->next();
if (!current->IsYoungMarked()) { if (!current->IsYoungMarked()) {
freed_bytes += current->accounting_length(); size_t bytes = current->accounting_length();
delete current; delete current;
IncrementFreedBytes(bytes);
} else if (current->IsYoungPromoted()) { } else if (current->IsYoungPromoted()) {
current->YoungUnmark(); current->YoungUnmark();
new_old.Append(current); new_old.Append(current);
...@@ -309,9 +313,13 @@ void ArrayBufferSweeper::SweepingJob::SweepYoung() { ...@@ -309,9 +313,13 @@ void ArrayBufferSweeper::SweepingJob::SweepYoung() {
current = next; current = next;
} }
this->freed_bytes += freed_bytes; job_.old = new_old;
old = new_old; job_.young = new_young;
young = new_young; }
void ArrayBufferSweeper::IncrementFreedBytes(size_t bytes) {
if (bytes == 0) return;
freed_bytes_.fetch_add(bytes);
} }
} // namespace internal } // namespace internal
......
...@@ -50,6 +50,7 @@ class ArrayBufferSweeper { ...@@ -50,6 +50,7 @@ class ArrayBufferSweeper {
explicit ArrayBufferSweeper(Heap* heap) explicit ArrayBufferSweeper(Heap* heap)
: heap_(heap), : heap_(heap),
sweeping_in_progress_(false), sweeping_in_progress_(false),
freed_bytes_(0),
young_bytes_(0), young_bytes_(0),
old_bytes_(0) {} old_bytes_(0) {}
~ArrayBufferSweeper() { ReleaseAll(); } ~ArrayBufferSweeper() { ReleaseAll(); }
...@@ -77,14 +78,9 @@ class ArrayBufferSweeper { ...@@ -77,14 +78,9 @@ class ArrayBufferSweeper {
ArrayBufferList young; ArrayBufferList young;
ArrayBufferList old; ArrayBufferList old;
SweepingScope scope; SweepingScope scope;
size_t freed_bytes;
SweepingJob(); SweepingJob();
void Sweep();
void SweepYoung();
void SweepFull();
ArrayBufferList SweepListFull(ArrayBufferList* list);
static SweepingJob Prepare(ArrayBufferList young, ArrayBufferList old, static SweepingJob Prepare(ArrayBufferList young, ArrayBufferList old,
SweepingScope scope); SweepingScope scope);
} job_; } job_;
...@@ -93,11 +89,16 @@ class ArrayBufferSweeper { ...@@ -93,11 +89,16 @@ class ArrayBufferSweeper {
void DecrementExternalMemoryCounters(); void DecrementExternalMemoryCounters();
void IncrementExternalMemoryCounters(size_t bytes); void IncrementExternalMemoryCounters(size_t bytes);
void IncrementFreedBytes(size_t bytes);
void RequestSweep(SweepingScope sweeping_task); void RequestSweep(SweepingScope sweeping_task);
void Prepare(SweepingScope sweeping_task); void Prepare(SweepingScope sweeping_task);
void Sweep();
void SweepYoung();
void SweepFull();
ArrayBufferList SweepListFull(ArrayBufferList* list); ArrayBufferList SweepListFull(ArrayBufferList* list);
ArrayBufferList SweepYoungGen(); ArrayBufferList SweepYoungGen();
void SweepOldGen(ArrayBufferExtension* extension); void SweepOldGen(ArrayBufferExtension* extension);
...@@ -108,6 +109,7 @@ class ArrayBufferSweeper { ...@@ -108,6 +109,7 @@ class ArrayBufferSweeper {
bool sweeping_in_progress_; bool sweeping_in_progress_;
base::Mutex sweeping_mutex_; base::Mutex sweeping_mutex_;
base::ConditionVariable job_finished_; base::ConditionVariable job_finished_;
std::atomic<size_t> freed_bytes_;
ArrayBufferList young_; ArrayBufferList young_;
ArrayBufferList old_; ArrayBufferList old_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment