Line data Source code
1 : // Copyright 2014 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_LOOKUP_H_
6 : #define V8_LOOKUP_H_
7 :
8 : #include "src/globals.h"
9 : #include "src/heap/factory.h"
10 : #include "src/isolate.h"
11 : #include "src/objects.h"
12 : #include "src/objects/descriptor-array.h"
13 : #include "src/objects/js-objects.h"
14 : #include "src/objects/map.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : class V8_EXPORT_PRIVATE LookupIterator final {
20 : public:
21 : enum Configuration {
22 : // Configuration bits.
23 : kInterceptor = 1 << 0,
24 : kPrototypeChain = 1 << 1,
25 :
26 : // Convenience combinations of bits.
27 : OWN_SKIP_INTERCEPTOR = 0,
28 : OWN = kInterceptor,
29 : PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
30 : PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
31 : DEFAULT = PROTOTYPE_CHAIN
32 : };
33 :
34 : enum State {
35 : ACCESS_CHECK,
36 : INTEGER_INDEXED_EXOTIC,
37 : INTERCEPTOR,
38 : JSPROXY,
39 : NOT_FOUND,
40 : ACCESSOR,
41 : DATA,
42 : TRANSITION,
43 : // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
44 : // PROPERTY lookup.
45 : BEFORE_PROPERTY = INTERCEPTOR
46 : };
47 :
48 : inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
49 : Handle<Name> name,
50 : Configuration configuration = DEFAULT);
51 :
52 : inline LookupIterator(Handle<Object> receiver, Handle<Name> name,
53 : Handle<JSReceiver> holder,
54 : Configuration configuration = DEFAULT);
55 :
56 : inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
57 : Handle<Name> name, Handle<JSReceiver> holder,
58 : Configuration configuration = DEFAULT);
59 :
60 : inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
61 : uint32_t index, Configuration configuration = DEFAULT);
62 :
63 : LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
64 : Handle<JSReceiver> holder,
65 : Configuration configuration = DEFAULT)
66 : : configuration_(configuration),
67 : interceptor_state_(InterceptorState::kUninitialized),
68 : property_details_(PropertyDetails::Empty()),
69 : isolate_(isolate),
70 : receiver_(receiver),
71 : initial_holder_(holder),
72 : index_(index),
73 273639786 : number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
74 : // kMaxUInt32 isn't a valid index.
75 : DCHECK_NE(kMaxUInt32, index_);
76 91213262 : Start<true>();
77 : }
78 :
79 : static inline LookupIterator PropertyOrElement(
80 : Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
81 : Configuration configuration = DEFAULT);
82 :
83 : static inline LookupIterator PropertyOrElement(
84 : Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
85 : Handle<JSReceiver> holder, Configuration configuration = DEFAULT);
86 :
87 : static LookupIterator PropertyOrElement(
88 : Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
89 : bool* success, Handle<JSReceiver> holder,
90 : Configuration configuration = DEFAULT);
91 :
92 : static LookupIterator PropertyOrElement(
93 : Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
94 : bool* success, Configuration configuration = DEFAULT);
95 :
96 : static LookupIterator ForTransitionHandler(
97 : Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
98 : Handle<Object> value, MaybeHandle<Map> maybe_transition_map);
99 :
100 1413727 : void Restart() {
101 : InterceptorState state = InterceptorState::kUninitialized;
102 1413727 : IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
103 1413733 : }
104 :
105 : Isolate* isolate() const { return isolate_; }
106 : State state() const { return state_; }
107 :
108 : Handle<Name> name() const {
109 : DCHECK(!IsElement());
110 : return name_;
111 : }
112 : inline Handle<Name> GetName();
113 : uint32_t index() const { return index_; }
114 :
115 : bool IsElement() const { return index_ != kMaxUInt32; }
116 :
117 6042356 : bool IsFound() const { return state_ != NOT_FOUND; }
118 : void Next();
119 : void NotFound() {
120 537329 : has_property_ = false;
121 537329 : state_ = NOT_FOUND;
122 : }
123 :
124 : Heap* heap() const { return isolate_->heap(); }
125 : Factory* factory() const { return isolate_->factory(); }
126 : Handle<Object> GetReceiver() const { return receiver_; }
127 :
128 : template <class T>
129 : inline Handle<T> GetStoreTarget() const;
130 : inline bool is_dictionary_holder() const;
131 : inline Handle<Map> transition_map() const;
132 : inline Handle<PropertyCell> transition_cell() const;
133 : template <class T>
134 : inline Handle<T> GetHolder() const;
135 :
136 : bool HolderIsReceiver() const;
137 : bool HolderIsReceiverOrHiddenPrototype() const;
138 :
139 : bool check_prototype_chain() const {
140 227591768 : return (configuration_ & kPrototypeChain) != 0;
141 : }
142 :
143 : /* ACCESS_CHECK */
144 : bool HasAccess() const;
145 :
146 : /* PROPERTY */
147 : inline bool ExtendingNonExtensible(Handle<JSReceiver> receiver);
148 : void PrepareForDataProperty(Handle<Object> value);
149 : void PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
150 : Handle<Object> value,
151 : PropertyAttributes attributes,
152 : StoreOrigin store_origin);
153 : inline bool IsCacheableTransition();
154 : void ApplyTransitionToDataProperty(Handle<JSReceiver> receiver);
155 : void ReconfigureDataProperty(Handle<Object> value,
156 : PropertyAttributes attributes);
157 : void Delete();
158 : void TransitionToAccessorProperty(Handle<Object> getter,
159 : Handle<Object> setter,
160 : PropertyAttributes attributes);
161 : void TransitionToAccessorPair(Handle<Object> pair,
162 : PropertyAttributes attributes);
163 : PropertyDetails property_details() const {
164 : DCHECK(has_property_);
165 : return property_details_;
166 : }
167 : PropertyAttributes property_attributes() const {
168 : return property_details().attributes();
169 : }
170 : bool IsConfigurable() const { return property_details().IsConfigurable(); }
171 : bool IsReadOnly() const { return property_details().IsReadOnly(); }
172 : bool IsEnumerable() const { return property_details().IsEnumerable(); }
173 : Representation representation() const {
174 : return property_details().representation();
175 : }
176 : PropertyLocation location() const { return property_details().location(); }
177 : PropertyConstness constness() const { return property_details().constness(); }
178 : Handle<Map> GetFieldOwnerMap() const;
179 : FieldIndex GetFieldIndex() const;
180 : Handle<FieldType> GetFieldType() const;
181 : int GetFieldDescriptorIndex() const;
182 : int GetAccessorIndex() const;
183 : int GetConstantIndex() const;
184 : Handle<PropertyCell> GetPropertyCell() const;
185 : Handle<Object> GetAccessors() const;
186 : inline Handle<InterceptorInfo> GetInterceptor() const;
187 : Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
188 : Handle<Object> GetDataValue() const;
189 : void WriteDataValue(Handle<Object> value, bool initializing_store);
190 : inline void UpdateProtector();
191 :
192 : // Lookup a 'cached' private property for an accessor.
193 : // If not found returns false and leaves the LookupIterator unmodified.
194 : bool TryLookupCachedProperty();
195 : bool LookupCachedProperty();
196 :
197 : private:
198 : // For |ForTransitionHandler|.
199 : LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
200 : Handle<Map> transition_map, PropertyDetails details,
201 : bool has_property);
202 :
203 : void InternalUpdateProtector();
204 :
205 : enum class InterceptorState {
206 : kUninitialized,
207 : kSkipNonMasking,
208 : kProcessNonMasking
209 : };
210 :
211 : Handle<Map> GetReceiverMap() const;
212 :
213 : V8_WARN_UNUSED_RESULT inline JSReceiver NextHolder(Map map);
214 :
215 : template <bool is_element>
216 : V8_EXPORT_PRIVATE void Start();
217 : template <bool is_element>
218 : void NextInternal(Map map, JSReceiver holder);
219 : template <bool is_element>
220 370897171 : inline State LookupInHolder(Map map, JSReceiver holder) {
221 : return map->IsSpecialReceiverMap()
222 : ? LookupInSpecialHolder<is_element>(map, holder)
223 370897171 : : LookupInRegularHolder<is_element>(map, holder);
224 : }
225 : template <bool is_element>
226 : State LookupInRegularHolder(Map map, JSReceiver holder);
227 : template <bool is_element>
228 : State LookupInSpecialHolder(Map map, JSReceiver holder);
229 : template <bool is_element>
230 156 : void RestartLookupForNonMaskingInterceptors() {
231 156 : RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
232 156 : }
233 : template <bool is_element>
234 : void RestartInternal(InterceptorState interceptor_state);
235 : Handle<Object> FetchValue() const;
236 : bool IsConstFieldValueEqualTo(Object value) const;
237 : template <bool is_element>
238 : void ReloadPropertyInformation();
239 :
240 : template <bool is_element>
241 : bool SkipInterceptor(JSObject holder);
242 : template <bool is_element>
243 : static inline InterceptorInfo GetInterceptor(JSObject holder);
244 :
245 : bool check_interceptor() const {
246 40217392 : return (configuration_ & kInterceptor) != 0;
247 : }
248 : inline int descriptor_number() const;
249 : inline int dictionary_entry() const;
250 :
251 : static inline Configuration ComputeConfiguration(
252 : Configuration configuration, Handle<Name> name);
253 :
254 : static Handle<JSReceiver> GetRootForNonJSReceiver(
255 : Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
256 : static inline Handle<JSReceiver> GetRoot(Isolate* isolate,
257 : Handle<Object> receiver,
258 : uint32_t index = kMaxUInt32);
259 :
260 : State NotFound(JSReceiver const holder) const;
261 :
262 : // If configuration_ becomes mutable, update
263 : // HolderIsReceiverOrHiddenPrototype.
264 : const Configuration configuration_;
265 : State state_;
266 : bool has_property_;
267 : InterceptorState interceptor_state_;
268 : PropertyDetails property_details_;
269 : Isolate* const isolate_;
270 : Handle<Name> name_;
271 : Handle<Object> transition_;
272 : const Handle<Object> receiver_;
273 : Handle<JSReceiver> holder_;
274 : const Handle<JSReceiver> initial_holder_;
275 : const uint32_t index_;
276 : uint32_t number_;
277 : };
278 :
279 :
280 : } // namespace internal
281 : } // namespace v8
282 :
283 : #endif // V8_LOOKUP_H_
|