[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:
parent
1541f422a7
commit
07b1113252
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user