[heap] Add VisitEphemeron method

This modifies the ObjectVisitor to provide a dedicated VisitEphemeron
method invoked when visiting a EphemeronHashTable. This is pre-work
for further changes to how ephemerons are handled during scavenging.

Bug: v8:8557
Change-Id: Ia423b10667ec222cbe5f44d8a931ea33314625f4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1508673
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60119}
This commit is contained in:
Sigurd Schneider 2019-03-08 11:25:55 +01:00 committed by Commit Bot
parent d6465298b6
commit 7a6e829b72
7 changed files with 61 additions and 10 deletions

View File

@ -508,7 +508,7 @@ class ConcurrentMarkingVisitor final
// Implements ephemeron semantics: Marks value if key is already reachable.
// Returns true if value was actually marked.
bool VisitEphemeron(HeapObject key, HeapObject value) {
bool ProcessEphemeron(HeapObject key, HeapObject value) {
if (marking_state_.IsBlackOrGrey(key)) {
if (marking_state_.WhiteToGrey(value)) {
shared_.Push(value);
@ -776,7 +776,7 @@ void ConcurrentMarking::Run(int task_id, TaskState* task_state) {
Ephemeron ephemeron;
while (weak_objects_->current_ephemerons.Pop(task_id, &ephemeron)) {
if (visitor.VisitEphemeron(ephemeron.key, ephemeron.value)) {
if (visitor.ProcessEphemeron(ephemeron.key, ephemeron.value)) {
ephemeron_marked = true;
}
}
@ -821,7 +821,7 @@ void ConcurrentMarking::Run(int task_id, TaskState* task_state) {
Ephemeron ephemeron;
while (weak_objects_->discovered_ephemerons.Pop(task_id, &ephemeron)) {
if (visitor.VisitEphemeron(ephemeron.key, ephemeron.value)) {
if (visitor.ProcessEphemeron(ephemeron.key, ephemeron.value)) {
ephemeron_marked = true;
}
}

View File

@ -1547,7 +1547,7 @@ bool MarkCompactCollector::ProcessEphemerons() {
// Drain current_ephemerons and push ephemerons where key and value are still
// unreachable into next_ephemerons.
while (weak_objects_.current_ephemerons.Pop(kMainThread, &ephemeron)) {
if (VisitEphemeron(ephemeron.key, ephemeron.value)) {
if (ProcessEphemeron(ephemeron.key, ephemeron.value)) {
ephemeron_marked = true;
}
}
@ -1560,7 +1560,7 @@ bool MarkCompactCollector::ProcessEphemerons() {
// before) and push ephemerons where key and value are still unreachable into
// next_ephemerons.
while (weak_objects_.discovered_ephemerons.Pop(kMainThread, &ephemeron)) {
if (VisitEphemeron(ephemeron.key, ephemeron.value)) {
if (ProcessEphemeron(ephemeron.key, ephemeron.value)) {
ephemeron_marked = true;
}
}
@ -1583,7 +1583,7 @@ void MarkCompactCollector::ProcessEphemeronsLinear() {
weak_objects_.current_ephemerons.Swap(weak_objects_.next_ephemerons);
while (weak_objects_.current_ephemerons.Pop(kMainThread, &ephemeron)) {
VisitEphemeron(ephemeron.key, ephemeron.value);
ProcessEphemeron(ephemeron.key, ephemeron.value);
if (non_atomic_marking_state()->IsWhite(ephemeron.value)) {
key_to_values.insert(std::make_pair(ephemeron.key, ephemeron.value));
@ -1610,7 +1610,7 @@ void MarkCompactCollector::ProcessEphemeronsLinear() {
}
while (weak_objects_.discovered_ephemerons.Pop(kMainThread, &ephemeron)) {
VisitEphemeron(ephemeron.key, ephemeron.value);
ProcessEphemeron(ephemeron.key, ephemeron.value);
if (non_atomic_marking_state()->IsWhite(ephemeron.value)) {
key_to_values.insert(std::make_pair(ephemeron.key, ephemeron.value));
@ -1696,7 +1696,7 @@ void MarkCompactCollector::ProcessMarkingWorklistInternal() {
}
}
bool MarkCompactCollector::VisitEphemeron(HeapObject key, HeapObject value) {
bool MarkCompactCollector::ProcessEphemeron(HeapObject key, HeapObject value) {
if (marking_state()->IsBlackOrGrey(key)) {
if (marking_state()->WhiteToGrey(value)) {
marking_worklist()->Push(value);

View File

@ -765,7 +765,7 @@ class MarkCompactCollector final : public MarkCompactCollectorBase {
// Implements ephemeron semantics: Marks value if key is already reachable.
// Returns true if value was actually marked.
bool VisitEphemeron(HeapObject key, HeapObject value);
bool ProcessEphemeron(HeapObject key, HeapObject value);
// Marks ephemerons and drains marking worklist iteratively
// until a fixpoint is reached.

View File

@ -149,6 +149,16 @@ DISABLE_CFI_PERF void BodyDescriptorBase::IterateCustomWeakPointers(
HeapObject::RawField(obj, end_offset));
}
template <typename ObjectVisitor>
DISABLE_CFI_PERF void BodyDescriptorBase::IterateEphemeron(HeapObject obj,
int index,
int key_offset,
int value_offset,
ObjectVisitor* v) {
v->VisitEphemeron(obj, index, HeapObject::RawField(obj, key_offset),
HeapObject::RawField(obj, value_offset));
}
template <typename ObjectVisitor>
void BodyDescriptorBase::IterateCustomWeakPointer(HeapObject obj, int offset,
ObjectVisitor* v) {
@ -831,10 +841,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case NUMBER_DICTIONARY_TYPE:
case SIMPLE_NUMBER_DICTIONARY_TYPE:
case STRING_TABLE_TYPE:
case EPHEMERON_HASH_TABLE_TYPE:
case SCOPE_INFO_TYPE:
case SCRIPT_CONTEXT_TABLE_TYPE:
return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
case EPHEMERON_HASH_TABLE_TYPE:
return Op::template apply<EphemeronHashTable::BodyDescriptor>(p1, p2, p3,
p4);
case AWAIT_CONTEXT_TYPE:
case BLOCK_CONTEXT_TYPE:
case CATCH_CONTEXT_TYPE:
@ -1048,6 +1060,34 @@ void HeapObject::IterateBodyFast(Map map, int object_size, ObjectVisitor* v) {
BodyDescriptorApply<CallIterateBody, void>(map->instance_type(), map, *this,
object_size, v);
}
class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return (offset >= EphemeronHashTable::kHeaderSize);
}
template <typename ObjectVisitor>
static inline void IterateBody(Map map, HeapObject obj, int object_size,
ObjectVisitor* v) {
int entries_start = EphemeronHashTable::kHeaderSize +
EphemeronHashTable::kElementsStartIndex * kTaggedSize;
IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v);
EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj);
int entries = table.Capacity();
for (int i = 0; i < entries; ++i) {
const int key_index = EphemeronHashTable::EntryToIndex(i);
const int value_index = EphemeronHashTable::EntryToValueIndex(i);
IterateEphemeron(obj, i, OffsetOfElementAt(key_index),
OffsetOfElementAt(value_index), v);
}
}
static inline int SizeOf(Map map, HeapObject object) {
return object->SizeFromMap(map);
}
};
} // namespace internal
} // namespace v8

View File

@ -46,6 +46,10 @@ class BodyDescriptorBase {
static inline void IterateCustomWeakPointer(HeapObject obj, int offset,
ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateEphemeron(HeapObject obj, int index, int key_offset,
int value_offset, ObjectVisitor* v);
template <typename ObjectVisitor>
static inline void IterateMaybeWeakPointers(HeapObject obj, int start_offset,
int end_offset, ObjectVisitor* v);

View File

@ -342,6 +342,7 @@ class EphemeronHashTable
public:
DECL_CAST(EphemeronHashTable)
DECL_PRINTER(EphemeronHashTable)
class BodyDescriptor;
protected:
friend class MarkCompactCollector;

View File

@ -119,6 +119,12 @@ class ObjectVisitor {
VisitCustomWeakPointers(host, p, p + 1);
}
virtual void VisitEphemeron(HeapObject host, int index, ObjectSlot key,
ObjectSlot value) {
VisitPointer(host, key);
VisitPointer(host, value);
}
// To allow lazy clearing of inline caches the visitor has
// a rich interface for iterating over Code objects ...