[heap] Move first-level on Scavenger to instance-based visitor

Bug: 
Change-Id: I90e0c469d096cbffbecf01add6cfabbf3af275fa
Reviewed-on: https://chromium-review.googlesource.com/544307
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46158}
This commit is contained in:
Michael Lippautz 2017-06-22 21:41:52 +02:00 committed by Commit Bot
parent 1541f422a7
commit 07b1113252
6 changed files with 60 additions and 221 deletions

View File

@ -1992,6 +1992,7 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
}
Address Heap::DoScavenge(Address new_space_front) {
ScavengeVisitor scavenge_visitor(this);
do {
SemiSpace::AssertValidRange(new_space_front, new_space_->top());
// The addresses new_space_front and new_space_.top() define a
@ -2000,8 +2001,7 @@ Address Heap::DoScavenge(Address new_space_front) {
while (new_space_front != new_space_->top()) {
if (!Page::IsAlignedToPageSize(new_space_front)) {
HeapObject* object = HeapObject::FromAddress(new_space_front);
new_space_front +=
StaticScavengeVisitor::IterateBody(object->map(), object);
new_space_front += scavenge_visitor.Visit(object);
} else {
new_space_front = Page::FromAllocationAreaAddress(new_space_front)
->next_page()
@ -5684,7 +5684,6 @@ V8_DECLARE_ONCE(initialize_gc_once);
static void InitializeGCOnce() {
Scavenger::Initialize();
StaticScavengeVisitor::Initialize();
MarkCompactCollector::Initialize();
}

View File

@ -2236,7 +2236,7 @@ class YoungGenerationMarkingVisitor final
// Code is not in new space.
}
// Special cases for young generation. Also see StaticNewSpaceVisitor.
// Special cases for young generation.
int VisitJSFunction(Map* map, JSFunction* object) final {
if (!ShouldVisit(object)) return 0;

View File

@ -21,111 +21,6 @@ Callback VisitorDispatchTable<Callback>::GetVisitor(Map* map) {
return reinterpret_cast<Callback>(callbacks_[map->visitor_id()]);
}
template <typename StaticVisitor>
void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
table_.Register(
kVisitShortcutCandidate,
&FixedBodyVisitor<StaticVisitor, ConsString::BodyDescriptor, int>::Visit);
table_.Register(
kVisitConsString,
&FixedBodyVisitor<StaticVisitor, ConsString::BodyDescriptor, int>::Visit);
table_.Register(
kVisitThinString,
&FixedBodyVisitor<StaticVisitor, ThinString::BodyDescriptor, int>::Visit);
table_.Register(kVisitSlicedString,
&FixedBodyVisitor<StaticVisitor, SlicedString::BodyDescriptor,
int>::Visit);
table_.Register(
kVisitCell,
&FixedBodyVisitor<StaticVisitor, Cell::BodyDescriptor, int>::Visit);
table_.Register(
kVisitSymbol,
&FixedBodyVisitor<StaticVisitor, Symbol::BodyDescriptor, int>::Visit);
table_.Register(kVisitFixedArray,
&FlexibleBodyVisitor<StaticVisitor,
FixedArray::BodyDescriptor, int>::Visit);
table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray);
table_.Register(
kVisitFixedTypedArrayBase,
&FlexibleBodyVisitor<StaticVisitor, FixedTypedArrayBase::BodyDescriptor,
int>::Visit);
table_.Register(
kVisitFixedFloat64Array,
&FlexibleBodyVisitor<StaticVisitor, FixedTypedArrayBase::BodyDescriptor,
int>::Visit);
table_.Register(
kVisitNativeContext,
&FixedBodyVisitor<StaticVisitor, Context::BodyDescriptor, int>::Visit);
table_.Register(kVisitByteArray, &VisitByteArray);
table_.Register(
kVisitSharedFunctionInfo,
&FixedBodyVisitor<StaticVisitor, SharedFunctionInfo::BodyDescriptor,
int>::Visit);
table_.Register(kVisitSeqOneByteString, &VisitSeqOneByteString);
table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString);
// Don't visit code entry. We are using this visitor only during scavenges.
table_.Register(
kVisitJSFunction,
&FlexibleBodyVisitor<StaticVisitor, JSFunction::BodyDescriptorWeak,
int>::Visit);
table_.Register(
kVisitJSArrayBuffer,
&FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor,
int>::Visit);
table_.Register(kVisitFreeSpace, &VisitFreeSpace);
table_.Register(
kVisitJSWeakCollection,
&FlexibleBodyVisitor<StaticVisitor, JSWeakCollection::BodyDescriptor,
int>::Visit);
table_.Register(
kVisitSmallOrderedHashMap,
&FlexibleBodyVisitor<
StaticVisitor,
SmallOrderedHashTable<SmallOrderedHashMap>::BodyDescriptor,
int>::Visit);
table_.Register(
kVisitSmallOrderedHashSet,
&FlexibleBodyVisitor<
StaticVisitor,
SmallOrderedHashTable<SmallOrderedHashSet>::BodyDescriptor,
int>::Visit);
table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit);
table_.Register(kVisitDataObject, &DataObjectVisitor::Visit);
table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit);
table_.Register(kVisitJSObject, &JSObjectVisitor::Visit);
// Not using specialized Api object visitor for newspace.
table_.Register(kVisitJSApiObject, &JSObjectVisitor::Visit);
table_.Register(kVisitStruct, &StructVisitor::Visit);
table_.Register(kVisitBytecodeArray, &UnreachableVisitor);
table_.Register(kVisitSharedFunctionInfo, &UnreachableVisitor);
}
template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::Initialize() {
table_.Register(kVisitShortcutCandidate,
@ -646,6 +541,22 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
return static_cast<ResultType>(FreeSpace::cast(object)->size());
}
int NewSpaceVisitor::VisitJSFunction(Map* map, JSFunction* object) {
if (!ShouldVisit(object)) return 0;
int size = JSFunction::BodyDescriptorWeak::SizeOf(map, object);
VisitMapPointer(object, object->map_slot());
JSFunction::BodyDescriptorWeak::IterateBody(object, size, this);
return size;
}
int NewSpaceVisitor::VisitNativeContext(Map* map, Context* object) {
if (!ShouldVisit(object)) return 0;
int size = Context::BodyDescriptor::SizeOf(map, object);
VisitMapPointer(object, object->map_slot());
Context::BodyDescriptor::IterateBody(object, size, this);
return size;
}
} // namespace internal
} // namespace v8

