blob: 0c298d99bf7ed2a0de1015a1f383a1fb5292c34c [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 interceptor_state_(InterceptorState::kUninitialized),
52 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 isolate_(name->GetIsolate()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010054 name_(isolate_->factory()->InternalizeName(name)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 // kMaxUInt32 isn't a valid index.
56 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 receiver_(receiver),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 holder_(GetRoot(isolate_, receiver)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 initial_holder_(holder_),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061#ifdef DEBUG
62 uint32_t index; // Assert that the name is not an array index.
63 DCHECK(!name->AsArrayIndex(&index));
64#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 Next();
66 }
67
68 LookupIterator(Handle<Object> receiver, Handle<Name> name,
69 Handle<JSReceiver> holder,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 Configuration configuration = DEFAULT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 : configuration_(ComputeConfiguration(configuration, name)),
72 state_(NOT_FOUND),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 interceptor_state_(InterceptorState::kUninitialized),
74 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 isolate_(name->GetIsolate()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010076 name_(isolate_->factory()->InternalizeName(name)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 // kMaxUInt32 isn't a valid index.
78 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 receiver_(receiver),
80 holder_(holder),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 initial_holder_(holder_),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083#ifdef DEBUG
84 uint32_t index; // Assert that the name is not an array index.
85 DCHECK(!name->AsArrayIndex(&index));
86#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 Next();
88 }
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
91 Configuration configuration = DEFAULT)
92 : configuration_(configuration),
93 state_(NOT_FOUND),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 interceptor_state_(InterceptorState::kUninitialized),
95 property_details_(PropertyDetails::Empty()),
96 isolate_(isolate),
97 name_(),
98 index_(index),
99 receiver_(receiver),
100 holder_(GetRoot(isolate, receiver, index)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 initial_holder_(holder_),
102 number_(DescriptorArray::kNotFound) {
103 // kMaxUInt32 isn't a valid index.
104 DCHECK_NE(kMaxUInt32, index_);
105 Next();
106 }
107
108 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
109 Handle<JSReceiver> holder,
110 Configuration configuration = DEFAULT)
111 : configuration_(configuration),
112 state_(NOT_FOUND),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 interceptor_state_(InterceptorState::kUninitialized),
114 property_details_(PropertyDetails::Empty()),
115 isolate_(isolate),
116 name_(),
117 index_(index),
118 receiver_(receiver),
119 holder_(holder),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 initial_holder_(holder_),
121 number_(DescriptorArray::kNotFound) {
122 // kMaxUInt32 isn't a valid index.
123 DCHECK_NE(kMaxUInt32, index_);
124 Next();
125 }
126
127 static LookupIterator PropertyOrElement(
128 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
129 Configuration configuration = DEFAULT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 uint32_t index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100131 if (name->AsArrayIndex(&index)) {
132 LookupIterator it =
133 LookupIterator(isolate, receiver, index, configuration);
134 it.name_ = name;
135 return it;
136 }
137 return LookupIterator(receiver, name, configuration);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 }
139
140 static LookupIterator PropertyOrElement(
141 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
142 Handle<JSReceiver> holder, Configuration configuration = DEFAULT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 uint32_t index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100144 if (name->AsArrayIndex(&index)) {
145 LookupIterator it =
146 LookupIterator(isolate, receiver, index, holder, configuration);
147 it.name_ = name;
148 return it;
149 }
150 return LookupIterator(receiver, name, holder, configuration);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 }
152
153 static LookupIterator PropertyOrElement(
154 Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
155 bool* success, Configuration configuration = DEFAULT);
156
157 void Restart() { RestartInternal(InterceptorState::kUninitialized); }
158
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000159 Isolate* isolate() const { return isolate_; }
160 State state() const { return state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161
162 Handle<Name> name() const {
163 DCHECK(!IsElement());
164 return name_;
165 }
166 Handle<Name> GetName() {
167 if (name_.is_null()) {
168 DCHECK(IsElement());
169 name_ = factory()->Uint32ToString(index_);
170 }
171 return name_;
172 }
173 uint32_t index() const { return index_; }
174
175 bool IsElement() const { return index_ != kMaxUInt32; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176
177 bool IsFound() const { return state_ != NOT_FOUND; }
178 void Next();
179 void NotFound() {
180 has_property_ = false;
181 state_ = NOT_FOUND;
182 }
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 Heap* heap() const { return isolate_->heap(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 Factory* factory() const { return isolate_->factory(); }
186 Handle<Object> GetReceiver() const { return receiver_; }
187 Handle<JSObject> GetStoreTarget() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100188 bool is_dictionary_holder() const { return !holder_->HasFastProperties(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 Handle<Map> transition_map() const {
190 DCHECK_EQ(TRANSITION, state_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 return Handle<Map>::cast(transition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 }
193 template <class T>
194 Handle<T> GetHolder() const {
195 DCHECK(IsFound());
196 return Handle<T>::cast(holder_);
197 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 bool HolderIsReceiverOrHiddenPrototype() const;
200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 bool check_prototype_chain() const {
202 return (configuration_ & kPrototypeChain) != 0;
203 }
204
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 /* ACCESS_CHECK */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 bool HasAccess() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207
208 /* PROPERTY */
Ben Murdoch097c5b22016-05-18 11:27:45 +0100209 bool ExtendingNonExtensible(Handle<JSObject> receiver) {
210 DCHECK(receiver.is_identical_to(GetStoreTarget()));
211 return !receiver->map()->is_extensible() &&
212 (IsElement() || !name_->IsPrivate());
213 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 void PrepareForDataProperty(Handle<Object> value);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100215 void PrepareTransitionToDataProperty(Handle<JSObject> receiver,
216 Handle<Object> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 PropertyAttributes attributes,
218 Object::StoreFromKeyed store_mode);
219 bool IsCacheableTransition() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220 DCHECK_EQ(TRANSITION, state_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 return transition_->IsPropertyCell() ||
222 (!transition_map()->is_dictionary_map() &&
223 transition_map()->GetBackPointer()->IsMap());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100225 void ApplyTransitionToDataProperty(Handle<JSObject> receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 void ReconfigureDataProperty(Handle<Object> value,
227 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 void Delete();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 void TransitionToAccessorProperty(AccessorComponent component,
230 Handle<Object> accessor,
231 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 void TransitionToAccessorPair(Handle<Object> pair,
233 PropertyAttributes attributes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 PropertyDetails property_details() const {
235 DCHECK(has_property_);
236 return property_details_;
237 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100238 PropertyAttributes property_attributes() const {
239 return property_details().attributes();
240 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 bool IsConfigurable() const { return property_details().IsConfigurable(); }
242 bool IsReadOnly() const { return property_details().IsReadOnly(); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100243 bool IsEnumerable() const { return property_details().IsEnumerable(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244 Representation representation() const {
245 return property_details().representation();
246 }
247 FieldIndex GetFieldIndex() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100248 Handle<FieldType> GetFieldType() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 int GetAccessorIndex() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250 int GetConstantIndex() const;
251 Handle<PropertyCell> GetPropertyCell() const;
252 Handle<Object> GetAccessors() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 inline Handle<InterceptorInfo> GetInterceptor() const {
254 DCHECK_EQ(INTERCEPTOR, state_);
255 return handle(GetInterceptor(JSObject::cast(*holder_)), isolate_);
256 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 Handle<Object> GetDataValue() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 void WriteDataValue(Handle<Object> value);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100259 void UpdateProtector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260
261 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 enum class InterceptorState {
263 kUninitialized,
264 kSkipNonMasking,
265 kProcessNonMasking
266 };
267
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 Handle<Map> GetReceiverMap() const;
269
270 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
271 inline State LookupInHolder(Map* map, JSReceiver* holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 void RestartLookupForNonMaskingInterceptors() {
273 RestartInternal(InterceptorState::kProcessNonMasking);
274 }
275 void RestartInternal(InterceptorState interceptor_state);
276 State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 Handle<Object> FetchValue() const;
278 void ReloadPropertyInformation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 inline bool SkipInterceptor(JSObject* holder);
280 bool HasInterceptor(Map* map) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 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 {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100291 DCHECK(!IsElement());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292 DCHECK(has_property_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 DCHECK(holder_->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 return number_;
295 }
296 int dictionary_entry() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100297 DCHECK(!IsElement());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 DCHECK(has_property_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299 DCHECK(!holder_->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 return number_;
301 }
302
303 static Configuration ComputeConfiguration(
304 Configuration configuration, Handle<Name> name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 if (name->IsPrivate()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306 return static_cast<Configuration>(configuration &
307 HIDDEN_SKIP_INTERCEPTOR);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 } else {
309 return configuration;
310 }
311 }
312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 static Handle<JSReceiver> GetRootForNonJSReceiver(
314 Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
315 inline static Handle<JSReceiver> GetRoot(Isolate* isolate,
316 Handle<Object> receiver,
317 uint32_t index = kMaxUInt32) {
318 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
319 return GetRootForNonJSReceiver(isolate, receiver, index);
320 }
321
Ben Murdoch097c5b22016-05-18 11:27:45 +0100322 State NotFound(JSReceiver* const holder) const;
323
324 bool HolderIsInContextIndex(uint32_t index) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 // If configuration_ becomes mutable, update
327 // HolderIsReceiverOrHiddenPrototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 const Configuration configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 State state_;
330 bool has_property_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 InterceptorState interceptor_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 PropertyDetails property_details_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 Isolate* const isolate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 Handle<Name> name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 uint32_t index_;
336 Handle<Object> transition_;
337 const Handle<Object> receiver_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 Handle<JSReceiver> holder_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 const Handle<JSReceiver> initial_holder_;
340 uint32_t number_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341};
342
343
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344} // namespace internal
345} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346
347#endif // V8_LOOKUP_H_