[heap] Remove size specializations in static object visitors.
Apart from that this patch adds kVisitJSObjectFast for JSObjects that do not have any unboxed double fields and can be visited without run-time layout check. BUG=chromium:694255 Review-Url: https://codereview.chromium.org/2763413007 Cr-Commit-Position: refs/heads/master@{#44237}
This commit is contained in:
parent
d0c06a7b95
commit
dbb1cbe3a8
@ -95,18 +95,15 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
|
||||
|
||||
table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<DataObjectVisitor, kVisitDataObject,
|
||||
kVisitDataObjectGeneric>();
|
||||
table_.Register(kVisitDataObject, &DataObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject,
|
||||
kVisitJSObjectGeneric>();
|
||||
table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit);
|
||||
table_.Register(kVisitJSObject, &JSObjectVisitor::Visit);
|
||||
|
||||
// Not using specialized Api object visitor for newspace.
|
||||
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSApiObject,
|
||||
kVisitJSApiObjectGeneric>();
|
||||
table_.Register(kVisitJSApiObject, &JSObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<StructVisitor, kVisitStruct,
|
||||
kVisitStructGeneric>();
|
||||
table_.Register(kVisitStruct, &StructVisitor::Visit);
|
||||
|
||||
table_.Register(kVisitBytecodeArray, &UnreachableVisitor);
|
||||
table_.Register(kVisitSharedFunctionInfo, &UnreachableVisitor);
|
||||
@ -198,17 +195,14 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() {
|
||||
|
||||
table_.Register(kVisitTransitionArray, &VisitTransitionArray);
|
||||
|
||||
table_.template RegisterSpecializations<DataObjectVisitor, kVisitDataObject,
|
||||
kVisitDataObjectGeneric>();
|
||||
table_.Register(kVisitDataObject, &DataObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject,
|
||||
kVisitJSObjectGeneric>();
|
||||
table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit);
|
||||
table_.Register(kVisitJSObject, &JSObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<JSApiObjectVisitor, kVisitJSApiObject,
|
||||
kVisitJSApiObjectGeneric>();
|
||||
table_.Register(kVisitJSApiObject, &JSApiObjectVisitor::Visit);
|
||||
|
||||
table_.template RegisterSpecializations<StructObjectVisitor, kVisitStruct,
|
||||
kVisitStructGeneric>();
|
||||
table_.Register(kVisitStruct, &StructObjectVisitor::Visit);
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,8 +40,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
||||
return kVisitSlicedString;
|
||||
|
||||
case kExternalStringTag:
|
||||
return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return kVisitDataObject;
|
||||
|
||||
case kThinStringTag:
|
||||
return kVisitThinString;
|
||||
@ -97,8 +96,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
||||
return kVisitSharedFunctionInfo;
|
||||
|
||||
case JS_PROXY_TYPE:
|
||||
return GetVisitorIdForSize(kVisitStruct, kVisitStructGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return kVisitStruct;
|
||||
|
||||
case SYMBOL_TYPE:
|
||||
return kVisitSymbol;
|
||||
@ -166,24 +164,19 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
||||
case JS_PROMISE_CAPABILITY_TYPE:
|
||||
case JS_PROMISE_TYPE:
|
||||
case JS_BOUND_FUNCTION_TYPE:
|
||||
return GetVisitorIdForSize(kVisitJSObject, kVisitJSObjectGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
|
||||
case JS_API_OBJECT_TYPE:
|
||||
case JS_SPECIAL_API_OBJECT_TYPE:
|
||||
return GetVisitorIdForSize(kVisitJSApiObject, kVisitJSApiObjectGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return kVisitJSApiObject;
|
||||
|
||||
case JS_FUNCTION_TYPE:
|
||||
return kVisitJSFunction;
|
||||
|
||||
case FILLER_TYPE:
|
||||
if (instance_size == kPointerSize) return kVisitDataObjectGeneric;
|
||||
// Fall through.
|
||||
case FOREIGN_TYPE:
|
||||
case HEAP_NUMBER_TYPE:
|
||||
case MUTABLE_HEAP_NUMBER_TYPE:
|
||||
return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return kVisitDataObject;
|
||||
|
||||
case FIXED_UINT8_ARRAY_TYPE:
|
||||
case FIXED_INT8_ARRAY_TYPE:
|
||||
@ -205,8 +198,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
|
||||
return kVisitAllocationSite;
|
||||
}
|
||||
|
||||
return GetVisitorIdForSize(kVisitStruct, kVisitStructGeneric,
|
||||
instance_size, has_unboxed_fields);
|
||||
return kVisitStruct;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -41,42 +41,11 @@ class StaticVisitorBase : public AllStatic {
|
||||
V(FixedFloat64Array) \
|
||||
V(NativeContext) \
|
||||
V(AllocationSite) \
|
||||
V(DataObject2) \
|
||||
V(DataObject3) \
|
||||
V(DataObject4) \
|
||||
V(DataObject5) \
|
||||
V(DataObject6) \
|
||||
V(DataObject7) \
|
||||
V(DataObject8) \
|
||||
V(DataObject9) \
|
||||
V(DataObjectGeneric) \
|
||||
V(JSObject2) \
|
||||
V(JSObject3) \
|
||||
V(JSObject4) \
|
||||
V(JSObject5) \
|
||||
V(JSObject6) \
|
||||
V(JSObject7) \
|
||||
V(JSObject8) \
|
||||
V(JSObject9) \
|
||||
V(JSObjectGeneric) \
|
||||
V(JSApiObject2) \
|
||||
V(JSApiObject3) \
|
||||
V(JSApiObject4) \
|
||||
V(JSApiObject5) \
|
||||
V(JSApiObject6) \
|
||||
V(JSApiObject7) \
|
||||
V(JSApiObject8) \
|
||||
V(JSApiObject9) \
|
||||
V(JSApiObjectGeneric) \
|
||||
V(Struct2) \
|
||||
V(Struct3) \
|
||||
V(Struct4) \
|
||||
V(Struct5) \
|
||||
V(Struct6) \
|
||||
V(Struct7) \
|
||||
V(Struct8) \
|
||||
V(Struct9) \
|
||||
V(StructGeneric) \
|
||||
V(DataObject) \
|
||||
V(JSObjectFast) \
|
||||
V(JSObject) \
|
||||
V(JSApiObject) \
|
||||
V(Struct) \
|
||||
V(ConsString) \
|
||||
V(SlicedString) \
|
||||
V(ThinString) \
|
||||
@ -107,11 +76,7 @@ class StaticVisitorBase : public AllStatic {
|
||||
#define VISITOR_ID_ENUM_DECL(id) kVisit##id,
|
||||
VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
|
||||
#undef VISITOR_ID_ENUM_DECL
|
||||
kVisitorIdCount,
|
||||
kVisitDataObject = kVisitDataObject2,
|
||||
kVisitJSObject = kVisitJSObject2,
|
||||
kVisitJSApiObject = kVisitJSApiObject2,
|
||||
kVisitStruct = kVisitStruct2,
|
||||
kVisitorIdCount
|
||||
};
|
||||
|
||||
// Visitor ID should fit in one byte.
|
||||
@ -124,28 +89,6 @@ class StaticVisitorBase : public AllStatic {
|
||||
|
||||
// Determine which specialized visitor should be used for given map.
|
||||
static VisitorId GetVisitorId(Map* map);
|
||||
|
||||
// For visitors that allow specialization by size calculate VisitorId based
|
||||
// on size, base visitor id and generic visitor id.
|
||||
static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic,
|
||||
int object_size,
|
||||
bool has_unboxed_fields) {
|
||||
DCHECK((base == kVisitDataObject) || (base == kVisitStruct) ||
|
||||
(base == kVisitJSObject) || (base == kVisitJSApiObject));
|
||||
DCHECK(IsAligned(object_size, kPointerSize));
|
||||
DCHECK(Heap::kMinObjectSizeInWords * kPointerSize <= object_size);
|
||||
DCHECK(object_size <= kMaxRegularHeapObjectSize);
|
||||
DCHECK(!has_unboxed_fields || (base == kVisitJSObject) ||
|
||||
(base == kVisitJSApiObject));
|
||||
|
||||
if (has_unboxed_fields) return generic;
|
||||
|
||||
int visitor_id = Min(
|
||||
base + (object_size >> kPointerSizeLog2) - Heap::kMinObjectSizeInWords,
|
||||
static_cast<int>(generic));
|
||||
|
||||
return static_cast<VisitorId>(visitor_id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -172,30 +115,6 @@ class VisitorDispatchTable {
|
||||
callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback);
|
||||
}
|
||||
|
||||
template <typename Visitor, StaticVisitorBase::VisitorId base,
|
||||
StaticVisitorBase::VisitorId generic, int object_size_in_words>
|
||||
void RegisterSpecialization() {
|
||||
static const int size = object_size_in_words * kPointerSize;
|
||||
Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size, false),
|
||||
&Visitor::template VisitSpecialized<size>);
|
||||
}
|
||||
|
||||
|
||||
template <typename Visitor, StaticVisitorBase::VisitorId base,
|
||||
StaticVisitorBase::VisitorId generic>
|
||||
void RegisterSpecializations() {
|
||||
STATIC_ASSERT((generic - base + Heap::kMinObjectSizeInWords) == 10);
|
||||
RegisterSpecialization<Visitor, base, generic, 2>();
|
||||
RegisterSpecialization<Visitor, base, generic, 3>();
|
||||
RegisterSpecialization<Visitor, base, generic, 4>();
|
||||
RegisterSpecialization<Visitor, base, generic, 5>();
|
||||
RegisterSpecialization<Visitor, base, generic, 6>();
|
||||
RegisterSpecialization<Visitor, base, generic, 7>();
|
||||
RegisterSpecialization<Visitor, base, generic, 8>();
|
||||
RegisterSpecialization<Visitor, base, generic, 9>();
|
||||
Register(generic, &Visitor::Visit);
|
||||
}
|
||||
|
||||
private:
|
||||
base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount];
|
||||
};
|
||||
@ -209,18 +128,6 @@ class FlexibleBodyVisitor : public AllStatic {
|
||||
BodyDescriptor::template IterateBody<StaticVisitor>(object, object_size);
|
||||
return static_cast<ReturnType>(object_size);
|
||||
}
|
||||
|
||||
// This specialization is only suitable for objects containing pointer fields.
|
||||
template <int object_size>
|
||||
static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) {
|
||||
DCHECK(BodyDescriptor::SizeOf(map, object) == object_size);
|
||||
DCHECK(!FLAG_unbox_double_fields || map->HasFastPointerLayout());
|
||||
StaticVisitor::VisitPointers(
|
||||
object->GetHeap(), object,
|
||||
HeapObject::RawField(object, BodyDescriptor::kStartOffset),
|
||||
HeapObject::RawField(object, object_size));
|
||||
return static_cast<ReturnType>(object_size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -289,10 +196,6 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
|
||||
return FixedDoubleArray::SizeFor(length);
|
||||
}
|
||||
|
||||
INLINE(static int VisitJSObject(Map* map, HeapObject* object)) {
|
||||
return JSObjectVisitor::Visit(map, object);
|
||||
}
|
||||
|
||||
INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) {
|
||||
return SeqOneByteString::cast(object)
|
||||
->SeqOneByteStringSize(map->instance_type());
|
||||
@ -325,6 +228,10 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
|
||||
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_;
|
||||
@ -408,17 +315,13 @@ class StaticMarkingVisitor : public StaticVisitorBase {
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, FixedArray::BodyDescriptor, void>
|
||||
FixedArrayVisitor;
|
||||
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::FastBodyDescriptor, void>
|
||||
JSObjectFastVisitor;
|
||||
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, void>
|
||||
JSObjectVisitor;
|
||||
|
||||
class JSApiObjectVisitor : AllStatic {
|
||||
public:
|
||||
template <int size>
|
||||
static inline void VisitSpecialized(Map* map, HeapObject* object) {
|
||||
TracePossibleWrapper(object);
|
||||
JSObjectVisitor::template VisitSpecialized<size>(map, object);
|
||||
}
|
||||
|
||||
INLINE(static void Visit(Map* map, HeapObject* object)) {
|
||||
TracePossibleWrapper(object);
|
||||
JSObjectVisitor::Visit(map, object);
|
||||
|
@ -74,18 +74,19 @@ class ScavengingVisitor : public StaticVisitorBase {
|
||||
|
||||
table_.Register(kVisitJSFunction, &EvacuateJSFunction);
|
||||
|
||||
table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
|
||||
kVisitDataObject, kVisitDataObjectGeneric>();
|
||||
table_.Register(kVisitDataObject,
|
||||
&ObjectEvacuationStrategy<DATA_OBJECT>::Visit);
|
||||
|
||||
table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
|
||||
kVisitJSObject, kVisitJSObjectGeneric>();
|
||||
table_.Register(kVisitJSObjectFast,
|
||||
&ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
|
||||
table_.Register(kVisitJSObject,
|
||||
&ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
|
||||
|
||||
table_
|
||||
.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
|
||||
kVisitJSApiObject, kVisitJSApiObjectGeneric>();
|
||||
table_.Register(kVisitJSApiObject,
|
||||
&ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
|
||||
|
||||
table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
|
||||
kVisitStruct, kVisitStructGeneric>();
|
||||
table_.Register(kVisitStruct,
|
||||
&ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
|
||||
}
|
||||
|
||||
static VisitorDispatchTable<ScavengingCallback>* GetTable() {
|
||||
|
@ -131,6 +131,31 @@ class JSObject::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
class JSObject::FastBodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = JSReceiver::kPropertiesOffset;
|
||||
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
return offset >= kStartOffset;
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kStartOffset, object_size, v);
|
||||
}
|
||||
|
||||
template <typename StaticVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size) {
|
||||
Heap* heap = obj->GetHeap();
|
||||
IteratePointers<StaticVisitor>(heap, obj, kStartOffset, object_size);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return map->instance_size();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterates the function object according to the visiting policy.
|
||||
template <JSFunction::BodyVisitingPolicy body_visiting_policy>
|
||||
class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
|
||||
|
@ -2553,6 +2553,7 @@ class JSObject: public JSReceiver {
|
||||
STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize);
|
||||
|
||||
class BodyDescriptor;
|
||||
class FastBodyDescriptor;
|
||||
|
||||
// Gets the number of currently used elements.
|
||||
int GetFastElementsUsage();
|
||||
|
Loading…
Reference in New Issue
Block a user