View File

@ -142,105 +142,6 @@ class FixedBodyVisitor : public AllStatic {
}
};
// Base class for visitors used for a linear new space iteration.
// IterateBody returns size of visited object.
// Certain types of objects (i.e. Code objects) are not handled
// by dispatch table of this visitor because they cannot appear
// in the new space.
//
// This class is intended to be used in the following way:
//
// class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> {
// ...
// }
//
// This is an example of Curiously recurring template pattern
// (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
// We use CRTP to guarantee aggressive compile time optimizations (i.e.
// inlining and specialization of StaticVisitor::VisitPointers methods).
template <typename StaticVisitor>
class StaticNewSpaceVisitor : public StaticVisitorBase {
public:
static void Initialize();
INLINE(static int IterateBody(Map* map, HeapObject* obj)) {
return table_.GetVisitor(map)(map, obj);
}
INLINE(static void VisitPointers(Heap* heap, HeapObject* object,
Object** start, Object** end)) {
for (Object** p = start; p < end; p++) {
StaticVisitor::VisitPointer(heap, object, p);
}
}
inline static void VisitCodeEntry(Heap* heap, HeapObject* object,
Address entry_address) {
// Code is not in new space.
}
private:
inline static int UnreachableVisitor(Map* map, HeapObject* object) {
UNREACHABLE();
}
INLINE(static int VisitByteArray(Map* map, HeapObject* object)) {
return reinterpret_cast<ByteArray*>(object)->ByteArraySize();
}
INLINE(static int VisitFixedDoubleArray(Map* map, HeapObject* object)) {
int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
return FixedDoubleArray::SizeFor(length);
}
INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) {
return SeqOneByteString::cast(object)
->SeqOneByteStringSize(map->instance_type());
}
INLINE(static int VisitSeqTwoByteString(Map* map, HeapObject* object)) {
return SeqTwoByteString::cast(object)
->SeqTwoByteStringSize(map->instance_type());
}
INLINE(static int VisitFreeSpace(Map* map, HeapObject* object)) {
return FreeSpace::cast(object)->size();
}
class DataObjectVisitor {
public:
template <int object_size>
static inline int VisitSpecialized(Map* map, HeapObject* object) {
return object_size;
}
INLINE(static int Visit(Map* map, HeapObject* object)) {
return map->instance_size();
}
};
typedef FlexibleBodyVisitor<StaticVisitor, StructBodyDescriptor, int>
StructVisitor;
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, int>
JSObjectVisitor;
// Visitor for JSObjects without unboxed double fields.
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::FastBodyDescriptor, int>
JSObjectFastVisitor;
typedef int (*Callback)(Map* map, HeapObject* object);
static VisitorDispatchTable<Callback> table_;
};
template <typename StaticVisitor>
VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback>
StaticNewSpaceVisitor<StaticVisitor>::table_;
// Base class for visitors used to transitively mark the entire heap.
// IterateBody returns nothing.
// Certain types of objects might not be handled by this base class and
@ -408,6 +309,32 @@ class HeapVisitor : public ObjectVisitor {
virtual ResultType VisitFreeSpace(Map* map, FreeSpace* object);
};
class NewSpaceVisitor : public HeapVisitor<int, NewSpaceVisitor> {
public:
void VisitCodeEntry(JSFunction* host, Address code_entry) final {
// Code is not in new space.
}
// Special cases for young generation.
inline int VisitJSFunction(Map* map, JSFunction* object) final;
inline int VisitNativeContext(Map* map, Context* object) final;
int VisitJSApiObject(Map* map, JSObject* object) final {
return VisitJSObject(map, object);
}
int VisitBytecodeArray(Map* map, BytecodeArray* object) final {
UNREACHABLE();
return 0;
}
int VisitSharedFunctionInfo(Map* map, SharedFunctionInfo* object) final {
UNREACHABLE();
return 0;
}
};
class WeakObjectRetainer;
// A weak list is single linked list where each element has a weak pointer to

