From dbb1cbe3a85d5c5528ce876d905e78d2ab35f00b Mon Sep 17 00:00:00 2001 From: ulan Date: Wed, 29 Mar 2017 08:21:48 -0700 Subject: [PATCH] [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} --- src/heap/objects-visiting-inl.h | 26 +++---- src/heap/objects-visiting.cc | 20 ++--- src/heap/objects-visiting.h | 121 +++-------------------------- src/heap/scavenger.cc | 19 ++--- src/objects-body-descriptors-inl.h | 25 ++++++ src/objects.h | 1 + 6 files changed, 64 insertions(+), 148 deletions(-) diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index b6c20c00e0..2b82c6b29e 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -95,18 +95,15 @@ void StaticNewSpaceVisitor::Initialize() { table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitDataObject, &DataObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit); + table_.Register(kVisitJSObject, &JSObjectVisitor::Visit); // Not using specialized Api object visitor for newspace. - table_.template RegisterSpecializations(); + table_.Register(kVisitJSApiObject, &JSObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitStruct, &StructVisitor::Visit); table_.Register(kVisitBytecodeArray, &UnreachableVisitor); table_.Register(kVisitSharedFunctionInfo, &UnreachableVisitor); @@ -198,17 +195,14 @@ void StaticMarkingVisitor::Initialize() { table_.Register(kVisitTransitionArray, &VisitTransitionArray); - table_.template RegisterSpecializations(); + table_.Register(kVisitDataObject, &DataObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitJSObjectFast, &JSObjectFastVisitor::Visit); + table_.Register(kVisitJSObject, &JSObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitJSApiObject, &JSApiObjectVisitor::Visit); - table_.template RegisterSpecializations(); + table_.Register(kVisitStruct, &StructObjectVisitor::Visit); } diff --git a/src/heap/objects-visiting.cc b/src/heap/objects-visiting.cc index a0df1f50c0..cf9fb5ed26 100644 --- a/src/heap/objects-visiting.cc +++ b/src/heap/objects-visiting.cc @@ -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(); diff --git a/src/heap/objects-visiting.h b/src/heap/objects-visiting.h index f10f370314..abbb27a326 100644 --- a/src/heap/objects-visiting.h +++ b/src/heap/objects-visiting.h @@ -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(generic)); - - return static_cast(visitor_id); - } }; @@ -172,30 +115,6 @@ class VisitorDispatchTable { callbacks_[id] = reinterpret_cast(callback); } - template - void RegisterSpecialization() { - static const int size = object_size_in_words * kPointerSize; - Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size, false), - &Visitor::template VisitSpecialized); - } - - - template - void RegisterSpecializations() { - STATIC_ASSERT((generic - base + Heap::kMinObjectSizeInWords) == 10); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - RegisterSpecialization(); - Register(generic, &Visitor::Visit); - } - private: base::AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount]; }; @@ -209,18 +128,6 @@ class FlexibleBodyVisitor : public AllStatic { BodyDescriptor::template IterateBody(object, object_size); return static_cast(object_size); } - - // This specialization is only suitable for objects containing pointer fields. - template - 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(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 JSObjectVisitor; + // Visitor for JSObjects without unboxed double fields. + typedef FlexibleBodyVisitor + JSObjectFastVisitor; + typedef int (*Callback)(Map* map, HeapObject* object); static VisitorDispatchTable table_; @@ -408,17 +315,13 @@ class StaticMarkingVisitor : public StaticVisitorBase { typedef FlexibleBodyVisitor FixedArrayVisitor; + typedef FlexibleBodyVisitor + JSObjectFastVisitor; typedef FlexibleBodyVisitor JSObjectVisitor; class JSApiObjectVisitor : AllStatic { public: - template - static inline void VisitSpecialized(Map* map, HeapObject* object) { - TracePossibleWrapper(object); - JSObjectVisitor::template VisitSpecialized(map, object); - } - INLINE(static void Visit(Map* map, HeapObject* object)) { TracePossibleWrapper(object); JSObjectVisitor::Visit(map, object); diff --git a/src/heap/scavenger.cc b/src/heap/scavenger.cc index 4a7bb134cf..7a8e55fd19 100644 --- a/src/heap/scavenger.cc +++ b/src/heap/scavenger.cc @@ -74,18 +74,19 @@ class ScavengingVisitor : public StaticVisitorBase { table_.Register(kVisitJSFunction, &EvacuateJSFunction); - table_.RegisterSpecializations, - kVisitDataObject, kVisitDataObjectGeneric>(); + table_.Register(kVisitDataObject, + &ObjectEvacuationStrategy::Visit); - table_.RegisterSpecializations, - kVisitJSObject, kVisitJSObjectGeneric>(); + table_.Register(kVisitJSObjectFast, + &ObjectEvacuationStrategy::Visit); + table_.Register(kVisitJSObject, + &ObjectEvacuationStrategy::Visit); - table_ - .RegisterSpecializations, - kVisitJSApiObject, kVisitJSApiObjectGeneric>(); + table_.Register(kVisitJSApiObject, + &ObjectEvacuationStrategy::Visit); - table_.RegisterSpecializations, - kVisitStruct, kVisitStructGeneric>(); + table_.Register(kVisitStruct, + &ObjectEvacuationStrategy::Visit); } static VisitorDispatchTable* GetTable() { diff --git a/src/objects-body-descriptors-inl.h b/src/objects-body-descriptors-inl.h index d34c0f04e4..ff679c9846 100644 --- a/src/objects-body-descriptors-inl.h +++ b/src/objects-body-descriptors-inl.h @@ -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 + static inline void IterateBody(HeapObject* obj, int object_size, + ObjectVisitor* v) { + IteratePointers(obj, kStartOffset, object_size, v); + } + + template + static inline void IterateBody(HeapObject* obj, int object_size) { + Heap* heap = obj->GetHeap(); + IteratePointers(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 class JSFunction::BodyDescriptorImpl final : public BodyDescriptorBase { diff --git a/src/objects.h b/src/objects.h index 28704af616..4742ede0d5 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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();