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 class DescriptorArray : public FixedArray {
48  public:
49   // Returns the number of descriptors in the array.
50   inline int number_of_descriptors() const;
51   inline int number_of_descriptors_storage() const;
52   inline int NumberOfSlackDescriptors() const;
53 
54   inline void SetNumberOfDescriptors(int number_of_descriptors);
55   inline int number_of_entries() const;
56 
57   inline EnumCache* GetEnumCache();
58 
59   void ClearEnumCache();
60   inline void CopyEnumCacheFrom(DescriptorArray* array);
61   // Initialize or change the enum cache,
62   static void SetEnumCache(Handle<DescriptorArray> descriptors,
63                            Isolate* isolate, Handle<FixedArray> keys,
64                            Handle<FixedArray> indices);
65 
66   // Accessors for fetching instance descriptor at descriptor number.
67   inline Name* GetKey(int descriptor_number);
68   inline Object** GetKeySlot(int descriptor_number);
69   inline Object* GetValue(int descriptor_number);
70   inline void SetValue(int descriptor_number, Object* value);
71   inline Object** GetValueSlot(int descriptor_number);
72   static inline int GetValueOffset(int descriptor_number);
73   inline Object** GetDescriptorStartSlot(int descriptor_number);
74   inline Object** GetDescriptorEndSlot(int descriptor_number);
75   inline PropertyDetails GetDetails(int descriptor_number);
76   inline int GetFieldIndex(int descriptor_number);
77   inline FieldType* GetFieldType(int descriptor_number);
78 
79   inline Name* GetSortedKey(int descriptor_number);
80   inline int GetSortedKeyIndex(int descriptor_number);
81   inline void SetSortedKey(int pointer, int descriptor_number);
82 
83   // Accessor for complete descriptor.
84   inline void Get(int descriptor_number, Descriptor* desc);
85   inline void Set(int descriptor_number, Descriptor* desc);
86   inline void Set(int descriptor_number, Name* key, Object* value,
87                   PropertyDetails details);
88   void Replace(int descriptor_number, Descriptor* descriptor);
89 
90   // Generalizes constness, representation and field type of all field
91   // descriptors.
92   void GeneralizeAllFields();
93 
94   // Append automatically sets the enumeration index. This should only be used
95   // to add descriptors in bulk at the end, followed by sorting the descriptor
96   // array.
97   inline void Append(Descriptor* desc);
98 
99   static Handle<DescriptorArray> CopyUpTo(Handle<DescriptorArray> desc,
100                                           int enumeration_index, int slack = 0);
101 
102   static Handle<DescriptorArray> CopyUpToAddAttributes(
103       Handle<DescriptorArray> desc, int enumeration_index,
104       PropertyAttributes attributes, int slack = 0);
105 
106   // Sort the instance descriptors by the hash codes of their keys.
107   void Sort();
108 
109   // Search the instance descriptors for given name.
110   INLINE(int Search(Name* name, int number_of_own_descriptors));
111 
112   // As the above, but uses DescriptorLookupCache and updates it when
113   // necessary.
114   INLINE(int SearchWithCache(Isolate* isolate, Name* name, Map* map));
115 
116   bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors);
117 
118   // Allocates a DescriptorArray, but returns the singleton
119   // empty descriptor array object if number_of_descriptors is 0.
120   static Handle<DescriptorArray> Allocate(
121       Isolate* isolate, int number_of_descriptors, int slack,
122       PretenureFlag pretenure = NOT_TENURED);
123 
124   DECL_CAST(DescriptorArray)
125 
126   // Constant for denoting key was not found.
127   static const int kNotFound = -1;
128 
129   static const int kDescriptorLengthIndex = 0;
130   static const int kEnumCacheIndex = 1;
131   static const int kFirstIndex = 2;
132 
133   // Layout description.
134   static const int kDescriptorLengthOffset = FixedArray::kHeaderSize;
135   static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize;
136   static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
137 
138   // Layout of descriptor.
139   // Naming is consistent with Dictionary classes for easy templating.
140   static const int kEntryKeyIndex = 0;
141   static const int kEntryDetailsIndex = 1;
142   static const int kEntryValueIndex = 2;
143   static const int kEntrySize = 3;
144 
145   // Print all the descriptors.
146   void PrintDescriptors(std::ostream& os);
147   void PrintDescriptorDetails(std::ostream& os, int descriptor,
148                               PropertyDetails::PrintMode mode);
149 
150 #if defined(DEBUG) || defined(OBJECT_PRINT)
151   // For our gdb macros, we should perhaps change these in the future.
152   void Print();
153   void DescriptorArrayPrint(std::ostream& os);
154 #endif
155 
156   DECL_VERIFIER(DescriptorArray)
157 
158 #ifdef DEBUG
159   // Is the descriptor array sorted and without duplicates?
160   bool IsSortedNoDuplicates(int valid_descriptors = -1);
161 
162   // Are two DescriptorArrays equal?
163   bool IsEqualTo(DescriptorArray* other);
164 #endif
165 
166   // Returns the fixed array length required to hold number_of_descriptors
167   // descriptors.
LengthFor(int number_of_descriptors)168   static constexpr int LengthFor(int number_of_descriptors) {
169     return ToKeyIndex(number_of_descriptors);
170   }
171 
ToDetailsIndex(int descriptor_number)172   static constexpr int ToDetailsIndex(int descriptor_number) {
173     return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex;
174   }
175 
176   // Conversion from descriptor number to array indices.
ToKeyIndex(int descriptor_number)177   static constexpr int ToKeyIndex(int descriptor_number) {
178     return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex;
179   }
180 
ToValueIndex(int descriptor_number)181   static constexpr int ToValueIndex(int descriptor_number) {
182     return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex;
183   }
184 
185  private:
186   // Transfer a complete descriptor from the src descriptor array to this
187   // descriptor array.
188   void CopyFrom(int index, DescriptorArray* src);
189 
190   // Swap first and second descriptor.
191   inline void SwapSortedKeys(int first, int second);
192 
193   DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
194 };
195 
196 }  // namespace internal
197 }  // namespace v8
198 
199 #include "src/objects/object-macros-undef.h"
200 
201 #endif  // V8_OBJECTS_DESCRIPTOR_ARRAY_H_
202