Commit dbb1cbe3 authored by ulan's avatar ulan Committed by Commit bot

[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}
parent d0c06a7b
...@@ -95,18 +95,15 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() { ...@@ -95,18 +95,15 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit); table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit);
table_.template RegisterSpecializations<DataObjectVisitor, kVisitDataObject, table_.Register(kVisitDataObject, &DataObjectVisitor::Visit);
kVisitDataObjectGeneric>();
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject, table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit);
kVisitJSObjectGeneric>(); table_.Register(kVisitJSObject, &JSObjectVisitor::Visit);
// Not using specialized Api object visitor for newspace. // Not using specialized Api object visitor for newspace.
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSApiObject, table_.Register(kVisitJSApiObject, &JSObjectVisitor::Visit);
kVisitJSApiObjectGeneric>();
table_.template RegisterSpecializations<StructVisitor, kVisitStruct, table_.Register(kVisitStruct, &StructVisitor::Visit);
kVisitStructGeneric>();
table_.Register(kVisitBytecodeArray, &UnreachableVisitor); table_.Register(kVisitBytecodeArray, &UnreachableVisitor);
table_.Register(kVisitSharedFunctionInfo, &UnreachableVisitor); table_.Register(kVisitSharedFunctionInfo, &UnreachableVisitor);
...@@ -198,17 +195,14 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() { ...@@ -198,17 +195,14 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() {
table_.Register(kVisitTransitionArray, &VisitTransitionArray); table_.Register(kVisitTransitionArray, &VisitTransitionArray);
table_.template RegisterSpecializations<DataObjectVisitor, kVisitDataObject, table_.Register(kVisitDataObject, &DataObjectVisitor::Visit);
kVisitDataObjectGeneric>();
table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject, table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit);
kVisitJSObjectGeneric>(); table_.Register(kVisitJSObject, &JSObjectVisitor::Visit);
table_.template RegisterSpecializations<JSApiObjectVisitor, kVisitJSApiObject, table_.Register(kVisitJSApiObject, &JSApiObjectVisitor::Visit);
kVisitJSApiObjectGeneric>();
table_.template RegisterSpecializations<StructObjectVisitor, kVisitStruct, table_.Register(kVisitStruct, &StructObjectVisitor::Visit);
kVisitStructGeneric>();
} }
......
...@@ -40,8 +40,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -40,8 +40,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
return kVisitSlicedString; return kVisitSlicedString;
case kExternalStringTag: case kExternalStringTag:
return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric, return kVisitDataObject;
instance_size, has_unboxed_fields);
case kThinStringTag: case kThinStringTag:
return kVisitThinString; return kVisitThinString;
...@@ -97,8 +96,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -97,8 +96,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
return kVisitSharedFunctionInfo; return kVisitSharedFunctionInfo;
case JS_PROXY_TYPE: case JS_PROXY_TYPE:
return GetVisitorIdForSize(kVisitStruct, kVisitStructGeneric, return kVisitStruct;
instance_size, has_unboxed_fields);
case SYMBOL_TYPE: case SYMBOL_TYPE:
return kVisitSymbol; return kVisitSymbol;
...@@ -166,24 +164,19 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -166,24 +164,19 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_PROMISE_CAPABILITY_TYPE: case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE: case JS_PROMISE_TYPE:
case JS_BOUND_FUNCTION_TYPE: case JS_BOUND_FUNCTION_TYPE:
return GetVisitorIdForSize(kVisitJSObject, kVisitJSObjectGeneric, return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
instance_size, has_unboxed_fields);
case JS_API_OBJECT_TYPE: case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE: case JS_SPECIAL_API_OBJECT_TYPE:
return GetVisitorIdForSize(kVisitJSApiObject, kVisitJSApiObjectGeneric, return kVisitJSApiObject;
instance_size, has_unboxed_fields);
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
return kVisitJSFunction; return kVisitJSFunction;
case FILLER_TYPE: case FILLER_TYPE:
if (instance_size == kPointerSize) return kVisitDataObjectGeneric;
// Fall through.
case FOREIGN_TYPE: case FOREIGN_TYPE:
case HEAP_NUMBER_TYPE: case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE: case MUTABLE_HEAP_NUMBER_TYPE:
return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric, return kVisitDataObject;
instance_size, has_unboxed_fields);
case FIXED_UINT8_ARRAY_TYPE: case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE: case FIXED_INT8_ARRAY_TYPE:
...@@ -205,8 +198,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -205,8 +198,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
return kVisitAllocationSite; return kVisitAllocationSite;
} }
return GetVisitorIdForSize(kVisitStruct, kVisitStructGeneric, return kVisitStruct;
instance_size, has_unboxed_fields);
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -41,42 +41,11 @@ class StaticVisitorBase : public AllStatic { ...@@ -41,42 +41,11 @@ class StaticVisitorBase : public AllStatic {
V(FixedFloat64Array) \ V(FixedFloat64Array) \
V(NativeContext) \ V(NativeContext) \
V(AllocationSite) \ V(AllocationSite) \
V(DataObject2) \ V(DataObject) \
V(DataObject3) \ V(JSObjectFast) \
V(DataObject4) \ V(JSObject) \
V(DataObject5) \ V(JSApiObject) \
V(DataObject6) \ V(Struct) \
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(ConsString) \ V(ConsString) \
V(SlicedString) \ V(SlicedString) \
V(ThinString) \ V(ThinString) \
...@@ -107,11 +76,7 @@ class StaticVisitorBase : public AllStatic { ...@@ -107,11 +76,7 @@ class StaticVisitorBase : public AllStatic {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id, #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL #undef VISITOR_ID_ENUM_DECL
kVisitorIdCount, kVisitorIdCount
kVisitDataObject = kVisitDataObject2,
kVisitJSObject = kVisitJSObject2,
kVisitJSApiObject = kVisitJSApiObject2,
kVisitStruct = kVisitStruct2,
}; };
// Visitor ID should fit in one byte. // Visitor ID should fit in one byte.
...@@ -124,28 +89,6 @@ class StaticVisitorBase : public AllStatic { ...@@ -124,28 +89,6 @@ class StaticVisitorBase : public AllStatic {
// Determine which specialized visitor should be used for given map. // Determine which specialized visitor should be used for given map.
static VisitorId GetVisitorId(Map* 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 { ...@@ -172,30 +115,6 @@ class VisitorDispatchTable {
callbacks_[id] = reinterpret_cast<base::AtomicWord>(callback); 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: private:
base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount];
}; };
...@@ -209,18 +128,6 @@ class FlexibleBodyVisitor : public AllStatic { ...@@ -209,18 +128,6 @@ class FlexibleBodyVisitor : public AllStatic {
BodyDescriptor::template IterateBody<StaticVisitor>(object, object_size); BodyDescriptor::template IterateBody<StaticVisitor>(object, object_size);
return static_cast<ReturnType>(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 { ...@@ -289,10 +196,6 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
return FixedDoubleArray::SizeFor(length); 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)) { INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) {
return SeqOneByteString::cast(object) return SeqOneByteString::cast(object)
->SeqOneByteStringSize(map->instance_type()); ->SeqOneByteStringSize(map->instance_type());
...@@ -325,6 +228,10 @@ class StaticNewSpaceVisitor : public StaticVisitorBase { ...@@ -325,6 +228,10 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, int> typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, int>
JSObjectVisitor; JSObjectVisitor;
// Visitor for JSObjects without unboxed double fields.
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::FastBodyDescriptor, int>
JSObjectFastVisitor;
typedef int (*Callback)(Map* map, HeapObject* object); typedef int (*Callback)(Map* map, HeapObject* object);
static VisitorDispatchTable<Callback> table_; static VisitorDispatchTable<Callback> table_;
...@@ -408,17 +315,13 @@ class StaticMarkingVisitor : public StaticVisitorBase { ...@@ -408,17 +315,13 @@ class StaticMarkingVisitor : public StaticVisitorBase {
typedef FlexibleBodyVisitor<StaticVisitor, FixedArray::BodyDescriptor, void> typedef FlexibleBodyVisitor<StaticVisitor, FixedArray::BodyDescriptor, void>
FixedArrayVisitor; FixedArrayVisitor;
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::FastBodyDescriptor, void>
JSObjectFastVisitor;
typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, void> typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, void>
JSObjectVisitor; JSObjectVisitor;
class JSApiObjectVisitor : AllStatic { class JSApiObjectVisitor : AllStatic {
public: 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)) { INLINE(static void Visit(Map* map, HeapObject* object)) {
TracePossibleWrapper(object); TracePossibleWrapper(object);
JSObjectVisitor::Visit(map, object); JSObjectVisitor::Visit(map, object);
......
...@@ -74,18 +74,19 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -74,18 +74,19 @@ class ScavengingVisitor : public StaticVisitorBase {
table_.Register(kVisitJSFunction, &EvacuateJSFunction); table_.Register(kVisitJSFunction, &EvacuateJSFunction);
table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>, table_.Register(kVisitDataObject,
kVisitDataObject, kVisitDataObjectGeneric>(); &ObjectEvacuationStrategy<DATA_OBJECT>::Visit);
table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, table_.Register(kVisitJSObjectFast,
kVisitJSObject, kVisitJSObjectGeneric>(); &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
table_.Register(kVisitJSObject,
&ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
table_ table_.Register(kVisitJSApiObject,
.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
kVisitJSApiObject, kVisitJSApiObjectGeneric>();
table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, table_.Register(kVisitStruct,
kVisitStruct, kVisitStructGeneric>(); &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
} }
static VisitorDispatchTable<ScavengingCallback>* GetTable() { static VisitorDispatchTable<ScavengingCallback>* GetTable() {
......
...@@ -131,6 +131,31 @@ class JSObject::BodyDescriptor final : public BodyDescriptorBase { ...@@ -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. // Iterates the function object according to the visiting policy.
template <JSFunction::BodyVisitingPolicy body_visiting_policy> template <JSFunction::BodyVisitingPolicy body_visiting_policy>
class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase { class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase {
......
...@@ -2553,6 +2553,7 @@ class JSObject: public JSReceiver { ...@@ -2553,6 +2553,7 @@ class JSObject: public JSReceiver {
STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize); STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize);
class BodyDescriptor; class BodyDescriptor;
class FastBodyDescriptor;
// Gets the number of currently used elements. // Gets the number of currently used elements.
int GetFastElementsUsage(); int GetFastElementsUsage();
......
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