blob: f1a1b7cf354c37ae9f4c2dd854af2f48f6633c3e [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.
Ben Murdochc5610432016-08-08 18:44:38 +010019 kInterceptor = 1 << 0,
20 kPrototypeChain = 1 << 1,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021
22 // Convience combinations of bits.
23 OWN_SKIP_INTERCEPTOR = 0,
24 OWN = kInterceptor,
Ben Murdochc5610432016-08-08 18:44:38 +010025 PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
26 PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027 DEFAULT = PROTOTYPE_CHAIN
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 };
29
30 enum State {
31 ACCESS_CHECK,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 INTEGER_INDEXED_EXOTIC,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033 INTERCEPTOR,
34 JSPROXY,
35 NOT_FOUND,
36 ACCESSOR,
37 DATA,
38 TRANSITION,
39 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
40 // PROPERTY lookup.
41 BEFORE_PROPERTY = INTERCEPTOR
42 };
43
44 LookupIterator(Handle<Object> receiver, Handle<Name> name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045 Configuration configuration = DEFAULT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 : configuration_(ComputeConfiguration(configuration, name)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 interceptor_state_(InterceptorState::kUninitialized),
48 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 isolate_(name->GetIsolate()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010050 name_(isolate_->factory()->InternalizeName(name)),
Ben Murdochda12d292016-06-02 14:46:10 +010051 receiver_(receiver),
52 initial_holder_(GetRoot(isolate_, receiver)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 // kMaxUInt32 isn't a valid index.
54 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056#ifdef DEBUG
57 uint32_t index; // Assert that the name is not an array index.
58 DCHECK(!name->AsArrayIndex(&index));
59#endif // DEBUG
Ben Murdochda12d292016-06-02 14:46:10 +010060 Start<false>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 }
62
63 LookupIterator(Handle<Object> receiver, Handle<Name> name,
64 Handle<JSReceiver> holder,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 Configuration configuration = DEFAULT)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 : configuration_(ComputeConfiguration(configuration, name)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 interceptor_state_(InterceptorState::kUninitialized),
68 property_details_(PropertyDetails::Empty()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 isolate_(name->GetIsolate()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010070 name_(isolate_->factory()->InternalizeName(name)),
Ben Murdochda12d292016-06-02 14:46:10 +010071 receiver_(receiver),
72 initial_holder_(holder),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 // kMaxUInt32 isn't a valid index.
74 index_(kMaxUInt32),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 number_(DescriptorArray::kNotFound) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076#ifdef DEBUG
77 uint32_t index; // Assert that the name is not an array index.
78 DCHECK(!name->AsArrayIndex(&index));
79#endif // DEBUG
Ben Murdochda12d292016-06-02 14:46:10 +010080 Start<false>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 }
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
84 Configuration configuration = DEFAULT)
85 : configuration_(configuration),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 interceptor_state_(InterceptorState::kUninitialized),
87 property_details_(PropertyDetails::Empty()),
88 isolate_(isolate),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 receiver_(receiver),
Ben Murdochda12d292016-06-02 14:46:10 +010090 initial_holder_(GetRoot(isolate, receiver, index)),
91 index_(index),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 number_(DescriptorArray::kNotFound) {
93 // kMaxUInt32 isn't a valid index.
94 DCHECK_NE(kMaxUInt32, index_);
Ben Murdochda12d292016-06-02 14:46:10 +010095 Start<true>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 }
97
98 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
99 Handle<JSReceiver> holder,
100 Configuration configuration = DEFAULT)
101 : configuration_(configuration),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 interceptor_state_(InterceptorState::kUninitialized),
103 property_details_(PropertyDetails::Empty()),
104 isolate_(isolate),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 receiver_(receiver),
Ben Murdochda12d292016-06-02 14:46:10 +0100106 initial_holder_(holder),
107 index_(index),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 number_(DescriptorArray::kNotFound) {
109 // kMaxUInt32 isn't a valid index.
110 DCHECK_NE(kMaxUInt32, index_);
Ben Murdochda12d292016-06-02 14:46:10 +0100111 Start<true>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 }
113
114 static LookupIterator PropertyOrElement(
115 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
116 Configuration configuration = DEFAULT) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 uint32_t index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100118 if (name->AsArrayIndex(&index)) {
119 LookupIterator it =
120 LookupIterator(isolate, receiver, index, configuration);
121 it.name_ = name;
122 return it;
123 }
124 return LookupIterator(receiver, name, configuration);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 }
126
127 static LookupIterator PropertyOrElement(
128 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
129 Handle<JSReceiver> holder, 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, holder, configuration);
134 it.name_ = name;
135 return it;
136 }
137 return LookupIterator(receiver, name, holder, configuration);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 }
139
140 static LookupIterator PropertyOrElement(
141 Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
142 bool* success, Configuration configuration = DEFAULT);
143
Ben Murdochda12d292016-06-02 14:46:10 +0100144 void Restart() {
145 InterceptorState state = InterceptorState::kUninitialized;
146 IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 Isolate* isolate() const { return isolate_; }
150 State state() const { return state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151
152 Handle<Name> name() const {
153 DCHECK(!IsElement());
154 return name_;
155 }
156 Handle<Name> GetName() {
157 if (name_.is_null()) {
158 DCHECK(IsElement());
159 name_ = factory()->Uint32ToString(index_);
160 }
161 return name_;
162 }
163 uint32_t index() const { return index_; }
164
165 bool IsElement() const { return index_ != kMaxUInt32; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166
167 bool IsFound() const { return state_ != NOT_FOUND; }
168 void Next();
169 void NotFound() {
170 has_property_ = false;
171 state_ = NOT_FOUND;
172 }
173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 Heap* heap() const { return isolate_->heap(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 Factory* factory() const { return isolate_->factory(); }
176 Handle<Object> GetReceiver() const { return receiver_; }
Ben Murdochda12d292016-06-02 14:46:10 +0100177
178 Handle<JSObject> GetStoreTarget() const {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100179 DCHECK(receiver_->IsJSObject());
Ben Murdochda12d292016-06-02 14:46:10 +0100180 if (receiver_->IsJSGlobalProxy()) {
181 Map* map = JSGlobalProxy::cast(*receiver_)->map();
182 if (map->has_hidden_prototype()) {
183 return handle(JSGlobalObject::cast(map->prototype()), isolate_);
184 }
185 }
186 return Handle<JSObject>::cast(receiver_);
187 }
188
Ben Murdoch097c5b22016-05-18 11:27:45 +0100189 bool is_dictionary_holder() const { return !holder_->HasFastProperties(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 Handle<Map> transition_map() const {
191 DCHECK_EQ(TRANSITION, state_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 return Handle<Map>::cast(transition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 }
194 template <class T>
195 Handle<T> GetHolder() const {
196 DCHECK(IsFound());
197 return Handle<T>::cast(holder_);
198 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 bool HolderIsReceiverOrHiddenPrototype() const;
201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 bool check_prototype_chain() const {
203 return (configuration_ & kPrototypeChain) != 0;
204 }
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 /* ACCESS_CHECK */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 bool HasAccess() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208
209 /* PROPERTY */
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 bool ExtendingNonExtensible(Handle<JSObject> receiver) {
211 DCHECK(receiver.is_identical_to(GetStoreTarget()));
212 return !receiver->map()->is_extensible() &&
213 (IsElement() || !name_->IsPrivate());
214 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 void PrepareForDataProperty(Handle<Object> value);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 void PrepareTransitionToDataProperty(Handle<JSObject> receiver,
217 Handle<Object> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 PropertyAttributes attributes,
219 Object::StoreFromKeyed store_mode);
220 bool IsCacheableTransition() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100221 DCHECK_EQ(TRANSITION, state_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 return transition_->IsPropertyCell() ||
223 (!transition_map()->is_dictionary_map() &&
224 transition_map()->GetBackPointer()->IsMap());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100226 void ApplyTransitionToDataProperty(Handle<JSObject> receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 void ReconfigureDataProperty(Handle<Object> value,
228 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 void Delete();
Ben Murdochc5610432016-08-08 18:44:38 +0100230 void TransitionToAccessorProperty(Handle<Object> getter,
231 Handle<Object> setter,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 PropertyAttributes attributes);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 void TransitionToAccessorPair(Handle<Object> pair,
234 PropertyAttributes attributes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 PropertyDetails property_details() const {
236 DCHECK(has_property_);
237 return property_details_;
238 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 PropertyAttributes property_attributes() const {
240 return property_details().attributes();
241 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 bool IsConfigurable() const { return property_details().IsConfigurable(); }
243 bool IsReadOnly() const { return property_details().IsReadOnly(); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100244 bool IsEnumerable() const { return property_details().IsEnumerable(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 Representation representation() const {
246 return property_details().representation();
247 }
248 FieldIndex GetFieldIndex() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100249 Handle<FieldType> GetFieldType() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 int GetAccessorIndex() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 int GetConstantIndex() const;
252 Handle<PropertyCell> GetPropertyCell() const;
253 Handle<Object> GetAccessors() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 inline Handle<InterceptorInfo> GetInterceptor() const {
255 DCHECK_EQ(INTERCEPTOR, state_);
Ben Murdochda12d292016-06-02 14:46:10 +0100256 InterceptorInfo* result =
257 IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
258 : GetInterceptor<false>(JSObject::cast(*holder_));
259 return handle(result, isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100261 Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 Handle<Object> GetDataValue() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 void WriteDataValue(Handle<Object> value);
Ben Murdochda12d292016-06-02 14:46:10 +0100264 inline void UpdateProtector() {
Ben Murdochc5610432016-08-08 18:44:38 +0100265 if (IsElement()) return;
266 if (*name_ == heap()->is_concat_spreadable_symbol() ||
Ben Murdoch61f157c2016-09-16 13:49:30 +0100267 *name_ == heap()->constructor_string() ||
268 *name_ == heap()->species_symbol() ||
269 *name_ == heap()->has_instance_symbol()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100270 InternalUpdateProtector();
271 }
272 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273
274 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100275 void InternalUpdateProtector();
276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 enum class InterceptorState {
278 kUninitialized,
279 kSkipNonMasking,
280 kProcessNonMasking
281 };
282
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 Handle<Map> GetReceiverMap() const;
284
285 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
Ben Murdochda12d292016-06-02 14:46:10 +0100286
287 template <bool is_element>
288 void Start();
289 template <bool is_element>
290 void NextInternal(Map* map, JSReceiver* holder);
291 template <bool is_element>
292 inline State LookupInHolder(Map* map, JSReceiver* holder) {
293 return map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE
294 ? LookupInSpecialHolder<is_element>(map, holder)
295 : LookupInRegularHolder<is_element>(map, holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296 }
Ben Murdochda12d292016-06-02 14:46:10 +0100297 template <bool is_element>
298 State LookupInRegularHolder(Map* map, JSReceiver* holder);
299 template <bool is_element>
300 State LookupInSpecialHolder(Map* map, JSReceiver* holder);
301 template <bool is_element>
302 void RestartLookupForNonMaskingInterceptors() {
303 RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
304 }
305 template <bool is_element>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 void RestartInternal(InterceptorState interceptor_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 Handle<Object> FetchValue() const;
Ben Murdochda12d292016-06-02 14:46:10 +0100308 template <bool is_element>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 void ReloadPropertyInformation();
Ben Murdochda12d292016-06-02 14:46:10 +0100310
311 template <bool is_element>
312 bool SkipInterceptor(JSObject* holder);
313 template <bool is_element>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
Ben Murdochda12d292016-06-02 14:46:10 +0100315 return is_element ? holder->GetIndexedInterceptor()
316 : holder->GetNamedInterceptor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 bool check_interceptor() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 return (configuration_ & kInterceptor) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 }
322 int descriptor_number() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100323 DCHECK(!IsElement());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 DCHECK(has_property_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 DCHECK(holder_->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 return number_;
327 }
328 int dictionary_entry() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100329 DCHECK(!IsElement());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330 DCHECK(has_property_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 DCHECK(!holder_->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 return number_;
333 }
334
335 static Configuration ComputeConfiguration(
336 Configuration configuration, Handle<Name> name) {
Ben Murdochc5610432016-08-08 18:44:38 +0100337 return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 }
339
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 static Handle<JSReceiver> GetRootForNonJSReceiver(
341 Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
342 inline static Handle<JSReceiver> GetRoot(Isolate* isolate,
343 Handle<Object> receiver,
344 uint32_t index = kMaxUInt32) {
345 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
346 return GetRootForNonJSReceiver(isolate, receiver, index);
347 }
348
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349 State NotFound(JSReceiver* const holder) const;
350
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000351 // If configuration_ becomes mutable, update
352 // HolderIsReceiverOrHiddenPrototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 const Configuration configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 State state_;
355 bool has_property_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 InterceptorState interceptor_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 PropertyDetails property_details_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 Isolate* const isolate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 Handle<Name> name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 Handle<Object> transition_;
361 const Handle<Object> receiver_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 Handle<JSReceiver> holder_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 const Handle<JSReceiver> initial_holder_;
Ben Murdochda12d292016-06-02 14:46:10 +0100364 const uint32_t index_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365 uint32_t number_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000366};
367
368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369} // namespace internal
370} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371
372#endif // V8_LOOKUP_H_