blob: 7d689560b8f7efa5d106d1018fd42c26faa3e9cb [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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/factory.h"
9#include "src/isolate.h"
10#include "src/objects.h"
11
12namespace v8 {
13namespace internal {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015class LookupIterator final BASE_EMBEDDED {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016 public:
17 enum Configuration {
18 // Configuration bits.
19 kHidden = 1 << 0,
20 kInterceptor = 1 << 1,
21 kPrototypeChain = 1 << 2,
22
23 // Convience combinations of bits.
24 OWN_SKIP_INTERCEPTOR = 0,
25 OWN = kInterceptor,
26 HIDDEN_SKIP_INTERCEPTOR = kHidden,
27 HIDDEN = kHidden | kInterceptor,
28 PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029 PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor,
30 DEFAULT = PROTOTYPE_CHAIN
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 };
32
33 enum State {
34 ACCESS_CHECK,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 INTEGER_INDEXED_EXOTIC,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036 INTERCEPTOR,
37 JSPROXY,
38 NOT_FOUND,
39 ACCESSOR,
40 DATA,
41 TRANSITION,
42 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
43 // PROPERTY lookup.
44 BEFORE_PROPERTY = INTERCEPTOR
45 };
46
47 LookupIterator(Handle<Object> receiver, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 Configuration configuration = DEFAULT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 : configuration_(ComputeConfiguration(configuration, name)),
50 state_(NOT_FOUND),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 exotic_index_state_(ExoticIndexState::kUninitialized),
52 interceptor_state_(InterceptorState::kUninitialized),
53 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 isolate_(name->GetIsolate()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 name_(Name::Flatten(name)),
56 // kMaxUInt32 isn't a valid index.
57 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 receiver_(receiver),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 holder_(GetRoot(isolate_, receiver)),
60 holder_map_(holder_->map(), isolate_),
61 initial_holder_(holder_),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063#ifdef DEBUG
64 uint32_t index; // Assert that the name is not an array index.
65 DCHECK(!name->AsArrayIndex(&index));
66#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 Next();
68 }
69
70 LookupIterator(Handle<Object> receiver, Handle<Name> name,
71 Handle<JSReceiver> holder,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 Configuration configuration = DEFAULT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 : configuration_(ComputeConfiguration(configuration, name)),
74 state_(NOT_FOUND),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 exotic_index_state_(ExoticIndexState::kUninitialized),
76 interceptor_state_(InterceptorState::kUninitialized),
77 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 isolate_(name->GetIsolate()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079 name_(Name::Flatten(name)),
80 // kMaxUInt32 isn't a valid index.
81 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 receiver_(receiver),
83 holder_(holder),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 holder_map_(holder_->map(), isolate_),
85 initial_holder_(holder_),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087#ifdef DEBUG
88 uint32_t index; // Assert that the name is not an array index.
89 DCHECK(!name->AsArrayIndex(&index));
90#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 Next();
92 }
93
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
95 Configuration configuration = DEFAULT)
96 : configuration_(configuration),
97 state_(NOT_FOUND),
98 exotic_index_state_(ExoticIndexState::kUninitialized),
99 interceptor_state_(InterceptorState::kUninitialized),
100 property_details_(PropertyDetails::Empty()),
101 isolate_(isolate),
102 name_(),
103 index_(index),
104 receiver_(receiver),
105 holder_(GetRoot(isolate, receiver, index)),
106 holder_map_(holder_->map(), isolate_),
107 initial_holder_(holder_),
108 number_(DescriptorArray::kNotFound) {
109 // kMaxUInt32 isn't a valid index.
110 DCHECK_NE(kMaxUInt32, index_);
111 Next();
112 }
113
114 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
115 Handle<JSReceiver> holder,
116 Configuration configuration = DEFAULT)
117 : configuration_(configuration),
118 state_(NOT_FOUND),
119 exotic_index_state_(ExoticIndexState::kUninitialized),
120 interceptor_state_(InterceptorState::kUninitialized),
121 property_details_(PropertyDetails::Empty()),
122 isolate_(isolate),
123 name_(),
124 index_(index),
125 receiver_(receiver),
126 holder_(holder),
127 holder_map_(holder_->map(), isolate_),
128 initial_holder_(holder_),
129 number_(DescriptorArray::kNotFound) {
130 // kMaxUInt32 isn't a valid index.
131 DCHECK_NE(kMaxUInt32, index_);
132 Next();
133 }
134
135 static LookupIterator PropertyOrElement(
136 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
137 Configuration configuration = DEFAULT) {
138 name = Name::Flatten(name);
139 uint32_t index;
140 LookupIterator it =
141 name->AsArrayIndex(&index)
142 ? LookupIterator(isolate, receiver, index, configuration)
143 : LookupIterator(receiver, name, configuration);
144 it.name_ = name;
145 return it;
146 }
147
148 static LookupIterator PropertyOrElement(
149 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
150 Handle<JSReceiver> holder, Configuration configuration = DEFAULT) {
151 name = Name::Flatten(name);
152 uint32_t index;
153 LookupIterator it =
154 name->AsArrayIndex(&index)
155 ? LookupIterator(isolate, receiver, index, holder, configuration)
156 : LookupIterator(receiver, name, holder, configuration);
157 it.name_ = name;
158 return it;
159 }
160
161 static LookupIterator PropertyOrElement(
162 Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
163 bool* success, Configuration configuration = DEFAULT);
164
165 void Restart() { RestartInternal(InterceptorState::kUninitialized); }
166
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 Isolate* isolate() const { return isolate_; }
168 State state() const { return state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169
170 Handle<Name> name() const {
171 DCHECK(!IsElement());
172 return name_;
173 }
174 Handle<Name> GetName() {
175 if (name_.is_null()) {
176 DCHECK(IsElement());
177 name_ = factory()->Uint32ToString(index_);
178 }
179 return name_;
180 }
181 uint32_t index() const { return index_; }
182
183 bool IsElement() const { return index_ != kMaxUInt32; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184
185 bool IsFound() const { return state_ != NOT_FOUND; }
186 void Next();
187 void NotFound() {
188 has_property_ = false;
189 state_ = NOT_FOUND;
190 }
191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 Heap* heap() const { return isolate_->heap(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 Factory* factory() const { return isolate_->factory(); }
194 Handle<Object> GetReceiver() const { return receiver_; }
195 Handle<JSObject> GetStoreTarget() const;
196 bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
197 Handle<Map> transition_map() const {
198 DCHECK_EQ(TRANSITION, state_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 return Handle<Map>::cast(transition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 }
201 template <class T>
202 Handle<T> GetHolder() const {
203 DCHECK(IsFound());
204 return Handle<T>::cast(holder_);
205 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 bool HolderIsReceiverOrHiddenPrototype() const;
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 bool check_prototype_chain() const {
210 return (configuration_ & kPrototypeChain) != 0;
211 }
212
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 /* ACCESS_CHECK */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 bool HasAccess() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215
216 /* PROPERTY */
217 void PrepareForDataProperty(Handle<Object> value);
218 void PrepareTransitionToDataProperty(Handle<Object> value,
219 PropertyAttributes attributes,
220 Object::StoreFromKeyed store_mode);
221 bool IsCacheableTransition() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 if (state_ != TRANSITION) return false;
223 return transition_->IsPropertyCell() ||
224 (!transition_map()->is_dictionary_map() &&
225 transition_map()->GetBackPointer()->IsMap());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 }
227 void ApplyTransitionToDataProperty();
228 void ReconfigureDataProperty(Handle<Object> value,
229 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 void Delete();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 void TransitionToAccessorProperty(AccessorComponent component,
232 Handle<Object> accessor,
233 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 void TransitionToAccessorPair(Handle<Object> pair,
235 PropertyAttributes attributes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 PropertyDetails property_details() const {
237 DCHECK(has_property_);
238 return property_details_;
239 }
240 bool IsConfigurable() const { return property_details().IsConfigurable(); }
241 bool IsReadOnly() const { return property_details().IsReadOnly(); }
242 Representation representation() const {
243 return property_details().representation();
244 }
245 FieldIndex GetFieldIndex() const;
246 Handle<HeapType> GetFieldType() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 int GetAccessorIndex() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248 int GetConstantIndex() const;
249 Handle<PropertyCell> GetPropertyCell() const;
250 Handle<Object> GetAccessors() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 inline Handle<InterceptorInfo> GetInterceptor() const {
252 DCHECK_EQ(INTERCEPTOR, state_);
253 return handle(GetInterceptor(JSObject::cast(*holder_)), isolate_);
254 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 Handle<Object> GetDataValue() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 void WriteDataValue(Handle<Object> value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 void InternalizeName();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 void ReloadHolderMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259
260 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 enum class InterceptorState {
262 kUninitialized,
263 kSkipNonMasking,
264 kProcessNonMasking
265 };
266
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 Handle<Map> GetReceiverMap() const;
268
269 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
270 inline State LookupInHolder(Map* map, JSReceiver* holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 void RestartLookupForNonMaskingInterceptors() {
272 RestartInternal(InterceptorState::kProcessNonMasking);
273 }
274 void RestartInternal(InterceptorState interceptor_state);
275 State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 Handle<Object> FetchValue() const;
277 void ReloadPropertyInformation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 inline bool SkipInterceptor(JSObject* holder);
279 bool HasInterceptor(Map* map) const;
280 bool InternalHolderIsReceiverOrHiddenPrototype() const;
281 inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
282 if (IsElement()) return holder->GetIndexedInterceptor();
283 return holder->GetNamedInterceptor();
284 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285
286 bool check_hidden() const { return (configuration_ & kHidden) != 0; }
287 bool check_interceptor() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 return (configuration_ & kInterceptor) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 }
290 int descriptor_number() const {
291 DCHECK(has_property_);
292 DCHECK(!holder_map_->is_dictionary_map());
293 return number_;
294 }
295 int dictionary_entry() const {
296 DCHECK(has_property_);
297 DCHECK(holder_map_->is_dictionary_map());
298 return number_;
299 }
300
301 static Configuration ComputeConfiguration(
302 Configuration configuration, Handle<Name> name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 if (name->IsPrivate()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304 return static_cast<Configuration>(configuration &
305 HIDDEN_SKIP_INTERCEPTOR);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 } else {
307 return configuration;
308 }
309 }
310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 static Handle<JSReceiver> GetRootForNonJSReceiver(
312 Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
313 inline static Handle<JSReceiver> GetRoot(Isolate* isolate,
314 Handle<Object> receiver,
315 uint32_t index = kMaxUInt32) {
316 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
317 return GetRootForNonJSReceiver(isolate, receiver, index);
318 }
319
320 enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic };
321 inline bool IsIntegerIndexedExotic(JSReceiver* holder);
322
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 // If configuration_ becomes mutable, update
324 // HolderIsReceiverOrHiddenPrototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325 const Configuration configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 State state_;
327 bool has_property_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 ExoticIndexState exotic_index_state_;
329 InterceptorState interceptor_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330 PropertyDetails property_details_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 Isolate* const isolate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 Handle<Name> name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 uint32_t index_;
334 Handle<Object> transition_;
335 const Handle<Object> receiver_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 Handle<JSReceiver> holder_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 Handle<Map> holder_map_;
338 const Handle<JSReceiver> initial_holder_;
339 uint32_t number_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340};
341
342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343} // namespace internal
344} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345
346#endif // V8_LOOKUP_H_