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() {
});
RememberedSet<OLD_TO_NEW>::IterateTyped(
this, [this](SlotType type, Address addr) {
this, [this](SlotType type, Address host_addr, Address addr) {
return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate(), type, addr, [this](Object** addr) {
// We expect that objects referenced by code are long living.
......
......@@ -1553,7 +1553,8 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
Address code_entry = Memory::Address_at(code_entry_slot);
if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
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,
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 {
if (direction == OLD_TO_OLD) {
Isolate* isolate = heap->isolate();
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,
UpdateSlot);
});
} else {
Isolate* isolate = heap->isolate();
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(
isolate, type, slot, [heap](Object** slot) {
return CheckAndUpdateOldToNewSlot(
......@@ -3967,7 +3970,8 @@ void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* host, Address slot,
!ShouldSkipEvacuationSlotRecording(host)) {
// TODO(ulan): remove this check after investigating crbug.com/414964.
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 {
// Given a page and a typed slot in that page, this function adds the slot
// 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);
if (slot_set == nullptr) {
AllocateTypedSlotSet(page);
slot_set = GetTypedSlotSet(page);
}
if (host_addr == nullptr) {
host_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));
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
......@@ -116,7 +123,8 @@ class RememberedSet {
static void RemoveRangeTyped(Page* page, Address start, Address end) {
TypedSlotSet* slots = GetTypedSlotSet(page);
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;
});
}
......@@ -142,7 +150,6 @@ class RememberedSet {
int new_count = slots->Iterate(callback);
if (new_count == 0) {
ReleaseTypedSlotSet(chunk);
chunk->ReleaseTypedOldToOldSlots();
}
}
}
......
......@@ -233,7 +233,30 @@ enum SlotType {
// typed slots contain V8 internal pointers that are not directly exposed to JS.
class TypedSlotSet {
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;
explicit TypedSlotSet(Address page_start) : page_start_(page_start) {
......@@ -250,8 +273,8 @@ class TypedSlotSet {
}
// The slot offset specifies a slot at address page_start_ + offset.
void Insert(SlotType type, int offset) {
TypedSlot slot = ToTypedSlot(type, offset);
void Insert(SlotType type, uint32_t host_offset, uint32_t offset) {
TypedSlot slot(type, host_offset, offset);
if (!chunk_->AddSlot(slot)) {
chunk_ = new Chunk(chunk_, NextCapacity(chunk_->capacity));
bool added = chunk_->AddSlot(slot);
......@@ -272,7 +295,7 @@ class TypedSlotSet {
template <typename Callback>
int Iterate(Callback callback) {
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_;
int new_count = 0;
while (chunk != nullptr) {
......@@ -281,9 +304,10 @@ class TypedSlotSet {
for (int i = 0; i < count; i++) {
TypedSlot slot = buffer[i];
if (slot != kRemovedSlot) {
SlotType type = TypeField::decode(slot);
Address addr = page_start_ + OffsetField::decode(slot);
if (callback(type, addr) == KEEP_SLOT) {
SlotType type = slot.type();
Address addr = page_start_ + slot.offset();
Address host_addr = page_start_ + slot.host_offset();
if (callback(type, host_addr, addr) == KEEP_SLOT) {
new_count++;
} else {
buffer[i] = kRemovedSlot;
......@@ -303,10 +327,6 @@ class TypedSlotSet {
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 TypeField : public BitField<SlotType, 29, 3> {};
......
......@@ -142,23 +142,29 @@ TEST(SlotSet, RemoveRange) {
TEST(TypedSlotSet, Iterate) {
TypedSlotSet set(0);
const int kDelta = 10000001;
const int kHostDelta = 50001;
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);
set.Insert(type, i);
set.Insert(type, j, i);
++added;
}
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 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(0, i % kDelta);
EXPECT_EQ(0, j % kHostDelta);
++iterated;
return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT;
});
EXPECT_EQ(added, iterated);
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));
EXPECT_EQ(0, i % 2);
++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