View File

@ -61,13 +61,14 @@ SlotCallbackResult Scavenger::CheckAndScavengeObject(Heap* heap,
return REMOVE_SLOT;
}
// static
void StaticScavengeVisitor::VisitPointer(Heap* heap, HeapObject* obj,
Object** p) {
Object* object = *p;
if (!heap->InNewSpace(object)) return;
Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p),
reinterpret_cast<HeapObject*>(object));
void ScavengeVisitor::VisitPointers(HeapObject* host, Object** start,
Object** end) {
for (Object** p = start; p < end; p++) {
Object* object = *p;
if (!heap_->InNewSpace(object)) continue;
Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p),
reinterpret_cast<HeapObject*>(object));
}
}
} // namespace internal

View File

@ -59,13 +59,14 @@ class RootScavengeVisitor : public RootVisitor {
Heap* heap_;
};
// Helper class for turning the scavenger into an object visitor that is also
// filtering out non-HeapObjects and objects which do not reside in new space.
class StaticScavengeVisitor
: public StaticNewSpaceVisitor<StaticScavengeVisitor> {
class ScavengeVisitor : public NewSpaceVisitor {
public:
static inline void VisitPointer(Heap* heap, HeapObject* object, Object** p);
explicit ScavengeVisitor(Heap* heap) : heap_(heap) {}
inline void VisitPointers(HeapObject* host, Object** start,
Object** end) final;
private:
Heap* heap_;
};
} // namespace internal