Commit 9cb2211c authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[heap] Remove StaticVisitorBase; Introduce Map::GetVisitorId

Bug: chromium:738368
Change-Id: I749517391f9d5dd0827f3d37f975f6c61542d1ff
Reviewed-on: https://chromium-review.googlesource.com/558914
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46391}
parent 72b5d5c0
...@@ -2187,29 +2187,28 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, ...@@ -2187,29 +2187,28 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE); AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE);
if (!allocation.To(&result)) return allocation; if (!allocation.To(&result)) return allocation;
// Map::cast cannot be used due to uninitialized map field. // Map::cast cannot be used due to uninitialized map field.
reinterpret_cast<Map*>(result)->set_map_after_allocation( Map* map = reinterpret_cast<Map*>(result);
reinterpret_cast<Map*>(root(kMetaMapRootIndex)), SKIP_WRITE_BARRIER); map->set_map_after_allocation(reinterpret_cast<Map*>(root(kMetaMapRootIndex)),
reinterpret_cast<Map*>(result)->set_instance_type(instance_type); SKIP_WRITE_BARRIER);
reinterpret_cast<Map*>(result)->set_instance_size(instance_size); map->set_instance_type(instance_type);
map->set_instance_size(instance_size);
// Initialize to only containing tagged fields. // Initialize to only containing tagged fields.
reinterpret_cast<Map*>(result)->set_visitor_id(
StaticVisitorBase::GetVisitorId(instance_type, instance_size, false));
if (FLAG_unbox_double_fields) { if (FLAG_unbox_double_fields) {
reinterpret_cast<Map*>(result) map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); }
} // GetVisitorId requires a properly initialized LayoutDescriptor.
reinterpret_cast<Map*>(result)->clear_unused(); map->set_visitor_id(Map::GetVisitorId(map));
reinterpret_cast<Map*>(result) map->clear_unused();
->set_inobject_properties_or_constructor_function_index(0); map->set_inobject_properties_or_constructor_function_index(0);
reinterpret_cast<Map*>(result)->set_unused_property_fields(0); map->set_unused_property_fields(0);
reinterpret_cast<Map*>(result)->set_bit_field(0); map->set_bit_field(0);
reinterpret_cast<Map*>(result)->set_bit_field2(0); map->set_bit_field2(0);
int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
Map::OwnsDescriptors::encode(true) | Map::OwnsDescriptors::encode(true) |
Map::ConstructionCounter::encode(Map::kNoSlackTracking); Map::ConstructionCounter::encode(Map::kNoSlackTracking);
reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3); map->set_bit_field3(bit_field3);
reinterpret_cast<Map*>(result)->set_weak_cell_cache(Smi::kZero); map->set_weak_cell_cache(Smi::kZero);
return result; return map;
} }
...@@ -2241,7 +2240,7 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type, ...@@ -2241,7 +2240,7 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
} }
// Must be called only after |instance_type|, |instance_size| and // Must be called only after |instance_type|, |instance_size| and
// |layout_descriptor| are set. // |layout_descriptor| are set.
map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map)); map->set_visitor_id(Map::GetVisitorId(map));
map->set_bit_field(0); map->set_bit_field(0);
map->set_bit_field2(1 << Map::kIsExtensible); map->set_bit_field2(1 << Map::kIsExtensible);
int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) | int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
...@@ -6692,12 +6691,6 @@ bool Heap::GetObjectTypeName(size_t index, const char** object_type, ...@@ -6692,12 +6691,6 @@ bool Heap::GetObjectTypeName(size_t index, const char** object_type,
return false; return false;
} }
// static
int Heap::GetStaticVisitorIdForMap(Map* map) {
return StaticVisitorBase::GetVisitorId(map);
}
const char* AllocationSpaceName(AllocationSpace space) { const char* AllocationSpaceName(AllocationSpace space) {
switch (space) { switch (space) {
case NEW_SPACE: case NEW_SPACE:
......
...@@ -728,10 +728,6 @@ class Heap { ...@@ -728,10 +728,6 @@ class Heap {
// by pointer size. // by pointer size.
static inline void CopyBlock(Address dst, Address src, int byte_size); static inline void CopyBlock(Address dst, Address src, int byte_size);
// Determines a static visitor id based on the given {map} that can then be
// stored on the map to facilitate fast dispatch for {StaticVisitorBase}.
static int GetStaticVisitorIdForMap(Map* map);
// Notifies the heap that is ok to start marking or other activities that // Notifies the heap that is ok to start marking or other activities that
// should not happen during deserialization. // should not happen during deserialization.
void NotifyDeserializationComplete(); void NotifyDeserializationComplete();
......
...@@ -17,205 +17,6 @@ ...@@ -17,205 +17,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
VisitorId StaticVisitorBase::GetVisitorId(Map* map) {
return GetVisitorId(map->instance_type(), map->instance_size(),
FLAG_unbox_double_fields && !map->HasFastPointerLayout());
}
VisitorId StaticVisitorBase::GetVisitorId(int instance_type, int instance_size,
bool has_unboxed_fields) {
if (instance_type < FIRST_NONSTRING_TYPE) {
switch (instance_type & kStringRepresentationMask) {
case kSeqStringTag:
if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
return kVisitSeqOneByteString;
} else {
return kVisitSeqTwoByteString;
}
case kConsStringTag:
if (IsShortcutCandidate(instance_type)) {
return kVisitShortcutCandidate;
} else {
return kVisitConsString;
}
case kSlicedStringTag:
return kVisitSlicedString;
case kExternalStringTag:
return kVisitDataObject;
case kThinStringTag:
return kVisitThinString;
}
UNREACHABLE();
}
switch (instance_type) {
case BYTE_ARRAY_TYPE:
return kVisitByteArray;
case BYTECODE_ARRAY_TYPE:
return kVisitBytecodeArray;
case FREE_SPACE_TYPE:
return kVisitFreeSpace;
case FIXED_ARRAY_TYPE:
return kVisitFixedArray;
case FIXED_DOUBLE_ARRAY_TYPE:
return kVisitFixedDoubleArray;
case ODDBALL_TYPE:
return kVisitOddball;
case MAP_TYPE:
return kVisitMap;
case CODE_TYPE:
return kVisitCode;
case CELL_TYPE:
return kVisitCell;
case PROPERTY_CELL_TYPE:
return kVisitPropertyCell;
case WEAK_CELL_TYPE:
return kVisitWeakCell;
case TRANSITION_ARRAY_TYPE:
return kVisitTransitionArray;
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
return kVisitJSWeakCollection;
case JS_REGEXP_TYPE:
return kVisitJSRegExp;
case SHARED_FUNCTION_INFO_TYPE:
return kVisitSharedFunctionInfo;
case JS_PROXY_TYPE:
return kVisitStruct;
case SYMBOL_TYPE:
return kVisitSymbol;
case JS_ARRAY_BUFFER_TYPE:
return kVisitJSArrayBuffer;
case SMALL_ORDERED_HASH_MAP_TYPE:
return kVisitSmallOrderedHashMap;
case SMALL_ORDERED_HASH_SET_TYPE:
return kVisitSmallOrderedHashSet;
case JS_OBJECT_TYPE:
case JS_ERROR_TYPE:
case JS_ARGUMENTS_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
case JS_MODULE_NAMESPACE_TYPE:
case JS_VALUE_TYPE:
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE:
case JS_BOUND_FUNCTION_TYPE:
return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
return kVisitJSApiObject;
case JS_FUNCTION_TYPE:
return kVisitJSFunction;
case FILLER_TYPE:
case FOREIGN_TYPE:
case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE:
return kVisitDataObject;
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
return kVisitFixedTypedArrayBase;
case FIXED_FLOAT64_ARRAY_TYPE:
return kVisitFixedFloat64Array;
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
if (instance_type == ALLOCATION_SITE_TYPE) {
return kVisitAllocationSite;
}
return kVisitStruct;
default:
UNREACHABLE();
}
}
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) { ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) {
return Visit(object->map(), object); return Visit(object->map(), object);
......
...@@ -14,74 +14,6 @@ ...@@ -14,74 +14,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(ByteArray) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(ConsString) \
V(DataObject) \
V(FixedArray) \
V(FixedDoubleArray) \
V(FixedFloat64Array) \
V(FixedTypedArrayBase) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
V(JSFunction) \
V(JSObject) \
V(JSObjectFast) \
V(JSRegExp) \
V(JSWeakCollection) \
V(Map) \
V(NativeContext) \
V(Oddball) \
V(PropertyCell) \
V(SeqOneByteString) \
V(SeqTwoByteString) \
V(SharedFunctionInfo) \
V(ShortcutCandidate) \
V(SlicedString) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(Struct) \
V(Symbol) \
V(ThinString) \
V(TransitionArray) \
V(WeakCell)
// For data objects, JS objects and structs along with generic visitor which
// can visit object of any size we provide visitors specialized by
// object size in words.
// Ids of specialized visitors are declared in a linear order (without
// holes) starting from the id of visitor specialized for 2 words objects
// (base visitor id) and ending with the id of generic visitor.
// Method GetVisitorIdForSize depends on this ordering to calculate visitor
// id of specialized visitor from given instance size, base visitor id and
// generic visitor's id.
enum VisitorId {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id,
VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL
kVisitorIdCount
};
// Base class for all static visitors.
class StaticVisitorBase : public AllStatic {
public:
// Visitor ID should fit in one byte.
STATIC_ASSERT(kVisitorIdCount <= 256);
// Determine which specialized visitor should be used for given instance type
// and instance type.
static inline VisitorId GetVisitorId(int instance_type, int instance_size,
bool has_unboxed_fields);
// Determine which specialized visitor should be used for given map.
static inline VisitorId GetVisitorId(Map* map);
};
#define TYPED_VISITOR_ID_LIST(V) \ #define TYPED_VISITOR_ID_LIST(V) \
V(AllocationSite) \ V(AllocationSite) \
V(ByteArray) \ V(ByteArray) \
...@@ -112,10 +44,9 @@ class StaticVisitorBase : public AllStatic { ...@@ -112,10 +44,9 @@ class StaticVisitorBase : public AllStatic {
V(TransitionArray) \ V(TransitionArray) \
V(WeakCell) V(WeakCell)
// The base class for visitors that need to dispatch on object type. It is // The base class for visitors that need to dispatch on object type. The default
// similar to StaticVisitor except it uses virtual dispatch instead of static // behavior of all visit functions is to iterate body of the given object using
// dispatch table. The default behavior of all visit functions is to iterate // the BodyDescriptor of the object.
// body of the given object using the BodyDescriptor of the object.
// //
// The visit functions return the size of the object cast to ResultType. // The visit functions return the size of the object cast to ResultType.
// //
...@@ -124,8 +55,6 @@ class StaticVisitorBase : public AllStatic { ...@@ -124,8 +55,6 @@ class StaticVisitorBase : public AllStatic {
// class SomeVisitor : public HeapVisitor<ResultType, SomeVisitor> { // class SomeVisitor : public HeapVisitor<ResultType, SomeVisitor> {
// ... // ...
// } // }
//
// TODO(ulan): replace static visitors with the HeapVisitor.
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
class HeapVisitor : public ObjectVisitor { class HeapVisitor : public ObjectVisitor {
public: public:
......
...@@ -6,11 +6,15 @@ ...@@ -6,11 +6,15 @@
#define V8_HEAP_SCAVENGER_INL_H_ #define V8_HEAP_SCAVENGER_INL_H_
#include "src/heap/scavenger.h" #include "src/heap/scavenger.h"
#include "src/objects/map.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
bool Scavenger::ContainsOnlyData(VisitorId visitor_id) { namespace {
// White list for objects that for sure only contain data.
bool ContainsOnlyData(VisitorId visitor_id) {
switch (visitor_id) { switch (visitor_id) {
case kVisitSeqOneByteString: case kVisitSeqOneByteString:
return true; return true;
...@@ -28,6 +32,8 @@ bool Scavenger::ContainsOnlyData(VisitorId visitor_id) { ...@@ -28,6 +32,8 @@ bool Scavenger::ContainsOnlyData(VisitorId visitor_id) {
return false; return false;
} }
} // namespace
// Helper function used by CopyObject to copy a source object to an // Helper function used by CopyObject to copy a source object to an
// allocated target object and update the forwarding pointer in the source // allocated target object and update the forwarding pointer in the source
// object. Returns the target object. // object. Returns the target object.
......
...@@ -32,9 +32,6 @@ class Scavenger { ...@@ -32,9 +32,6 @@ class Scavenger {
inline Heap* heap() { return heap_; } inline Heap* heap() { return heap_; }
private: private:
// White list for objects that for sure only contain data.
V8_INLINE static bool ContainsOnlyData(VisitorId visitor_id);
V8_INLINE HeapObject* MigrateObject(HeapObject* source, HeapObject* target, V8_INLINE HeapObject* MigrateObject(HeapObject* source, HeapObject* target,
int size); int size);
......
...@@ -425,7 +425,7 @@ void Map::DictionaryMapVerify() { ...@@ -425,7 +425,7 @@ void Map::DictionaryMapVerify() {
CHECK(is_dictionary_map()); CHECK(is_dictionary_map());
CHECK(instance_descriptors()->IsEmpty()); CHECK(instance_descriptors()->IsEmpty());
CHECK_EQ(0, unused_property_fields()); CHECK_EQ(0, unused_property_fields());
CHECK_EQ(Heap::GetStaticVisitorIdForMap(this), visitor_id()); CHECK_EQ(Map::GetVisitorId(this), visitor_id());
} }
......
...@@ -4273,11 +4273,11 @@ void Map::UpdateDescriptors(DescriptorArray* descriptors, ...@@ -4273,11 +4273,11 @@ void Map::UpdateDescriptors(DescriptorArray* descriptors,
// TODO(ishell): remove these checks from VERIFY_HEAP mode. // TODO(ishell): remove these checks from VERIFY_HEAP mode.
if (FLAG_verify_heap) { if (FLAG_verify_heap) {
CHECK(layout_descriptor()->IsConsistentWithMap(this)); CHECK(layout_descriptor()->IsConsistentWithMap(this));
CHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); CHECK(visitor_id() == Map::GetVisitorId(this));
} }
#else #else
SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this));
DCHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); DCHECK(visitor_id() == Map::GetVisitorId(this));
#endif #endif
} }
} }
...@@ -4299,7 +4299,7 @@ void Map::InitializeDescriptors(DescriptorArray* descriptors, ...@@ -4299,7 +4299,7 @@ void Map::InitializeDescriptors(DescriptorArray* descriptors,
#else #else
SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this));
#endif #endif
set_visitor_id(Heap::GetStaticVisitorIdForMap(this)); set_visitor_id(Map::GetVisitorId(this));
} }
} }
......
...@@ -2855,6 +2855,204 @@ void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind, ...@@ -2855,6 +2855,204 @@ void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
os << "]\n"; os << "]\n";
} }
VisitorId Map::GetVisitorId(Map* map) {
STATIC_ASSERT(kVisitorIdCount <= 256);
const int instance_type = map->instance_type();
const bool has_unboxed_fields =
FLAG_unbox_double_fields && !map->HasFastPointerLayout();
if (instance_type < FIRST_NONSTRING_TYPE) {
switch (instance_type & kStringRepresentationMask) {
case kSeqStringTag:
if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
return kVisitSeqOneByteString;
} else {
return kVisitSeqTwoByteString;
}
case kConsStringTag:
if (IsShortcutCandidate(instance_type)) {
return kVisitShortcutCandidate;
} else {
return kVisitConsString;
}
case kSlicedStringTag:
return kVisitSlicedString;
case kExternalStringTag:
return kVisitDataObject;
case kThinStringTag:
return kVisitThinString;
}
UNREACHABLE();
}
switch (instance_type) {
case BYTE_ARRAY_TYPE:
return kVisitByteArray;
case BYTECODE_ARRAY_TYPE:
return kVisitBytecodeArray;
case FREE_SPACE_TYPE:
return kVisitFreeSpace;
case FIXED_ARRAY_TYPE:
return kVisitFixedArray;
case FIXED_DOUBLE_ARRAY_TYPE:
return kVisitFixedDoubleArray;
case ODDBALL_TYPE:
return kVisitOddball;
case MAP_TYPE:
return kVisitMap;
case CODE_TYPE:
return kVisitCode;
case CELL_TYPE:
return kVisitCell;
case PROPERTY_CELL_TYPE:
return kVisitPropertyCell;
case WEAK_CELL_TYPE:
return kVisitWeakCell;
case TRANSITION_ARRAY_TYPE:
return kVisitTransitionArray;
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
return kVisitJSWeakCollection;
case JS_REGEXP_TYPE:
return kVisitJSRegExp;
case SHARED_FUNCTION_INFO_TYPE:
return kVisitSharedFunctionInfo;
case JS_PROXY_TYPE:
return kVisitStruct;
case SYMBOL_TYPE:
return kVisitSymbol;
case JS_ARRAY_BUFFER_TYPE:
return kVisitJSArrayBuffer;
case SMALL_ORDERED_HASH_MAP_TYPE:
return kVisitSmallOrderedHashMap;
case SMALL_ORDERED_HASH_SET_TYPE:
return kVisitSmallOrderedHashSet;
case JS_OBJECT_TYPE:
case JS_ERROR_TYPE:
case JS_ARGUMENTS_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
case JS_MODULE_NAMESPACE_TYPE:
case JS_VALUE_TYPE:
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE:
case JS_BOUND_FUNCTION_TYPE:
return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
return kVisitJSApiObject;
case JS_FUNCTION_TYPE:
return kVisitJSFunction;
case FILLER_TYPE:
case FOREIGN_TYPE:
case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE:
return kVisitDataObject;
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
return kVisitFixedTypedArrayBase;
case FIXED_FLOAT64_ARRAY_TYPE:
return kVisitFixedFloat64Array;
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
if (instance_type == ALLOCATION_SITE_TYPE) {
return kVisitAllocationSite;
}
return kVisitStruct;
default:
UNREACHABLE();
}
}
void Map::PrintGeneralization( void Map::PrintGeneralization(
FILE* file, const char* reason, int modify_index, int split, FILE* file, const char* reason, int modify_index, int split,
int descriptors, bool descriptor_to_field, int descriptors, bool descriptor_to_field,
...@@ -8819,7 +9017,7 @@ void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child, ...@@ -8819,7 +9017,7 @@ void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
#else #else
SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child)); SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
#endif #endif
child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child)); child->set_visitor_id(Map::GetVisitorId(*child));
} }
Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
...@@ -8970,7 +9168,7 @@ Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { ...@@ -8970,7 +9168,7 @@ Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
copy->SetInObjectProperties(inobject_properties); copy->SetInObjectProperties(inobject_properties);
copy->set_unused_property_fields(inobject_properties); copy->set_unused_property_fields(inobject_properties);
copy->set_instance_size(new_instance_size); copy->set_instance_size(new_instance_size);
copy->set_visitor_id(Heap::GetStaticVisitorIdForMap(*copy)); copy->set_visitor_id(Map::GetVisitorId(*copy));
return copy; return copy;
} }
...@@ -11909,7 +12107,7 @@ static void GetMinInobjectSlack(Map* map, void* data) { ...@@ -11909,7 +12107,7 @@ static void GetMinInobjectSlack(Map* map, void* data) {
static void ShrinkInstanceSize(Map* map, void* data) { static void ShrinkInstanceSize(Map* map, void* data) {
#ifdef DEBUG #ifdef DEBUG
int old_visitor_id = Heap::GetStaticVisitorIdForMap(map); int old_visitor_id = Map::GetVisitorId(map);
#endif #endif
int slack = *reinterpret_cast<int*>(data); int slack = *reinterpret_cast<int*>(data);
DCHECK_GE(slack, 0); DCHECK_GE(slack, 0);
...@@ -11917,7 +12115,7 @@ static void ShrinkInstanceSize(Map* map, void* data) { ...@@ -11917,7 +12115,7 @@ static void ShrinkInstanceSize(Map* map, void* data) {
map->set_unused_property_fields(map->unused_property_fields() - slack); map->set_unused_property_fields(map->unused_property_fields() - slack);
map->set_instance_size(map->instance_size() - slack * kPointerSize); map->set_instance_size(map->instance_size() - slack * kPointerSize);
map->set_construction_counter(Map::kNoSlackTracking); map->set_construction_counter(Map::kNoSlackTracking);
DCHECK_EQ(old_visitor_id, Heap::GetStaticVisitorIdForMap(map)); DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
} }
static void StopSlackTracking(Map* map, void* data) { static void StopSlackTracking(Map* map, void* data) {
......
...@@ -15,6 +15,59 @@ ...@@ -15,6 +15,59 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(ByteArray) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(ConsString) \
V(DataObject) \
V(FixedArray) \
V(FixedDoubleArray) \
V(FixedFloat64Array) \
V(FixedTypedArrayBase) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
V(JSFunction) \
V(JSObject) \
V(JSObjectFast) \
V(JSRegExp) \
V(JSWeakCollection) \
V(Map) \
V(NativeContext) \
V(Oddball) \
V(PropertyCell) \
V(SeqOneByteString) \
V(SeqTwoByteString) \
V(SharedFunctionInfo) \
V(ShortcutCandidate) \
V(SlicedString) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(Struct) \
V(Symbol) \
V(ThinString) \
V(TransitionArray) \
V(WeakCell)
// For data objects, JS objects and structs along with generic visitor which
// can visit object of any size we provide visitors specialized by
// object size in words.
// Ids of specialized visitors are declared in a linear order (without
// holes) starting from the id of visitor specialized for 2 words objects
// (base visitor id) and ending with the id of generic visitor.
// Method GetVisitorIdForSize depends on this ordering to calculate visitor
// id of specialized visitor from given instance size, base visitor id and
// generic visitor's id.
enum VisitorId {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id,
VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL
kVisitorIdCount
};
typedef std::vector<Handle<Map>> MapHandles; typedef std::vector<Handle<Map>> MapHandles;
// All heap objects have a Map that describes their structure. // All heap objects have a Map that describes their structure.
...@@ -694,6 +747,8 @@ class Map : public HeapObject { ...@@ -694,6 +747,8 @@ class Map : public HeapObject {
// the descriptor array. // the descriptor array.
inline void NotifyLeafMapLayoutChange(); inline void NotifyLeafMapLayoutChange();
static VisitorId GetVisitorId(Map* map);
private: private:
// Returns the map that this (root) map transitions to if its elements_kind // Returns the map that this (root) map transitions to if its elements_kind
// is changed to |elements_kind|, or |nullptr| if no such map is cached yet. // is changed to |elements_kind|, or |nullptr| if no such map is cached yet.
......
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