Commit ae521505 authored by ahaas's avatar ahaas Committed by Commit bot

[heap] Store the host address in the typed remembered set.

We need the host address in another CL to clear invalid slots.

R=ulan@chromium.org

Review-Url: https://codereview.chromium.org/2025833002
Cr-Commit-Position: refs/heads/master@{#36696}
parent dea0d747
...@@ -1675,7 +1675,7 @@ void Heap::Scavenge() { ...@@ -1675,7 +1675,7 @@ void Heap::Scavenge() {
}); });
RememberedSet<OLD_TO_NEW>::IterateTyped( RememberedSet<OLD_TO_NEW>::IterateTyped(
this, [this](SlotType type, Address addr) { this, [this](SlotType type, Address host_addr, Address addr) {
return UpdateTypedSlotHelper::UpdateTypedSlot( return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate(), type, addr, [this](Object** addr) { isolate(), type, addr, [this](Object** addr) {
// We expect that objects referenced by code are long living. // We expect that objects referenced by code are long living.
......
...@@ -1553,7 +1553,8 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor { ...@@ -1553,7 +1553,8 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
Address code_entry = Memory::Address_at(code_entry_slot); Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) { if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot), RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot),
CODE_ENTRY_SLOT, code_entry_slot); nullptr, CODE_ENTRY_SLOT,
code_entry_slot);
} }
} }
...@@ -2824,7 +2825,8 @@ void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo, ...@@ -2824,7 +2825,8 @@ void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo,
slot_type = OBJECT_SLOT; slot_type = OBJECT_SLOT;
} }
} }
RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr); RememberedSet<OLD_TO_OLD>::InsertTyped(
source_page, reinterpret_cast<Address>(host), slot_type, addr);
} }
} }
...@@ -3605,14 +3607,15 @@ class PointerUpdateJobTraits { ...@@ -3605,14 +3607,15 @@ class PointerUpdateJobTraits {
if (direction == OLD_TO_OLD) { if (direction == OLD_TO_OLD) {
Isolate* isolate = heap->isolate(); Isolate* isolate = heap->isolate();
RememberedSet<OLD_TO_OLD>::IterateTyped( RememberedSet<OLD_TO_OLD>::IterateTyped(
chunk, [isolate](SlotType type, Address slot) { chunk, [isolate](SlotType type, Address host_addr, Address slot) {
return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, type, slot, return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, type, slot,
UpdateSlot); UpdateSlot);
}); });
} else { } else {
Isolate* isolate = heap->isolate(); Isolate* isolate = heap->isolate();
RememberedSet<OLD_TO_NEW>::IterateTyped( RememberedSet<OLD_TO_NEW>::IterateTyped(
chunk, [isolate, heap](SlotType type, Address slot) { chunk,
[isolate, heap](SlotType type, Address host_addr, Address slot) {
return UpdateTypedSlotHelper::UpdateTypedSlot( return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate, type, slot, [heap](Object** slot) { isolate, type, slot, [heap](Object** slot) {
return CheckAndUpdateOldToNewSlot( return CheckAndUpdateOldToNewSlot(
...@@ -3967,7 +3970,8 @@ void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* host, Address slot, ...@@ -3967,7 +3970,8 @@ void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* host, Address slot,
!ShouldSkipEvacuationSlotRecording(host)) { !ShouldSkipEvacuationSlotRecording(host)) {
// TODO(ulan): remove this check after investigating crbug.com/414964. // TODO(ulan): remove this check after investigating crbug.com/414964.
CHECK(target->IsCode()); CHECK(target->IsCode());
RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, CODE_ENTRY_SLOT, slot); RememberedSet<OLD_TO_OLD>::InsertTyped(
source_page, reinterpret_cast<Address>(host), CODE_ENTRY_SLOT, slot);
} }
} }
......
...@@ -100,15 +100,22 @@ class RememberedSet { ...@@ -100,15 +100,22 @@ class RememberedSet {
// Given a page and a typed slot in that page, this function adds the slot // Given a page and a typed slot in that page, this function adds the slot
// to the remembered set. // to the remembered set.
static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) { static void InsertTyped(Page* page, Address host_addr, SlotType slot_type,
Address slot_addr) {
TypedSlotSet* slot_set = GetTypedSlotSet(page); TypedSlotSet* slot_set = GetTypedSlotSet(page);
if (slot_set == nullptr) { if (slot_set == nullptr) {
AllocateTypedSlotSet(page); AllocateTypedSlotSet(page);
slot_set = GetTypedSlotSet(page); slot_set = GetTypedSlotSet(page);
} }
if (host_addr == nullptr) {
host_addr = page->address();
}
uintptr_t offset = slot_addr - page->address(); uintptr_t offset = slot_addr - page->address();
uintptr_t host_offset = host_addr - page->address();
DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset)); DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset));
slot_set->Insert(slot_type, static_cast<uint32_t>(offset)); DCHECK_LT(host_offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset));
slot_set->Insert(slot_type, static_cast<uint32_t>(host_offset),
static_cast<uint32_t>(offset));
} }
// Given a page and a range of typed slots in that page, this function removes // Given a page and a range of typed slots in that page, this function removes
...@@ -116,7 +123,8 @@ class RememberedSet { ...@@ -116,7 +123,8 @@ class RememberedSet {
static void RemoveRangeTyped(Page* page, Address start, Address end) { static void RemoveRangeTyped(Page* page, Address start, Address end) {
TypedSlotSet* slots = GetTypedSlotSet(page); TypedSlotSet* slots = GetTypedSlotSet(page);
if (slots != nullptr) { if (slots != nullptr) {
slots->Iterate([start, end](SlotType slot_type, Address slot_addr) { slots->Iterate([start, end](SlotType slot_type, Address host_addr,
Address slot_addr) {
return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT; return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT;
}); });
} }
...@@ -142,7 +150,6 @@ class RememberedSet { ...@@ -142,7 +150,6 @@ class RememberedSet {
int new_count = slots->Iterate(callback); int new_count = slots->Iterate(callback);
if (new_count == 0) { if (new_count == 0) {
ReleaseTypedSlotSet(chunk); ReleaseTypedSlotSet(chunk);
chunk->ReleaseTypedOldToOldSlots();
} }
} }
} }
......
...@@ -233,7 +233,30 @@ enum SlotType { ...@@ -233,7 +233,30 @@ enum SlotType {
// typed slots contain V8 internal pointers that are not directly exposed to JS. // typed slots contain V8 internal pointers that are not directly exposed to JS.
class TypedSlotSet { class TypedSlotSet {
public: public:
typedef uint32_t TypedSlot; struct TypedSlot {
TypedSlot() : type_and_offset_(0), host_offset_(0) {}
TypedSlot(SlotType type, uint32_t host_offset, uint32_t offset)
: type_and_offset_(TypeField::encode(type) |
OffsetField::encode(offset)),
host_offset_(host_offset) {}
bool operator==(const TypedSlot other) {
return type_and_offset_ == other.type_and_offset_ &&
host_offset_ == other.host_offset_;
}
bool operator!=(const TypedSlot other) { return !(*this == other); }
SlotType type() { return TypeField::decode(type_and_offset_); }
uint32_t offset() { return OffsetField::decode(type_and_offset_); }
uint32_t host_offset() { return host_offset_; }
uint32_t type_and_offset_;
uint32_t host_offset_;
};
static const int kMaxOffset = 1 << 29; static const int kMaxOffset = 1 << 29;
explicit TypedSlotSet(Address page_start) : page_start_(page_start) { explicit TypedSlotSet(Address page_start) : page_start_(page_start) {
...@@ -250,8 +273,8 @@ class TypedSlotSet { ...@@ -250,8 +273,8 @@ class TypedSlotSet {
} }
// The slot offset specifies a slot at address page_start_ + offset. // The slot offset specifies a slot at address page_start_ + offset.
void Insert(SlotType type, int offset) { void Insert(SlotType type, uint32_t host_offset, uint32_t offset) {
TypedSlot slot = ToTypedSlot(type, offset); TypedSlot slot(type, host_offset, offset);
if (!chunk_->AddSlot(slot)) { if (!chunk_->AddSlot(slot)) {
chunk_ = new Chunk(chunk_, NextCapacity(chunk_->capacity)); chunk_ = new Chunk(chunk_, NextCapacity(chunk_->capacity));
bool added = chunk_->AddSlot(slot); bool added = chunk_->AddSlot(slot);
...@@ -272,7 +295,7 @@ class TypedSlotSet { ...@@ -272,7 +295,7 @@ class TypedSlotSet {
template <typename Callback> template <typename Callback>
int Iterate(Callback callback) { int Iterate(Callback callback) {
STATIC_ASSERT(NUMBER_OF_SLOT_TYPES < 8); STATIC_ASSERT(NUMBER_OF_SLOT_TYPES < 8);
const TypedSlot kRemovedSlot = TypeField::encode(NUMBER_OF_SLOT_TYPES); const TypedSlot kRemovedSlot(NUMBER_OF_SLOT_TYPES, 0, 0);
Chunk* chunk = chunk_; Chunk* chunk = chunk_;
int new_count = 0; int new_count = 0;
while (chunk != nullptr) { while (chunk != nullptr) {
...@@ -281,9 +304,10 @@ class TypedSlotSet { ...@@ -281,9 +304,10 @@ class TypedSlotSet {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
TypedSlot slot = buffer[i]; TypedSlot slot = buffer[i];
if (slot != kRemovedSlot) { if (slot != kRemovedSlot) {
SlotType type = TypeField::decode(slot); SlotType type = slot.type();
Address addr = page_start_ + OffsetField::decode(slot); Address addr = page_start_ + slot.offset();
if (callback(type, addr) == KEEP_SLOT) { Address host_addr = page_start_ + slot.host_offset();
if (callback(type, host_addr, addr) == KEEP_SLOT) {
new_count++; new_count++;
} else { } else {
buffer[i] = kRemovedSlot; buffer[i] = kRemovedSlot;
...@@ -303,10 +327,6 @@ class TypedSlotSet { ...@@ -303,10 +327,6 @@ class TypedSlotSet {
return Min(kMaxBufferSize, capacity * 2); return Min(kMaxBufferSize, capacity * 2);
} }
static TypedSlot ToTypedSlot(SlotType type, int offset) {
return TypeField::encode(type) | OffsetField::encode(offset);
}
class OffsetField : public BitField<int, 0, 29> {}; class OffsetField : public BitField<int, 0, 29> {};
class TypeField : public BitField<SlotType, 29, 3> {}; class TypeField : public BitField<SlotType, 29, 3> {};
......
...@@ -142,23 +142,29 @@ TEST(SlotSet, RemoveRange) { ...@@ -142,23 +142,29 @@ TEST(SlotSet, RemoveRange) {
TEST(TypedSlotSet, Iterate) { TEST(TypedSlotSet, Iterate) {
TypedSlotSet set(0); TypedSlotSet set(0);
const int kDelta = 10000001; const int kDelta = 10000001;
const int kHostDelta = 50001;
int added = 0; int added = 0;
for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset; i += kDelta) { uint32_t j = 0;
for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset;
i += kDelta, j += kHostDelta) {
SlotType type = static_cast<SlotType>(i % NUMBER_OF_SLOT_TYPES); SlotType type = static_cast<SlotType>(i % NUMBER_OF_SLOT_TYPES);
set.Insert(type, i); set.Insert(type, j, i);
++added; ++added;
} }
int iterated = 0; int iterated = 0;
set.Iterate([&iterated, kDelta](SlotType type, Address addr) { set.Iterate([&iterated, kDelta, kHostDelta](SlotType type, Address host_addr,
Address addr) {
uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)); uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr));
uint32_t j = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(host_addr));
EXPECT_EQ(i % NUMBER_OF_SLOT_TYPES, static_cast<uint32_t>(type)); EXPECT_EQ(i % NUMBER_OF_SLOT_TYPES, static_cast<uint32_t>(type));
EXPECT_EQ(0, i % kDelta); EXPECT_EQ(0, i % kDelta);
EXPECT_EQ(0, j % kHostDelta);
++iterated; ++iterated;
return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT; return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT;
}); });
EXPECT_EQ(added, iterated); EXPECT_EQ(added, iterated);
iterated = 0; iterated = 0;
set.Iterate([&iterated](SlotType type, Address addr) { set.Iterate([&iterated](SlotType type, Address host_addr, Address addr) {
uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)); uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr));
EXPECT_EQ(0, i % 2); EXPECT_EQ(0, i % 2);
++iterated; ++iterated;
......
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