Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index bfd1fb50958ee8288422606051700c4324438775..62719af8a7b83486526eb4f0af81f0e940639282 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -1561,6 +1561,8 @@ void Heap::Scavenge() { |
incremental_marking()->PrepareForScavenge(); |
+ PrepareArrayBufferDiscoveryInNewSpace(); |
+ |
// Flip the semispaces. After flipping, to space is empty, from space has |
// live objects. |
new_space_.Flip(); |
@@ -1642,6 +1644,8 @@ void Heap::Scavenge() { |
new_space_.LowerInlineAllocationLimit( |
new_space_.inline_allocation_limit_step()); |
+ FreeDeadArrayBuffers(true); |
+ |
// Update how much has survived scavenge. |
IncrementYoungSurvivorsCounter(static_cast<int>( |
(PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); |
@@ -1735,46 +1739,121 @@ void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { |
} |
-void Heap::RegisterNewArrayBuffer(void* data, size_t length) { |
+namespace { |
+ |
+void RegisterNewArrayBufferHelper(std::map<void*, size_t>& live_buffers, |
+ void* data, size_t length) { |
+ live_buffers[data] = length; |
+} |
+ |
+ |
+void UnregisterArrayBufferHelper( |
+ std::map<void*, size_t>& live_buffers, |
+ std::map<void*, size_t>& not_yet_discovered_buffers, void* data) { |
+ DCHECK(live_buffers.count(data) > 0); |
+ live_buffers.erase(data); |
+ not_yet_discovered_buffers.erase(data); |
+} |
+ |
+ |
+void RegisterLiveArrayBufferHelper( |
+ std::map<void*, size_t>& not_yet_discovered_buffers, void* data) { |
+ not_yet_discovered_buffers.erase(data); |
+} |
+ |
+ |
+size_t FreeDeadArrayBuffersHelper( |
+ Isolate* isolate, std::map<void*, size_t>& live_buffers, |
+ std::map<void*, size_t>& not_yet_discovered_buffers) { |
+ size_t freed_memory = 0; |
+ for (auto buffer = not_yet_discovered_buffers.begin(); |
+ buffer != not_yet_discovered_buffers.end(); ++buffer) { |
+ isolate->array_buffer_allocator()->Free(buffer->first, buffer->second); |
+ freed_memory += buffer->second; |
+ live_buffers.erase(buffer->first); |
+ } |
+ not_yet_discovered_buffers = live_buffers; |
+ return freed_memory; |
+} |
+ |
+ |
+void TearDownArrayBuffersHelper( |
+ Isolate* isolate, std::map<void*, size_t>& live_buffers, |
+ std::map<void*, size_t>& not_yet_discovered_buffers) { |
+ for (auto buffer = live_buffers.begin(); buffer != live_buffers.end(); |
+ ++buffer) { |
+ isolate->array_buffer_allocator()->Free(buffer->first, buffer->second); |
+ } |
+ live_buffers.clear(); |
+ not_yet_discovered_buffers.clear(); |
+} |
+ |
+} // namespace |
+ |
+ |
+void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data, |
+ size_t length) { |
if (!data) return; |
- live_array_buffers_[data] = length; |
+ RegisterNewArrayBufferHelper( |
+ in_new_space ? live_new_array_buffers_ : live_array_buffers_, data, |
+ length); |
reinterpret_cast<v8::Isolate*>(isolate_) |
->AdjustAmountOfExternalAllocatedMemory(length); |
} |
-void Heap::UnregisterArrayBuffer(void* data) { |
+void Heap::UnregisterArrayBuffer(bool in_new_space, void* data) { |
if (!data) return; |
- DCHECK(live_array_buffers_.count(data) > 0); |
- live_array_buffers_.erase(data); |
- not_yet_discovered_array_buffers_.erase(data); |
+ UnregisterArrayBufferHelper( |
+ in_new_space ? live_new_array_buffers_ : live_array_buffers_, |
+ in_new_space ? not_yet_discovered_new_array_buffers_ |
+ : not_yet_discovered_array_buffers_, |
+ data); |
} |
-void Heap::RegisterLiveArrayBuffer(void* data) { |
- not_yet_discovered_array_buffers_.erase(data); |
+void Heap::RegisterLiveArrayBuffer(bool in_new_space, void* data) { |
+ RegisterLiveArrayBufferHelper(in_new_space |
+ ? not_yet_discovered_new_array_buffers_ |
+ : not_yet_discovered_array_buffers_, |
+ data); |
} |
-void Heap::FreeDeadArrayBuffers() { |
- for (auto buffer = not_yet_discovered_array_buffers_.begin(); |
- buffer != not_yet_discovered_array_buffers_.end(); ++buffer) { |
- isolate_->array_buffer_allocator()->Free(buffer->first, buffer->second); |
- // Don't use the API method here since this could trigger another GC. |
- amount_of_external_allocated_memory_ -= buffer->second; |
- live_array_buffers_.erase(buffer->first); |
+void Heap::FreeDeadArrayBuffers(bool in_new_space) { |
+ size_t freed_memory = FreeDeadArrayBuffersHelper( |
+ isolate_, in_new_space ? live_new_array_buffers_ : live_array_buffers_, |
+ in_new_space ? not_yet_discovered_new_array_buffers_ |
+ : not_yet_discovered_array_buffers_); |
+ if (freed_memory) { |
+ reinterpret_cast<v8::Isolate*>(isolate_) |
+ ->AdjustAmountOfExternalAllocatedMemory( |
+ -static_cast<int64_t>(freed_memory)); |
} |
- not_yet_discovered_array_buffers_ = live_array_buffers_; |
} |
void Heap::TearDownArrayBuffers() { |
- for (auto buffer = live_array_buffers_.begin(); |
- buffer != live_array_buffers_.end(); ++buffer) { |
- isolate_->array_buffer_allocator()->Free(buffer->first, buffer->second); |
- } |
- live_array_buffers_.clear(); |
- not_yet_discovered_array_buffers_.clear(); |
+ TearDownArrayBuffersHelper(isolate_, live_array_buffers_, |
+ not_yet_discovered_array_buffers_); |
+ TearDownArrayBuffersHelper(isolate_, live_new_array_buffers_, |
+ not_yet_discovered_new_array_buffers_); |
+} |
+ |
+ |
+void Heap::PrepareArrayBufferDiscoveryInNewSpace() { |
+ not_yet_discovered_new_array_buffers_ = live_new_array_buffers_; |
+} |
+ |
+ |
+void Heap::PromoteArrayBuffer(JSArrayBuffer* buffer) { |
+ if (buffer->is_external()) return; |
+ void* data = buffer->backing_store(); |
+ if (!data) return; |
+ DCHECK(live_new_array_buffers_.count(data) > 0); |
+ live_array_buffers_[data] = live_new_array_buffers_[data]; |
+ live_new_array_buffers_.erase(data); |
+ not_yet_discovered_new_array_buffers_.erase(data); |
} |
@@ -2173,6 +2252,9 @@ class ScavengingVisitor : public StaticVisitorBase { |
heap->promotion_queue()->insert(target, object_size); |
} |
} |
+ if (map->instance_type() == JS_ARRAY_BUFFER_TYPE) { |
+ heap->PromoteArrayBuffer(JSArrayBuffer::cast(target)); |
Hannes Payer (out of office)
2015/05/12 06:33:28
What about moving this logic into the promotion qu
|
+ } |
heap->IncrementPromotedObjectsSize(object_size); |
return true; |
} |