1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
// 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);
// 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_
|