Index: src/heap/array-buffer-tracker.cc |
diff --git a/src/heap/array-buffer-tracker.cc b/src/heap/array-buffer-tracker.cc |
index 62b848ef70c5339bf6bd3be7585b9290a4b022fb..bffe437c58e515f29f21b1c8c94cfd5cd1ed6b66 100644 |
--- a/src/heap/array-buffer-tracker.cc |
+++ b/src/heap/array-buffer-tracker.cc |
@@ -14,7 +14,7 @@ LocalArrayBufferTracker::~LocalArrayBufferTracker() { |
} |
template <LocalArrayBufferTracker::FreeMode free_mode> |
-void LocalArrayBufferTracker::Free() { |
+LocalArrayBufferTracker::ProcessResult LocalArrayBufferTracker::Free() { |
size_t freed_memory = 0; |
for (TrackingData::iterator it = array_buffers_.begin(); |
it != array_buffers_.end();) { |
@@ -30,60 +30,71 @@ void LocalArrayBufferTracker::Free() { |
++it; |
} |
} |
- if (freed_memory > 0) { |
- heap_->update_external_memory_concurrently_freed( |
- static_cast<intptr_t>(freed_memory)); |
- } |
+ return ProcessResult(freed_memory, 0); |
} |
template <typename Callback> |
-void LocalArrayBufferTracker::Process(Callback callback) { |
+LocalArrayBufferTracker::ProcessResult LocalArrayBufferTracker::Process( |
+ Callback callback) { |
JSArrayBuffer* new_buffer = nullptr; |
size_t freed_memory = 0; |
+ size_t promoted_memory = 0; |
+ size_t len = 0; |
+ Page* target_page = nullptr; |
+ LocalArrayBufferTracker* tracker = nullptr; |
for (TrackingData::iterator it = array_buffers_.begin(); |
it != array_buffers_.end();) { |
- const CallbackResult result = callback(it->first, &new_buffer); |
- if (result == kKeepEntry) { |
- ++it; |
- } else if (result == kUpdateEntry) { |
- DCHECK_NOT_NULL(new_buffer); |
- Page* target_page = Page::FromAddress(new_buffer->address()); |
- // We need to lock the target page because we cannot guarantee |
- // exclusive access to new space pages. |
- if (target_page->InNewSpace()) target_page->mutex()->Lock(); |
- LocalArrayBufferTracker* tracker = target_page->local_tracker(); |
- if (tracker == nullptr) { |
- target_page->AllocateLocalTracker(); |
+ switch (callback(it->first, &new_buffer)) { |
+ case kKeepEntry: |
+ ++it; |
+ break; |
+ case kUpdateEntry: |
+ DCHECK_NOT_NULL(new_buffer); |
+ target_page = Page::FromAddress(new_buffer->address()); |
+ // We need to lock the target page because we cannot guarantee |
+ // exclusive access to new space pages. |
+ if (target_page->InNewSpace()) target_page->mutex()->Lock(); |
tracker = target_page->local_tracker(); |
- } |
- DCHECK_NOT_NULL(tracker); |
- tracker->Add(new_buffer, it->second); |
- if (target_page->InNewSpace()) target_page->mutex()->Unlock(); |
- it = array_buffers_.erase(it); |
- } else if (result == kRemoveEntry) { |
- const size_t len = it->second; |
- heap_->isolate()->array_buffer_allocator()->Free( |
- it->first->backing_store(), len); |
- freed_memory += len; |
- it = array_buffers_.erase(it); |
- } else { |
- UNREACHABLE(); |
+ if (tracker == nullptr) { |
+ target_page->AllocateLocalTracker(); |
+ tracker = target_page->local_tracker(); |
+ } |
+ DCHECK_NOT_NULL(tracker); |
+ len = it->second; |
+ tracker->Add(new_buffer, len); |
+ if (target_page->InNewSpace()) { |
+ target_page->mutex()->Unlock(); |
+ } else { |
+ promoted_memory += len; |
+ } |
+ it = array_buffers_.erase(it); |
+ break; |
+ case kRemoveEntry: |
+ len = it->second; |
+ heap_->isolate()->array_buffer_allocator()->Free( |
+ it->first->backing_store(), len); |
+ freed_memory += len; |
+ it = array_buffers_.erase(it); |
+ break; |
} |
} |
- if (freed_memory > 0) { |
- heap_->update_external_memory_concurrently_freed( |
- static_cast<intptr_t>(freed_memory)); |
- } |
+ return ProcessResult(freed_memory, promoted_memory); |
+} |
+ |
+void ArrayBufferTracker::AccountForConcurrentlyFreedMemory() { |
+ heap_->update_external_memory( |
+ static_cast<int64_t>(concurrently_freed_.Value())); |
+ concurrently_freed_.SetValue(0); |
} |
-void ArrayBufferTracker::FreeDeadInNewSpace(Heap* heap) { |
- DCHECK_EQ(heap->gc_state(), Heap::HeapState::SCAVENGE); |
- for (Page* page : NewSpacePageRange(heap->new_space()->FromSpaceStart(), |
- heap->new_space()->FromSpaceEnd())) { |
+void ArrayBufferTracker::FreeDeadInNewSpace() { |
+ DCHECK_EQ(heap_->gc_state(), Heap::HeapState::SCAVENGE); |
+ for (Page* page : NewSpacePageRange(heap_->new_space()->FromSpaceStart(), |
+ heap_->new_space()->FromSpaceEnd())) { |
bool empty = ProcessBuffers(page, kUpdateForwardedRemoveOthers); |
CHECK(empty); |
} |
- heap->account_external_memory_concurrently_freed(); |
+ AccountForConcurrentlyFreedMemory(); |
} |
void ArrayBufferTracker::FreeDead(Page* page) { |
@@ -91,7 +102,13 @@ void ArrayBufferTracker::FreeDead(Page* page) { |
LocalArrayBufferTracker* tracker = page->local_tracker(); |
if (tracker == nullptr) return; |
DCHECK(!page->SweepingDone()); |
- tracker->Free<LocalArrayBufferTracker::kFreeDead>(); |
+ LocalArrayBufferTracker::ProcessResult result = |
+ tracker->Free<LocalArrayBufferTracker::kFreeDead>(); |
+ if (page->InNewSpace()) { |
+ retained_from_new_space_.Decrement(result.freed); |
+ } else { |
+ retained_from_old_space_.Decrement(result.freed); |
+ } |
if (tracker->IsEmpty()) { |
page->ReleaseLocalTracker(); |
} |
@@ -100,7 +117,14 @@ void ArrayBufferTracker::FreeDead(Page* page) { |
void ArrayBufferTracker::FreeAll(Page* page) { |
LocalArrayBufferTracker* tracker = page->local_tracker(); |
if (tracker == nullptr) return; |
- tracker->Free<LocalArrayBufferTracker::kFreeAll>(); |
+ LocalArrayBufferTracker::ProcessResult result = |
+ tracker->Free<LocalArrayBufferTracker::kFreeAll>(); |
+ concurrently_freed_.Increment(result.freed); |
+ if (page->InNewSpace()) { |
+ retained_from_new_space_.Decrement(result.freed); |
+ } else { |
+ retained_from_old_space_.Decrement(result.freed); |
+ } |
if (tracker->IsEmpty()) { |
page->ReleaseLocalTracker(); |
} |
@@ -111,7 +135,7 @@ bool ArrayBufferTracker::ProcessBuffers(Page* page, ProcessingMode mode) { |
if (tracker == nullptr) return true; |
DCHECK(page->SweepingDone()); |
- tracker->Process( |
+ LocalArrayBufferTracker::ProcessResult result = tracker->Process( |
[mode](JSArrayBuffer* old_buffer, JSArrayBuffer** new_buffer) { |
MapWord map_word = old_buffer->map_word(); |
if (map_word.IsForwardingAddress()) { |
@@ -122,6 +146,13 @@ bool ArrayBufferTracker::ProcessBuffers(Page* page, ProcessingMode mode) { |
? LocalArrayBufferTracker::kKeepEntry |
: LocalArrayBufferTracker::kRemoveEntry; |
}); |
+ concurrently_freed_.Increment(result.freed); |
+ if (page->InNewSpace()) { |
+ retained_from_new_space_.Decrement(result.freed + result.promoted); |
+ } else { |
+ retained_from_old_space_.Decrement(result.freed); |
+ } |
+ retained_from_old_space_.Increment(result.promoted); |
return tracker->IsEmpty(); |
} |