[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:
ulan 2017-03-29 08:21:48 -07:00 committed by Commit bot
parent d0c06a7b95
commit dbb1cbe3a8
6 changed files with 64 additions and 148 deletions

View File

@ -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);
}

View File

@ -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();

View File

@ -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);

View File

@ -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() {

View File

@ -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 {

View File

@ -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();