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.
8 #include "src/factory.h"
9 #include "src/isolate.h"
10 #include "src/objects.h"
15 class LookupIterator final BASE_EMBEDDED {
18 // Configuration bits.
20 kInterceptor = 1 << 1,
21 kPrototypeChain = 1 << 2,
23 // Convience combinations of bits.
24 OWN_SKIP_INTERCEPTOR = 0,
26 HIDDEN_SKIP_INTERCEPTOR = kHidden,
27 HIDDEN = kHidden | kInterceptor,
28 PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain,
29 PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor,
30 DEFAULT = PROTOTYPE_CHAIN
35 INTEGER_INDEXED_EXOTIC,
42 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
44 BEFORE_PROPERTY = INTERCEPTOR
47 LookupIterator(Handle<Object> receiver, Handle<Name> name,
48 Configuration configuration = DEFAULT)
49 : configuration_(ComputeConfiguration(configuration, name)),
51 exotic_index_state_(ExoticIndexState::kUninitialized),
52 interceptor_state_(InterceptorState::kUninitialized),
53 property_details_(PropertyDetails::Empty()),
54 isolate_(name->GetIsolate()),
55 name_(Name::Flatten(name)),
56 // kMaxUInt32 isn't a valid index.
59 holder_(GetRoot(isolate_, receiver)),
60 holder_map_(holder_->map(), isolate_),
61 initial_holder_(holder_),
62 number_(DescriptorArray::kNotFound) {
64 uint32_t index; // Assert that the name is not an array index.
65 DCHECK(!name->AsArrayIndex(&index));
70 LookupIterator(Handle<Object> receiver, Handle<Name> name,
71 Handle<JSReceiver> holder,
72 Configuration configuration = DEFAULT)
73 : configuration_(ComputeConfiguration(configuration, name)),
75 exotic_index_state_(ExoticIndexState::kUninitialized),
76 interceptor_state_(InterceptorState::kUninitialized),
77 property_details_(PropertyDetails::Empty()),
78 isolate_(name->GetIsolate()),
79 name_(Name::Flatten(name)),
80 // kMaxUInt32 isn't a valid index.
84 holder_map_(holder_->map(), isolate_),
85 initial_holder_(holder_),
86 number_(DescriptorArray::kNotFound) {
88 uint32_t index; // Assert that the name is not an array index.
89 DCHECK(!name->AsArrayIndex(&index));
94 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
95 Configuration configuration = DEFAULT)
96 : configuration_(configuration),
98 exotic_index_state_(ExoticIndexState::kUninitialized),
99 interceptor_state_(InterceptorState::kUninitialized),
100 property_details_(PropertyDetails::Empty()),
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_);
114 LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
115 Handle<JSReceiver> holder,
116 Configuration configuration = DEFAULT)
117 : configuration_(configuration),
119 exotic_index_state_(ExoticIndexState::kUninitialized),
120 interceptor_state_(InterceptorState::kUninitialized),
121 property_details_(PropertyDetails::Empty()),
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_);
135 static LookupIterator PropertyOrElement(
136 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
137 Configuration configuration = DEFAULT) {
138 name = Name::Flatten(name);
141 name->AsArrayIndex(&index)
142 ? LookupIterator(isolate, receiver, index, configuration)
143 : LookupIterator(receiver, name, configuration);
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);
154 name->AsArrayIndex(&index)
155 ? LookupIterator(isolate, receiver, index, holder, configuration)
156 : LookupIterator(receiver, name, holder, configuration);
161 Isolate* isolate() const { return isolate_; }
162 State state() const { return state_; }
164 Handle<Name> name() const {
165 DCHECK(!IsElement());
168 Handle<Name> GetName() {
169 if (name_.is_null()) {
171 name_ = factory()->Uint32ToString(index_);
175 uint32_t index() const { return index_; }
177 bool IsElement() const { return index_ != kMaxUInt32; }
179 bool IsFound() const { return state_ != NOT_FOUND; }
182 has_property_ = false;
186 Heap* heap() const { return isolate_->heap(); }
187 Factory* factory() const { return isolate_->factory(); }
188 Handle<Object> GetReceiver() const { return receiver_; }
189 Handle<JSObject> GetStoreTarget() const;
190 bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
191 Handle<Map> transition_map() const {
192 DCHECK_EQ(TRANSITION, state_);
193 return Handle<Map>::cast(transition_);
196 Handle<T> GetHolder() const {
198 return Handle<T>::cast(holder_);
200 static Handle<JSReceiver> GetRoot(Isolate* isolate, Handle<Object> receiver,
201 uint32_t index = kMaxUInt32);
202 bool HolderIsReceiverOrHiddenPrototype() const;
205 bool HasAccess() const;
208 void PrepareForDataProperty(Handle<Object> value);
209 void PrepareTransitionToDataProperty(Handle<Object> value,
210 PropertyAttributes attributes,
211 Object::StoreFromKeyed store_mode);
212 bool IsCacheableTransition() {
213 if (state_ != TRANSITION) return false;
214 return transition_->IsPropertyCell() ||
215 (!transition_map()->is_dictionary_map() &&
216 transition_map()->GetBackPointer()->IsMap());
218 void ApplyTransitionToDataProperty();
219 void ReconfigureDataProperty(Handle<Object> value,
220 PropertyAttributes attributes);
222 void TransitionToAccessorProperty(AccessorComponent component,
223 Handle<Object> accessor,
224 PropertyAttributes attributes);
225 void TransitionToAccessorPair(Handle<Object> pair,
226 PropertyAttributes attributes);
227 PropertyDetails property_details() const {
228 DCHECK(has_property_);
229 return property_details_;
231 bool IsConfigurable() const { return property_details().IsConfigurable(); }
232 bool IsReadOnly() const { return property_details().IsReadOnly(); }
233 Representation representation() const {
234 return property_details().representation();
236 FieldIndex GetFieldIndex() const;
237 Handle<HeapType> GetFieldType() const;
238 int GetAccessorIndex() const;
239 int GetConstantIndex() const;
240 Handle<PropertyCell> GetPropertyCell() const;
241 Handle<Object> GetAccessors() const;
242 Handle<InterceptorInfo> GetInterceptor() const;
243 Handle<Object> GetDataValue() const;
244 void WriteDataValue(Handle<Object> value);
245 void InternalizeName();
246 void ReloadHolderMap();
249 enum class InterceptorState {
255 Handle<Map> GetReceiverMap() const;
257 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
258 inline State LookupInHolder(Map* map, JSReceiver* holder);
259 void RestartLookupForNonMaskingInterceptors();
260 State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
261 Handle<Object> FetchValue() const;
262 void ReloadPropertyInformation();
263 bool SkipInterceptor(JSObject* holder);
264 bool HasInterceptor(Map* map) const;
265 bool InternalHolderIsReceiverOrHiddenPrototype() const;
266 InterceptorInfo* GetInterceptor(JSObject* holder) const;
268 bool check_hidden() const { return (configuration_ & kHidden) != 0; }
269 bool check_interceptor() const {
270 return (configuration_ & kInterceptor) != 0;
272 bool check_prototype_chain() const {
273 return (configuration_ & kPrototypeChain) != 0;
275 int descriptor_number() const {
276 DCHECK(has_property_);
277 DCHECK(!holder_map_->is_dictionary_map());
280 int dictionary_entry() const {
281 DCHECK(has_property_);
282 DCHECK(holder_map_->is_dictionary_map());
286 static Configuration ComputeConfiguration(
287 Configuration configuration, Handle<Name> name) {
288 if (name->IsPrivate()) {
289 return static_cast<Configuration>(configuration &
290 HIDDEN_SKIP_INTERCEPTOR);
292 return configuration;
296 enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic };
297 bool IsIntegerIndexedExotic(JSReceiver* holder);
299 // If configuration_ becomes mutable, update
300 // HolderIsReceiverOrHiddenPrototype.
301 const Configuration configuration_;
304 ExoticIndexState exotic_index_state_;
305 InterceptorState interceptor_state_;
306 PropertyDetails property_details_;
307 Isolate* const isolate_;
310 Handle<Object> transition_;
311 const Handle<Object> receiver_;
312 Handle<JSReceiver> holder_;
313 Handle<Map> holder_map_;
314 const Handle<JSReceiver> initial_holder_;
319 } } // namespace v8::internal
321 #endif // V8_LOOKUP_H_