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
34 INTEGER_INDEXED_EXOTIC,
41 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
43 BEFORE_PROPERTY = INTERCEPTOR
46 LookupIterator(Handle<Object> receiver, Handle<Name> name,
47 Configuration configuration = PROTOTYPE_CHAIN)
48 : configuration_(ComputeConfiguration(configuration, name)),
50 exotic_index_state_(ExoticIndexState::kUninitialized),
51 interceptor_state_(InterceptorState::kUninitialized),
52 property_details_(PropertyDetails::Empty()),
53 isolate_(name->GetIsolate()),
56 holder_(GetRoot(receiver_, isolate_)),
57 holder_map_(holder_->map(), isolate_),
58 initial_holder_(holder_),
59 number_(DescriptorArray::kNotFound) {
63 LookupIterator(Handle<Object> receiver, Handle<Name> name,
64 Handle<JSReceiver> holder,
65 Configuration configuration = PROTOTYPE_CHAIN)
66 : configuration_(ComputeConfiguration(configuration, name)),
68 exotic_index_state_(ExoticIndexState::kUninitialized),
69 interceptor_state_(InterceptorState::kUninitialized),
70 property_details_(PropertyDetails::Empty()),
71 isolate_(name->GetIsolate()),
75 holder_map_(holder_->map(), isolate_),
76 initial_holder_(holder_),
77 number_(DescriptorArray::kNotFound) {
81 Isolate* isolate() const { return isolate_; }
82 State state() const { return state_; }
83 Handle<Name> name() const { return name_; }
85 bool IsFound() const { return state_ != NOT_FOUND; }
88 has_property_ = false;
92 Factory* factory() const { return isolate_->factory(); }
93 Handle<Object> GetReceiver() const { return receiver_; }
94 Handle<JSObject> GetStoreTarget() const;
95 bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
96 Handle<Map> transition_map() const {
97 DCHECK_EQ(TRANSITION, state_);
98 return Handle<Map>::cast(transition_);
101 Handle<T> GetHolder() const {
103 return Handle<T>::cast(holder_);
105 static Handle<JSReceiver> GetRoot(Handle<Object> receiver, Isolate* isolate);
106 bool HolderIsReceiverOrHiddenPrototype() const;
109 bool HasAccess() const;
112 void PrepareForDataProperty(Handle<Object> value);
113 void PrepareTransitionToDataProperty(Handle<Object> value,
114 PropertyAttributes attributes,
115 Object::StoreFromKeyed store_mode);
116 bool IsCacheableTransition() {
117 if (state_ != TRANSITION) return false;
118 return transition_->IsPropertyCell() ||
119 transition_map()->GetBackPointer()->IsMap();
121 void ApplyTransitionToDataProperty();
122 void ReconfigureDataProperty(Handle<Object> value,
123 PropertyAttributes attributes);
124 void TransitionToAccessorProperty(AccessorComponent component,
125 Handle<Object> accessor,
126 PropertyAttributes attributes);
127 PropertyDetails property_details() const {
128 DCHECK(has_property_);
129 return property_details_;
131 bool IsConfigurable() const { return property_details().IsConfigurable(); }
132 bool IsReadOnly() const { return property_details().IsReadOnly(); }
133 Representation representation() const {
134 return property_details().representation();
136 FieldIndex GetFieldIndex() const;
137 Handle<HeapType> GetFieldType() const;
138 int GetAccessorIndex() const;
139 int GetConstantIndex() const;
140 Handle<PropertyCell> GetPropertyCell() const;
141 Handle<Object> GetAccessors() const;
142 Handle<Object> GetDataValue() const;
143 // Usually returns the value that was passed in, but may perform
144 // non-observable modifications on it, such as internalize strings.
145 Handle<Object> WriteDataValue(Handle<Object> value);
146 void InternalizeName();
149 enum class InterceptorState {
155 Handle<Map> GetReceiverMap() const;
157 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
158 inline State LookupInHolder(Map* map, JSReceiver* holder);
159 void RestartLookupForNonMaskingInterceptors();
160 State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
161 Handle<Object> FetchValue() const;
162 void ReloadPropertyInformation();
163 bool SkipInterceptor(JSObject* holder);
165 bool IsBootstrapping() const;
167 bool check_hidden() const { return (configuration_ & kHidden) != 0; }
168 bool check_interceptor() const {
169 return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
171 bool check_prototype_chain() const {
172 return (configuration_ & kPrototypeChain) != 0;
174 int descriptor_number() const {
175 DCHECK(has_property_);
176 DCHECK(!holder_map_->is_dictionary_map());
179 int dictionary_entry() const {
180 DCHECK(has_property_);
181 DCHECK(holder_map_->is_dictionary_map());
185 static Configuration ComputeConfiguration(
186 Configuration configuration, Handle<Name> name) {
188 return static_cast<Configuration>(configuration &
189 HIDDEN_SKIP_INTERCEPTOR);
191 return configuration;
195 enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex };
196 bool IsIntegerIndexedExotic(JSReceiver* holder);
198 // If configuration_ becomes mutable, update
199 // HolderIsReceiverOrHiddenPrototype.
200 const Configuration configuration_;
203 ExoticIndexState exotic_index_state_;
204 InterceptorState interceptor_state_;
205 PropertyDetails property_details_;
206 Isolate* const isolate_;
208 Handle<Object> transition_;
209 const Handle<Object> receiver_;
210 Handle<JSReceiver> holder_;
211 Handle<Map> holder_map_;
212 const Handle<JSReceiver> initial_holder_;
217 } } // namespace v8::internal
219 #endif // V8_LOOKUP_H_