Keep track of ArrayBuffers based on collector type, not space

Since Mark/Compact also collects garbage in the new space, we can't just
free old space ArrayBuffers during MC - otherwise we run the risk of
never freeing new array buffers

BUG=v8:4201
R=hpayer@chromium.org
LOG=n

Review URL: https://codereview.chromium.org/1199913002

Cr-Commit-Position: refs/heads/master@{#29190}
This commit is contained in:
jochen 2015-06-22 06:24:40 -07:00 committed by Commit bot
parent 2197ef2aaf
commit 839170e785
3 changed files with 65 additions and 33 deletions

View File

@ -1863,9 +1863,11 @@ void Heap::TearDownArrayBuffersHelper(
void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data,
size_t length) {
if (!data) return;
RegisterNewArrayBufferHelper(
in_new_space ? live_new_array_buffers_ : live_array_buffers_, data,
length);
RegisterNewArrayBufferHelper(live_array_buffers_, data, length);
if (in_new_space) {
RegisterNewArrayBufferHelper(live_array_buffers_for_scavenge_, data,
length);
}
reinterpret_cast<v8::Isolate*>(isolate_)
->AdjustAmountOfExternalAllocatedMemory(length);
}
@ -1873,29 +1875,46 @@ void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data,
void Heap::UnregisterArrayBuffer(bool in_new_space, void* data) {
if (!data) return;
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_,
UnregisterArrayBufferHelper(live_array_buffers_,
not_yet_discovered_array_buffers_, data);
if (in_new_space) {
UnregisterArrayBufferHelper(live_array_buffers_for_scavenge_,
not_yet_discovered_array_buffers_for_scavenge_,
data);
}
}
void Heap::RegisterLiveArrayBuffer(bool from_scavenge, void* data) {
// ArrayBuffer might be in the middle of being constructed.
if (data == undefined_value()) return;
RegisterLiveArrayBufferHelper(
from_scavenge ? not_yet_discovered_array_buffers_for_scavenge_
: not_yet_discovered_array_buffers_,
data);
}
void Heap::RegisterLiveArrayBuffer(bool in_new_space, void* data) {
// ArrayBuffer might be in the middle of being constructed.
if (data == undefined_value()) return;
RegisterLiveArrayBufferHelper(in_new_space
? not_yet_discovered_new_array_buffers_
: not_yet_discovered_array_buffers_,
data);
}
void Heap::FreeDeadArrayBuffers(bool in_new_space) {
void Heap::FreeDeadArrayBuffers(bool from_scavenge) {
if (from_scavenge) {
for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) {
not_yet_discovered_array_buffers_.erase(buffer.first);
live_array_buffers_.erase(buffer.first);
}
} else {
for (auto& buffer : not_yet_discovered_array_buffers_) {
// Scavenge can't happend during evacuation, so we only need to update
// live_array_buffers_for_scavenge_.
// not_yet_discovered_array_buffers_for_scanvenge_ will be reset before
// the next scavenge run in PrepareArrayBufferDiscoveryInNewSpace.
live_array_buffers_for_scavenge_.erase(buffer.first);
}
}
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_);
isolate_,
from_scavenge ? live_array_buffers_for_scavenge_ : live_array_buffers_,
from_scavenge ? not_yet_discovered_array_buffers_for_scavenge_
: not_yet_discovered_array_buffers_);
if (freed_memory) {
reinterpret_cast<v8::Isolate*>(isolate_)
->AdjustAmountOfExternalAllocatedMemory(
@ -1907,13 +1926,12 @@ void Heap::FreeDeadArrayBuffers(bool in_new_space) {
void Heap::TearDownArrayBuffers() {
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_;
not_yet_discovered_array_buffers_for_scavenge_ =
live_array_buffers_for_scavenge_;
}
@ -1924,10 +1942,10 @@ void Heap::PromoteArrayBuffer(Object* obj) {
if (!data) return;
// ArrayBuffer might be in the middle of being constructed.
if (data == undefined_value()) 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);
DCHECK(live_array_buffers_for_scavenge_.count(data) > 0);
DCHECK(live_array_buffers_.count(data) > 0);
live_array_buffers_for_scavenge_.erase(data);
not_yet_discovered_array_buffers_for_scavenge_.erase(data);
}

View File

@ -1599,11 +1599,11 @@ class Heap {
void UnregisterArrayBuffer(bool in_new_space, void* data);
// A live ArrayBuffer was discovered during marking/scavenge.
void RegisterLiveArrayBuffer(bool in_new_space, void* data);
void RegisterLiveArrayBuffer(bool from_scavenge, void* data);
// Frees all backing store pointers that weren't discovered in the previous
// marking or scavenge phase.
void FreeDeadArrayBuffers(bool in_new_space);
void FreeDeadArrayBuffers(bool from_scavenge);
// Prepare for a new scavenge phase. A new marking phase is implicitly
// prepared by finishing the previous one.
@ -2373,10 +2373,24 @@ class Heap {
bool concurrent_sweeping_enabled_;
// |live_array_buffers_| maps externally allocated memory used as backing
// store for ArrayBuffers to the length of the respective memory blocks.
//
// At the beginning of mark/compact, |not_yet_discovered_array_buffers_| is
// a copy of |live_array_buffers_| and we remove pointers as we discover live
// ArrayBuffer objects during marking. At the end of mark/compact, the
// remaining memory blocks can be freed.
std::map<void*, size_t> live_array_buffers_;
std::map<void*, size_t> live_new_array_buffers_;
std::map<void*, size_t> not_yet_discovered_array_buffers_;
std::map<void*, size_t> not_yet_discovered_new_array_buffers_;
// To be able to free memory held by ArrayBuffers during scavenge as well, we
// have a separate list of allocated memory held by ArrayBuffers in new space.
//
// Since mark/compact also evacuates the new space, all pointers in the
// |live_array_buffers_for_scavenge_| list are also in the
// |live_array_buffers_| list.
std::map<void*, size_t> live_array_buffers_for_scavenge_;
std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_;
struct StrongRootsList;
StrongRootsList* strong_roots_list_;

View File

@ -508,7 +508,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(heap->InNewSpace(object),
heap->RegisterLiveArrayBuffer(false,
JSArrayBuffer::cast(object)->backing_store());
}
}