1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 6 #define V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 7 8 #include "src/objects.h" 9 #include "src/objects/fixed-array.h" 10 11 // Has to be the last include (doesn't have include guards): 12 #include "src/objects/object-macros.h" 13 14 namespace v8 { 15 namespace internal { 16 17 template <typename T> 18 class Handle; 19 20 class Isolate; 21 22 // An EnumCache is a pair used to hold keys and indices caches. 23 class EnumCache : public Tuple2 { 24 public: 25 DECL_ACCESSORS(keys, FixedArray) 26 DECL_ACCESSORS(indices, FixedArray) 27 28 DECL_CAST(EnumCache) 29 30 // Layout description. 31 static const int kKeysOffset = kValue1Offset; 32 static const int kIndicesOffset = kValue2Offset; 33 34 private: 35 DISALLOW_IMPLICIT_CONSTRUCTORS(EnumCache); 36 }; 37 38 // A DescriptorArray is a fixed array used to hold instance descriptors. 39 // The format of these objects is: 40 // [0]: Number of descriptors 41 // [1]: Enum cache. 42 // [2]: first key (and internalized String) 43 // [3]: first descriptor details (see PropertyDetails) 44 // [4]: first value for constants | Smi(1) when not used 45 // 46 // [2 + number of descriptors * 3]: start of slack 47 // The "value" fields store either values or field types. A field type is either 48 // FieldType::None(), FieldType::Any() or a weak reference to a Map. All other 49 // references are strong. 50 class DescriptorArray : public WeakFixedArray { 51 public: 52 // Returns the number of descriptors in the array. 53 inline int number_of_descriptors() const; 54 inline int number_of_descriptors_storage() const; 55 inline int NumberOfSlackDescriptors() const; 56 57 inline void SetNumberOfDescriptors(int number_of_descriptors); 58 inline int number_of_entries() const; 59 60 inline EnumCache* GetEnumCache(); 61 62 void ClearEnumCache(); 63 inline void CopyEnumCacheFrom(DescriptorArray* array); 64 // Initialize or change the enum cache, 65 static void SetEnumCache(Handle<DescriptorArray> descriptors, 66 Isolate* isolate, Handle<FixedArray> keys, 67 Handle<FixedArray> indices); 68 69 // Accessors for fetching instance descriptor at descriptor number. 70 inline Name* GetKey(int descriptor_number); 71 inline Object** GetKeySlot(int descriptor_number); 72 inline Object* GetStrongValue(int descriptor_number); 73 inline void SetValue(int descriptor_number, Object* value); 74 inline MaybeObject* GetValue(int descriptor_number); 75 inline MaybeObject** GetValueSlot(int descriptor_number); 76 static inline int GetValueOffset(int descriptor_number); 77 inline MaybeObject** GetDescriptorStartSlot(int descriptor_number); 78 inline MaybeObject** GetDescriptorEndSlot(int descriptor_number); 79 inline PropertyDetails GetDetails(int descriptor_number); 80 inline int GetFieldIndex(int descriptor_number); 81 inline FieldType* GetFieldType(int descriptor_number); 82 83 inline Name* GetSortedKey(int descriptor_number); 84 inline int GetSortedKeyIndex(int descriptor_number); 85 inline void SetSortedKey(int pointer, int descriptor_number); 86 87 // Accessor for complete descriptor. 88 inline void Set(int descriptor_number, Descriptor* desc); 89 inline void Set(int descriptor_number, Name* key, MaybeObject* value, 90 PropertyDetails details); 91 void Replace(int descriptor_number, Descriptor* descriptor); 92 93 // Generalizes constness, representation and field type of all field 94 // descriptors. 95 void GeneralizeAllFields(); 96 97 // Append automatically sets the enumeration index. This should only be used 98 // to add descriptors in bulk at the end, followed by sorting the descriptor 99 // array. 100 inline void Append(Descriptor* desc); 101 102 static Handle<DescriptorArray> CopyUpTo(Isolate* isolate, 103 Handle<DescriptorArray> desc, 104 int enumeration_index, int slack = 0); 105 106 static Handle<DescriptorArray> CopyUpToAddAttributes( 107 Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, 108 PropertyAttributes attributes, int slack = 0); 109 110 static Handle<DescriptorArray> CopyForFastObjectClone( 111 Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, 112 int slack = 0); 113 114 // Sort the instance descriptors by the hash codes of their keys. 115 void Sort(); 116 117 // Search the instance descriptors for given name. 118 V8_INLINE int Search(Name* name, int number_of_own_descriptors); 119 V8_INLINE int Search(Name* name, Map* map); 120 121 // As the above, but uses DescriptorLookupCache and updates it when 122 // necessary. 123 V8_INLINE int SearchWithCache(Isolate* isolate, Name* name, Map* map); 124 125 bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors); 126 127 // Allocates a DescriptorArray, but returns the singleton 128 // empty descriptor array object if number_of_descriptors is 0. 129 static Handle<DescriptorArray> Allocate( 130 Isolate* isolate, int number_of_descriptors, int slack, 131 PretenureFlag pretenure = NOT_TENURED); 132 133 DECL_CAST(DescriptorArray) 134 135 // Constant for denoting key was not found. 136 static const int kNotFound = -1; 137 138 static const int kDescriptorLengthIndex = 0; 139 static const int kEnumCacheIndex = 1; 140 static const int kFirstIndex = 2; 141 142 // Layout description. 143 static const int kDescriptorLengthOffset = FixedArray::kHeaderSize; 144 static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize; 145 static const int kFirstOffset = kEnumCacheOffset + kPointerSize; 146 147 // Layout of descriptor. 148 // Naming is consistent with Dictionary classes for easy templating. 149 static const int kEntryKeyIndex = 0; 150 static const int kEntryDetailsIndex = 1; 151 static const int kEntryValueIndex = 2; 152 static const int kEntrySize = 3; 153 154 // Print all the descriptors. 155 void PrintDescriptors(std::ostream& os); 156 void PrintDescriptorDetails(std::ostream& os, int descriptor, 157 PropertyDetails::PrintMode mode); 158 159 DECL_PRINTER(DescriptorArray) 160 DECL_VERIFIER(DescriptorArray) 161 162 #ifdef DEBUG 163 // Is the descriptor array sorted and without duplicates? 164 bool IsSortedNoDuplicates(int valid_descriptors = -1); 165 166 // Are two DescriptorArrays equal? 167 bool IsEqualTo(DescriptorArray* other); 168 #endif 169 170 // Returns the fixed array length required to hold number_of_descriptors 171 // descriptors. LengthFor(int number_of_descriptors)172 static constexpr int LengthFor(int number_of_descriptors) { 173 return ToKeyIndex(number_of_descriptors); 174 } 175 ToDetailsIndex(int descriptor_number)176 static constexpr int ToDetailsIndex(int descriptor_number) { 177 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex; 178 } 179 180 // Conversion from descriptor number to array indices. ToKeyIndex(int descriptor_number)181 static constexpr int ToKeyIndex(int descriptor_number) { 182 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex; 183 } 184 ToValueIndex(int descriptor_number)185 static constexpr int ToValueIndex(int descriptor_number) { 186 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex; 187 } 188 189 private: 190 inline MaybeObject* get(int index) const; 191 inline void set(int index, MaybeObject* value); 192 193 // Transfer a complete descriptor from the src descriptor array to this 194 // descriptor array. 195 void CopyFrom(int index, DescriptorArray* src); 196 197 // Swap first and second descriptor. 198 inline void SwapSortedKeys(int first, int second); 199 200 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); 201 }; 202 203 } // namespace internal 204 } // namespace v8 205 206 #include "src/objects/object-macros-undef.h" 207 208 #endif // V8_OBJECTS_DESCRIPTOR_ARRAY_H_ 209