diff options
Diffstat (limited to 'deps/v8/src/objects/map.h')
-rw-r--r-- | deps/v8/src/objects/map.h | 250 |
1 files changed, 115 insertions, 135 deletions
diff --git a/deps/v8/src/objects/map.h b/deps/v8/src/objects/map.h index 5806a24ae0..d9a0a73158 100644 --- a/deps/v8/src/objects/map.h +++ b/deps/v8/src/objects/map.h @@ -6,6 +6,7 @@ #define V8_OBJECTS_MAP_H_ #include "src/objects.h" +#include "src/objects/code.h" #include "src/globals.h" @@ -22,6 +23,7 @@ namespace internal { V(BytecodeArray) \ V(Cell) \ V(Code) \ + V(CodeDataContainer) \ V(ConsString) \ V(DataObject) \ V(FeedbackVector) \ @@ -84,23 +86,28 @@ typedef std::vector<Handle<Map>> MapHandles; // +---------------+---------------------------------------------+ // | TaggedPointer | map - Always a pointer to the MetaMap root | // +---------------+---------------------------------------------+ -// | Int | instance_sizes (the first int field) | +// | Int | The first int field | // `---+----------+---------------------------------------------+ // | Byte | [instance_size] | // +----------+---------------------------------------------+ // | Byte | If Map for a primitive type: | // | | native context index for constructor fn | // | | If Map for an Object type: | -// | | number of in-object properties | +// | | inobject properties start offset in words | // +----------+---------------------------------------------+ -// | Byte | unused | +// | Byte | [used_or_unused_instance_size_in_words] | +// | | For JSObject in fast mode this byte encodes | +// | | the size of the object that includes only | +// | | the used property fields or the slack size | +// | | in properties backing store. | // +----------+---------------------------------------------+ // | Byte | [visitor_id] | // +----+----------+---------------------------------------------+ -// | Int | instance_attributes (second int field) | +// | Int | The second int field | // `---+----------+---------------------------------------------+ -// | Word16 | [instance_type] in low byte | -// | | [bit_field] in high byte | +// | Short | [instance_type] | +// +----------+---------------------------------------------+ +// | Byte | [bit_field] | // | | - has_non_instance_prototype (bit 0) | // | | - is_callable (bit 1) | // | | - has_named_interceptor (bit 2) | @@ -114,11 +121,8 @@ typedef std::vector<Handle<Map>> MapHandles; // | | - is_extensible (bit 0) | // | | - is_prototype_map (bit 2) | // | | - elements_kind (bits 3..7) | -// +----------+---------------------------------------------+ -// | Byte | [unused_property_fields] number of unused | -// | | property fields in JSObject (for fast-mode) | // +----+----------+---------------------------------------------+ -// | Word | [bit_field3] | +// | Int | [bit_field3] | // | | - number_of_own_descriptors (bit 0..19) | // | | - is_dictionary_map (bit 20) | // | | - owns_descriptors (bit 21) | @@ -131,9 +135,10 @@ typedef std::vector<Handle<Map>> MapHandles; // | | - may_have_interesting_symbols (bit 28) | // | | - construction_counter (bit 29..31) | // | | | -// | | On systems with 64bit pointer types, there | +// +*************************************************************+ +// | Int | On systems with 64bit pointer types, there | // | | is an unused 32bits after bit_field3 | -// +---------------+---------------------------------------------+ +// +*************************************************************+ // | TaggedPointer | [prototype] | // +---------------+---------------------------------------------+ // | TaggedPointer | [constructor_or_backpointer] | @@ -146,7 +151,9 @@ typedef std::vector<Handle<Map>> MapHandles; // | TaggedPointer | [instance_descriptors] | // +*************************************************************+ // ! TaggedPointer ! [layout_descriptors] ! -// ! ! Field is only present on 64 bit arch ! +// ! ! Field is only present if compile-time flag ! +// ! ! FLAG_unbox_double_fields is enabled ! +// ! ! (basically on 64 bit architectures) ! // +*************************************************************+ // | TaggedPointer | [dependent_code] | // +---------------+---------------------------------------------+ @@ -158,20 +165,21 @@ class Map : public HeapObject { // Instance size. // Size in bytes or kVariableSizeSentinel if instances do not have // a fixed size. - inline int instance_size() const; - inline void set_instance_size(int value); + DECL_INT_ACCESSORS(instance_size) + // Size in words or kVariableSizeSentinel if instances do not have + // a fixed size. + DECL_INT_ACCESSORS(instance_size_in_words) - // Only to clear an unused byte, remove once byte is used. - inline void clear_unused(); + // [inobject_properties_start_or_constructor_function_index]: + // Provides access to the inobject properties start offset in words in case of + // JSObject maps, or the constructor function index in case of primitive maps. + DECL_INT_ACCESSORS(inobject_properties_start_or_constructor_function_index) - // [inobject_properties_or_constructor_function_index]: Provides access - // to the inobject properties in case of JSObject maps, or the constructor - // function index in case of primitive maps. - inline int inobject_properties_or_constructor_function_index() const; - inline void set_inobject_properties_or_constructor_function_index(int value); + // Get/set the in-object property area start offset in words in the object. + inline int GetInObjectPropertiesStartInWords() const; + inline void SetInObjectPropertiesStartInWords(int value); // Count of properties allocated in the object (JSObject only). inline int GetInObjectProperties() const; - inline void SetInObjectProperties(int value); // Index of the constructor function in the native context (primitives only), // or the special sentinel value to indicate that there is no object wrapper // for the primitive (i.e. in case of null or undefined). @@ -189,10 +197,22 @@ class Map : public HeapObject { inline InstanceType instance_type() const; inline void set_instance_type(InstanceType value); - // Tells how many unused property fields are available in the - // instance (only used for JSObject in fast mode). - inline int unused_property_fields() const; - inline void set_unused_property_fields(int value); + // Returns the size of the used in-object area including object header + // (only used for JSObject in fast mode, for the other kinds of objects it + // is equal to the instance size). + inline int UsedInstanceSize() const; + + // Tells how many unused property fields (in-object or out-of object) are + // available in the instance (only used for JSObject in fast mode). + inline int UnusedPropertyFields() const; + // Updates the counters tracking unused fields in the object. + inline void SetInObjectUnusedPropertyFields(int unused_property_fields); + // Updates the counters tracking unused fields in the property array. + inline void SetOutOfObjectUnusedPropertyFields(int unused_property_fields); + inline void CopyUnusedPropertyFields(Map* map); + inline void AccountAddedPropertyField(); + inline void AccountAddedOutOfObjectPropertyField( + int unused_in_property_array); // Bit field. inline byte bit_field() const; @@ -222,6 +242,8 @@ class Map : public HeapObject { class NewTargetIsBase : public BitField<bool, 27, 1> {}; class MayHaveInterestingSymbols : public BitField<bool, 28, 1> {}; + STATIC_ASSERT(NumberOfOwnDescriptorsBits::kMax >= kMaxNumberOfDescriptors); + // Keep this bit field at the very end for better code in // Builtins::kJSConstructStubGeneric stub. // This counter is used for in-object slack tracking. @@ -293,19 +315,18 @@ class Map : public HeapObject { // Tells whether the instance has a [[Construct]] internal method. // This property is implemented according to ES6, section 7.2.4. - inline void set_is_constructor(bool value); - inline bool is_constructor() const; + DECL_BOOLEAN_ACCESSORS(is_constructor) // Tells whether the instance with this map may have properties for // interesting symbols on it. // An "interesting symbol" is one for which Name::IsInterestingSymbol() // returns true, i.e. a well-known symbol like @@toStringTag. - inline void set_may_have_interesting_symbols(bool value); - inline bool may_have_interesting_symbols() const; + DECL_BOOLEAN_ACCESSORS(may_have_interesting_symbols) + + DECL_BOOLEAN_ACCESSORS(has_prototype_slot) // Tells whether the instance with this map has a hidden prototype. - inline void set_has_hidden_prototype(bool value); - inline bool has_hidden_prototype() const; + DECL_BOOLEAN_ACCESSORS(has_hidden_prototype) // Records and queries whether the instance has a named interceptor. inline void set_has_named_interceptor(); @@ -329,12 +350,9 @@ class Map : public HeapObject { inline void set_is_callable(); inline bool is_callable() const; - inline void set_new_target_is_base(bool value); - inline bool new_target_is_base() const; - inline void set_is_extensible(bool value); - inline bool is_extensible() const; - inline void set_is_prototype_map(bool value); - inline bool is_prototype_map() const; + DECL_BOOLEAN_ACCESSORS(new_target_is_base) + DECL_BOOLEAN_ACCESSORS(is_extensible) + DECL_BOOLEAN_ACCESSORS(is_prototype_map) inline bool is_abandoned_prototype_map() const; inline void set_elements_kind(ElementsKind elements_kind); @@ -482,7 +500,8 @@ class Map : public HeapObject { // [prototype]: implicit prototype object. DECL_ACCESSORS(prototype, Object) // TODO(jkummerow): make set_prototype private. - static void SetPrototype(Handle<Map> map, Handle<Object> prototype); + static void SetPrototype(Handle<Map> map, Handle<Object> prototype, + bool enable_prototype_setup_mode = true); // [constructor]: points back to the function or FunctionTemplateInfo // responsible for this map. @@ -543,16 +562,14 @@ class Map : public HeapObject { inline int EnumLength() const; inline void SetEnumLength(int length); - inline bool owns_descriptors() const; - inline void set_owns_descriptors(bool owns_descriptors); + DECL_BOOLEAN_ACCESSORS(owns_descriptors) inline void mark_unstable(); inline bool is_stable() const; inline void set_migration_target(bool value); inline bool is_migration_target() const; inline void set_immutable_proto(bool value); inline bool is_immutable_proto() const; - inline void set_construction_counter(int value); - inline int construction_counter() const; + DECL_INT_ACCESSORS(construction_counter) inline void deprecate(); inline bool is_deprecated() const; inline bool CanBeDeprecated() const; @@ -649,17 +666,18 @@ class Map : public HeapObject { DECL_CAST(Map) - // Extend the descriptor array of the map with the list of descriptors. - // In case of duplicates, the latest descriptor is used. - static void AppendCallbackDescriptors(Handle<Map> map, - Handle<Object> descriptors); - static inline int SlackForArraySize(int old_size, int size_limit); static void EnsureDescriptorSlack(Handle<Map> map, int slack); + // Returns the map to be used for instances when the given {prototype} is + // passed to an Object.create call. Might transition the given {prototype}. static Handle<Map> GetObjectCreateMap(Handle<HeapObject> prototype); + // Similar to {GetObjectCreateMap} but does not transition {prototype} and + // fails gracefully by returning an empty handle instead. + static MaybeHandle<Map> TryGetObjectCreateMap(Handle<HeapObject> prototype); + // Computes a hash value for this map, to be used in HashTables and such. int Hash(); @@ -702,8 +720,7 @@ class Map : public HeapObject { void DictionaryMapVerify(); #endif - inline int visitor_id() const; - inline void set_visitor_id(int visitor_id); + DECL_PRIMITIVE_ACCESSORS(visitor_id, VisitorId) static Handle<Map> TransitionToPrototype(Handle<Map> map, Handle<Object> prototype); @@ -713,65 +730,34 @@ class Map : public HeapObject { static const int kMaxPreAllocatedPropertyFields = 255; // Layout description. - static const int kInstanceSizesOffset = HeapObject::kHeaderSize; - static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; - static const int kBitField3Offset = kInstanceAttributesOffset + kIntSize; - static const int kPrototypeOffset = kBitField3Offset + kPointerSize; - static const int kConstructorOrBackPointerOffset = - kPrototypeOffset + kPointerSize; - // When there is only one transition, it is stored directly in this field; - // otherwise a transition array is used. - // For prototype maps, this slot is used to store this map's PrototypeInfo - // struct. - static const int kTransitionsOrPrototypeInfoOffset = - kConstructorOrBackPointerOffset + kPointerSize; - static const int kDescriptorsOffset = - kTransitionsOrPrototypeInfoOffset + kPointerSize; -#if V8_DOUBLE_FIELDS_UNBOXING - static const int kLayoutDescriptorOffset = kDescriptorsOffset + kPointerSize; - static const int kDependentCodeOffset = - kLayoutDescriptorOffset + kPointerSize; -#else - static const int kLayoutDescriptorOffset = 1; // Must not be ever accessed. - static const int kDependentCodeOffset = kDescriptorsOffset + kPointerSize; -#endif - static const int kWeakCellCacheOffset = kDependentCodeOffset + kPointerSize; - static const int kSize = kWeakCellCacheOffset + kPointerSize; - - // Layout of pointer fields. Heap iteration code relies on them - // being continuously allocated. - static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset; - static const int kPointerFieldsEndOffset = kSize; - - // Byte offsets within kInstanceSizesOffset. - static const int kInstanceSizeOffset = kInstanceSizesOffset + 0; - static const int kInObjectPropertiesOrConstructorFunctionIndexByte = 1; - static const int kInObjectPropertiesOrConstructorFunctionIndexOffset = - kInstanceSizesOffset + kInObjectPropertiesOrConstructorFunctionIndexByte; - // Note there is one byte available for use here. - static const int kUnusedByte = 2; - static const int kUnusedOffset = kInstanceSizesOffset + kUnusedByte; - static const int kVisitorIdByte = 3; - static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte; - -// Byte offsets within kInstanceAttributesOffset attributes. -#if V8_TARGET_LITTLE_ENDIAN - // Order instance type and bit field together such that they can be loaded - // together as a 16-bit word with instance type in the lower 8 bits regardless - // of endianess. Also provide endian-independent offset to that 16-bit word. - static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0; - static const int kBitFieldOffset = kInstanceAttributesOffset + 1; -#else - static const int kBitFieldOffset = kInstanceAttributesOffset + 0; - static const int kInstanceTypeOffset = kInstanceAttributesOffset + 1; -#endif - static const int kInstanceTypeAndBitFieldOffset = - kInstanceAttributesOffset + 0; - static const int kBitField2Offset = kInstanceAttributesOffset + 2; - static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 3; - - STATIC_ASSERT(kInstanceTypeAndBitFieldOffset == - Internals::kMapInstanceTypeAndBitFieldOffset); +#define MAP_FIELDS(V) \ + /* Raw data fields. */ \ + V(kInstanceSizeInWordsOffset, kUInt8Size) \ + V(kInObjectPropertiesStartOrConstructorFunctionIndexOffset, kUInt8Size) \ + V(kUsedOrUnusedInstanceSizeInWordsOffset, kUInt8Size) \ + V(kVisitorIdOffset, kUInt8Size) \ + V(kInstanceTypeOffset, kUInt16Size) \ + V(kBitFieldOffset, kUInt8Size) \ + V(kBitField2Offset, kUInt8Size) \ + V(kBitField3Offset, kUInt32Size) \ + V(k64BitArchPaddingOffset, kPointerSize == kUInt32Size ? 0 : kUInt32Size) \ + /* Pointer fields. */ \ + V(kPointerFieldsBeginOffset, 0) \ + V(kPrototypeOffset, kPointerSize) \ + V(kConstructorOrBackPointerOffset, kPointerSize) \ + V(kTransitionsOrPrototypeInfoOffset, kPointerSize) \ + V(kDescriptorsOffset, kPointerSize) \ + V(kLayoutDescriptorOffset, FLAG_unbox_double_fields ? kPointerSize : 0) \ + V(kDependentCodeOffset, kPointerSize) \ + V(kWeakCellCacheOffset, kPointerSize) \ + V(kPointerFieldsEndOffset, 0) \ + /* Total size. */ \ + V(kSize, 0) + + DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS) +#undef MAP_FIELDS + + STATIC_ASSERT(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); // Bit positions for bit field. static const int kHasNonInstancePrototype = 0; @@ -781,7 +767,7 @@ class Map : public HeapObject { static const int kIsUndetectable = 4; static const int kIsAccessCheckNeeded = 5; static const int kIsConstructor = 6; - // Bit 7 is free. + static const int kHasPrototypeSlot = 7; // Bit positions for bit field 2 static const int kIsExtensible = 0; @@ -789,24 +775,6 @@ class Map : public HeapObject { class IsPrototypeMapBits : public BitField<bool, 2, 1> {}; class ElementsKindBits : public BitField<ElementsKind, 3, 5> {}; - // Derived values from bit field 2 - static const int8_t kMaximumBitField2FastElementValue = - static_cast<int8_t>((PACKED_ELEMENTS + 1) - << Map::ElementsKindBits::kShift) - - 1; - static const int8_t kMaximumBitField2FastSmiElementValue = - static_cast<int8_t>((PACKED_SMI_ELEMENTS + 1) - << Map::ElementsKindBits::kShift) - - 1; - static const int8_t kMaximumBitField2FastHoleyElementValue = - static_cast<int8_t>((HOLEY_ELEMENTS + 1) - << Map::ElementsKindBits::kShift) - - 1; - static const int8_t kMaximumBitField2FastHoleySmiElementValue = - static_cast<int8_t>((HOLEY_SMI_ELEMENTS + 1) - << Map::ElementsKindBits::kShift) - - 1; - typedef FixedBodyDescriptor<kPointerFieldsBeginOffset, kPointerFieldsEndOffset, kSize> BodyDescriptor; @@ -821,10 +789,7 @@ class Map : public HeapObject { // Returns true if given field is unboxed double. inline bool IsUnboxedDoubleField(FieldIndex index) const; -#if V8_TRACE_MAPS - static void TraceTransition(const char* what, Map* from, Map* to, Name* name); - static void TraceAllTransitions(Map* map); -#endif + void PrintMapDetails(std::ostream& os, JSObject* holder = nullptr); static inline Handle<Map> AddMissingTransitionsForTesting( Handle<Map> split_map, Handle<DescriptorArray> descriptors, @@ -848,6 +813,19 @@ class Map : public HeapObject { inline bool CanHaveFastTransitionableElementsKind() const; private: + // This byte encodes either the instance size without the in-object slack or + // the slack size in properties backing store. + // Let H be JSObject::kHeaderSize / kPointerSize. + // If value >= H then: + // - all field properties are stored in the object. + // - there is no property array. + // - value * kPointerSize is the actual object size without the slack. + // Otherwise: + // - there is no slack in the object. + // - the property array has value slack slots. + // Note that this encoding requires that H = JSObject::kFieldsAdded. + DECL_INT_ACCESSORS(used_or_unused_instance_size_in_words) + // 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. Map* LookupElementsTransitionMap(ElementsKind elements_kind); @@ -864,7 +842,8 @@ class Map : public HeapObject { bool EquivalentToForTransition(const Map* other) const; bool EquivalentToForElementsKindTransition(const Map* other) const; - static Handle<Map> RawCopy(Handle<Map> map, int instance_size); + static Handle<Map> RawCopy(Handle<Map> map, int instance_size, + int inobject_properties); static Handle<Map> ShareDescriptor(Handle<Map> map, Handle<DescriptorArray> descriptors, Descriptor* descriptor); @@ -941,7 +920,8 @@ class NormalizedMapCache : public FixedArray { MUST_USE_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map, PropertyNormalizationMode mode); - void Set(Handle<Map> fast_map, Handle<Map> normalized_map); + void Set(Handle<Map> fast_map, Handle<Map> normalized_map, + Handle<WeakCell> normalized_map_weak_cell); void Clear(); |