| // Copyright 2017 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_H_ | |
| #define V8_OBJECTS_DESCRIPTOR_ARRAY_H_ | |
| #include "src/objects.h" | |
| #include "src/objects/fixed-array.h" | |
| // Has to be the last include (doesn't have include guards): | |
| #include "src/objects/object-macros.h" | |
| namespace v8 { | |
| namespace internal { | |
| template <typename T> | |
| class Handle; | |
| class Isolate; | |
| // An EnumCache is a pair used to hold keys and indices caches. | |
| class EnumCache : public Tuple2 { | |
| public: | |
| DECL_ACCESSORS(keys, FixedArray) | |
| DECL_ACCESSORS(indices, FixedArray) | |
| DECL_CAST(EnumCache) | |
| // Layout description. | |
| static const int kKeysOffset = kValue1Offset; | |
| static const int kIndicesOffset = kValue2Offset; | |
| private: | |
| DISALLOW_IMPLICIT_CONSTRUCTORS(EnumCache); | |
| }; | |
| // A DescriptorArray is a fixed array used to hold instance descriptors. | |
| // The format of these objects is: | |
| // [0]: Number of descriptors | |
| // [1]: Enum cache. | |
| // [2]: first key (and internalized String) | |
| // [3]: first descriptor details (see PropertyDetails) | |
| // [4]: first value for constants | Smi(1) when not used | |
| // | |
| // [2 + number of descriptors * 3]: start of slack | |
| // The "value" fields store either values or field types. A field type is either | |
| // FieldType::None(), FieldType::Any() or a weak reference to a Map. All other | |
| // references are strong. | |
| class DescriptorArray : public WeakFixedArray { | |
| public: | |
| // Returns the number of descriptors in the array. | |
| inline int number_of_descriptors() const; | |
| inline int number_of_descriptors_storage() const; | |
| inline int NumberOfSlackDescriptors() const; | |
| inline void SetNumberOfDescriptors(int number_of_descriptors); | |
| inline int number_of_entries() const; | |
| inline EnumCache* GetEnumCache(); | |
| void ClearEnumCache(); | |
| inline void CopyEnumCacheFrom(DescriptorArray* array); | |
| // Initialize or change the enum cache, | |
| static void SetEnumCache(Handle<DescriptorArray> descriptors, | |
| Isolate* isolate, Handle<FixedArray> keys, | |
| Handle<FixedArray> indices); | |
| // Accessors for fetching instance descriptor at descriptor number. | |
| inline Name* GetKey(int descriptor_number); | |
| inline Object** GetKeySlot(int descriptor_number); | |
| inline Object* GetStrongValue(int descriptor_number); | |
| inline void SetValue(int descriptor_number, Object* value); | |
| inline MaybeObject* GetValue(int descriptor_number); | |
| inline MaybeObject** GetValueSlot(int descriptor_number); | |
| static inline int GetValueOffset(int descriptor_number); | |
| inline MaybeObject** GetDescriptorStartSlot(int descriptor_number); | |
| inline MaybeObject** GetDescriptorEndSlot(int descriptor_number); | |
| inline PropertyDetails GetDetails(int descriptor_number); | |
| inline int GetFieldIndex(int descriptor_number); | |
| inline FieldType* GetFieldType(int descriptor_number); | |
| inline Name* GetSortedKey(int descriptor_number); | |
| inline int GetSortedKeyIndex(int descriptor_number); | |
| inline void SetSortedKey(int pointer, int descriptor_number); | |
| // Accessor for complete descriptor. | |
| inline void Set(int descriptor_number, Descriptor* desc); | |
| inline void Set(int descriptor_number, Name* key, MaybeObject* value, | |
| PropertyDetails details); | |
| void Replace(int descriptor_number, Descriptor* descriptor); | |
| // Generalizes constness, representation and field type of all field | |
| // descriptors. | |
| void GeneralizeAllFields(); | |
| // Append automatically sets the enumeration index. This should only be used | |
| // to add descriptors in bulk at the end, followed by sorting the descriptor | |
| // array. | |
| inline void Append(Descriptor* desc); | |
| static Handle<DescriptorArray> CopyUpTo(Isolate* isolate, | |
| Handle<DescriptorArray> desc, | |
| int enumeration_index, int slack = 0); | |
| static Handle<DescriptorArray> CopyUpToAddAttributes( | |
| Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, | |
| PropertyAttributes attributes, int slack = 0); | |
| static Handle<DescriptorArray> CopyForFastObjectClone( | |
| Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, | |
| int slack = 0); | |
| // Sort the instance descriptors by the hash codes of their keys. | |
| void Sort(); | |
| // Search the instance descriptors for given name. | |
| V8_INLINE int Search(Name* name, int number_of_own_descriptors); | |
| V8_INLINE int Search(Name* name, Map* map); | |
| // As the above, but uses DescriptorLookupCache and updates it when | |
| // necessary. | |
| V8_INLINE int SearchWithCache(Isolate* isolate, Name* name, Map* map); | |
| bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors); | |
| // Allocates a DescriptorArray, but returns the singleton | |
| // empty descriptor array object if number_of_descriptors is 0. | |
| static Handle<DescriptorArray> Allocate( | |
| Isolate* isolate, int number_of_descriptors, int slack, | |
| PretenureFlag pretenure = NOT_TENURED); | |
| DECL_CAST(DescriptorArray) | |
| // Constant for denoting key was not found. | |
| static const int kNotFound = -1; | |
| static const int kDescriptorLengthIndex = 0; | |
| static const int kEnumCacheIndex = 1; | |
| static const int kFirstIndex = 2; | |
| // Layout description. | |
| static const int kDescriptorLengthOffset = FixedArray::kHeaderSize; | |
| static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize; | |
| static const int kFirstOffset = kEnumCacheOffset + kPointerSize; | |
| // Layout of descriptor. | |
| // Naming is consistent with Dictionary classes for easy templating. | |
| static const int kEntryKeyIndex = 0; | |
| static const int kEntryDetailsIndex = 1; | |
| static const int kEntryValueIndex = 2; | |
| static const int kEntrySize = 3; | |
| // Print all the descriptors. | |
| void PrintDescriptors(std::ostream& os); | |
| void PrintDescriptorDetails(std::ostream& os, int descriptor, | |
| PropertyDetails::PrintMode mode); | |
| DECL_PRINTER(DescriptorArray) | |
| DECL_VERIFIER(DescriptorArray) | |
| #ifdef DEBUG | |
| // Is the descriptor array sorted and without duplicates? | |
| bool IsSortedNoDuplicates(int valid_descriptors = -1); | |
| // Are two DescriptorArrays equal? | |
| bool IsEqualTo(DescriptorArray* other); | |
| #endif | |
| // Returns the fixed array length required to hold number_of_descriptors | |
| // descriptors. | |
| static constexpr int LengthFor(int number_of_descriptors) { | |
| return ToKeyIndex(number_of_descriptors); | |
| } | |
| static constexpr int ToDetailsIndex(int descriptor_number) { | |
| return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex; | |
| } | |
| // Conversion from descriptor number to array indices. | |
| static constexpr int ToKeyIndex(int descriptor_number) { | |
| return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex; | |
| } | |
| static constexpr int ToValueIndex(int descriptor_number) { | |
| return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex; | |
| } | |
| private: | |
| inline MaybeObject* get(int index) const; | |
| inline void set(int index, MaybeObject* value); | |
| // Transfer a complete descriptor from the src descriptor array to this | |
| // descriptor array. | |
| void CopyFrom(int index, DescriptorArray* src); | |
| // Swap first and second descriptor. | |
| inline void SwapSortedKeys(int first, int second); | |
| DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); | |
| }; | |
| } // namespace internal | |
| } // namespace v8 | |
| #include "src/objects/object-macros-undef.h" | |
| #endif // V8_OBJECTS_DESCRIPTOR_ARRAY_H_ |