Store buffer is used for writes that are coming from the mutator. Writes coming from the GC are directly added to the remembered set.
BUG=chromium:648568 Review-Url: https://codereview.chromium.org/2528563003 Cr-Commit-Position: refs/heads/master@{#41263}
This commit is contained in:
parent
f447aeac4d
commit
c63c34e12e
@ -502,9 +502,7 @@ void Heap::RecordWrite(Object* object, int offset, Object* o) {
|
||||
if (!InNewSpace(o) || !object->IsHeapObject() || InNewSpace(object)) {
|
||||
return;
|
||||
}
|
||||
RememberedSet<OLD_TO_NEW>::Insert(
|
||||
Page::FromAddress(reinterpret_cast<Address>(object)),
|
||||
HeapObject::cast(object)->address() + offset);
|
||||
store_buffer()->InsertEntry(HeapObject::cast(object)->address() + offset);
|
||||
}
|
||||
|
||||
void Heap::RecordWriteIntoCode(Code* host, RelocInfo* rinfo, Object* value) {
|
||||
@ -515,11 +513,9 @@ void Heap::RecordWriteIntoCode(Code* host, RelocInfo* rinfo, Object* value) {
|
||||
|
||||
void Heap::RecordFixedArrayElements(FixedArray* array, int offset, int length) {
|
||||
if (InNewSpace(array)) return;
|
||||
Page* page = Page::FromAddress(reinterpret_cast<Address>(array));
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (!InNewSpace(array->get(offset + i))) continue;
|
||||
RememberedSet<OLD_TO_NEW>::Insert(
|
||||
page,
|
||||
store_buffer()->InsertEntry(
|
||||
reinterpret_cast<Address>(array->RawFieldOfElementAt(offset + i)));
|
||||
}
|
||||
}
|
||||
|
@ -5885,8 +5885,7 @@ void Heap::ClearRecordedSlot(HeapObject* object, Object** slot) {
|
||||
Address slot_addr = reinterpret_cast<Address>(slot);
|
||||
Page* page = Page::FromAddress(slot_addr);
|
||||
DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
|
||||
store_buffer()->MoveAllEntriesToRememberedSet();
|
||||
RememberedSet<OLD_TO_NEW>::Remove(page, slot_addr);
|
||||
store_buffer()->DeleteEntry(slot_addr);
|
||||
RememberedSet<OLD_TO_OLD>::Remove(page, slot_addr);
|
||||
}
|
||||
}
|
||||
@ -5895,9 +5894,7 @@ void Heap::ClearRecordedSlotRange(Address start, Address end) {
|
||||
Page* page = Page::FromAddress(start);
|
||||
if (!page->InNewSpace()) {
|
||||
DCHECK_EQ(page->owner()->identity(), OLD_SPACE);
|
||||
store_buffer()->MoveAllEntriesToRememberedSet();
|
||||
RememberedSet<OLD_TO_NEW>::RemoveRange(page, start, end,
|
||||
SlotSet::PREFREE_EMPTY_BUCKETS);
|
||||
store_buffer()->DeleteEntry(start, end);
|
||||
RememberedSet<OLD_TO_OLD>::RemoveRange(page, start, end,
|
||||
SlotSet::FREE_EMPTY_BUCKETS);
|
||||
}
|
||||
|
@ -138,6 +138,10 @@ void StoreBuffer::ConcurrentlyProcessStoreBuffer() {
|
||||
}
|
||||
|
||||
void StoreBuffer::DeleteEntry(Address start, Address end) {
|
||||
// Deletions coming from the GC are directly deleted from the remembered
|
||||
// set. Deletions coming from the runtime are added to the store buffer
|
||||
// to allow concurrent processing.
|
||||
if (heap_->gc_state() == Heap::NOT_IN_GC) {
|
||||
if (top_ + sizeof(Address) * 2 > limit_[current_]) {
|
||||
StoreBufferOverflow(heap_->isolate());
|
||||
}
|
||||
@ -145,7 +149,17 @@ void StoreBuffer::DeleteEntry(Address start, Address end) {
|
||||
top_++;
|
||||
*top_ = end;
|
||||
top_++;
|
||||
} else {
|
||||
// In GC the store buffer has to be empty at any time.
|
||||
DCHECK(Empty());
|
||||
Page* page = Page::FromAddress(start);
|
||||
if (end) {
|
||||
RememberedSet<OLD_TO_NEW>::RemoveRange(page, start, end,
|
||||
SlotSet::PREFREE_EMPTY_BUCKETS);
|
||||
} else {
|
||||
RememberedSet<OLD_TO_NEW>::Remove(page, start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/cancelable-task.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/heap/remembered-set.h"
|
||||
#include "src/heap/slot-set.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -28,7 +29,7 @@ class StoreBuffer {
|
||||
static const int kStoreBuffers = 2;
|
||||
static const intptr_t kDeletionTag = 1;
|
||||
|
||||
static void StoreBufferOverflow(Isolate* isolate);
|
||||
V8_EXPORT_PRIVATE static void StoreBufferOverflow(Isolate* isolate);
|
||||
|
||||
explicit StoreBuffer(Heap* heap);
|
||||
void SetUp();
|
||||
@ -64,6 +65,23 @@ class StoreBuffer {
|
||||
// the more efficient Remove method will be called in this case.
|
||||
void DeleteEntry(Address start, Address end = nullptr);
|
||||
|
||||
void InsertEntry(Address slot) {
|
||||
// Insertions coming from the GC are directly inserted into the remembered
|
||||
// set. Insertions coming from the runtime are added to the store buffer to
|
||||
// allow concurrent processing.
|
||||
if (heap_->gc_state() == Heap::NOT_IN_GC) {
|
||||
if (top_ + sizeof(Address) > limit_[current_]) {
|
||||
StoreBufferOverflow(heap_->isolate());
|
||||
}
|
||||
*top_ = slot;
|
||||
top_++;
|
||||
} else {
|
||||
// In GC the store buffer has to be empty at any time.
|
||||
DCHECK(Empty());
|
||||
RememberedSet<OLD_TO_NEW>::Insert(Page::FromAddress(slot), slot);
|
||||
}
|
||||
}
|
||||
|
||||
// Used by the concurrent processing thread to transfer entries from the
|
||||
// store buffer to the remembered set.
|
||||
void ConcurrentlyProcessStoreBuffer();
|
||||
|
Loading…
Reference in New Issue
Block a user