[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / lookup.h
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.
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
12 namespace v8 {
13 namespace internal {
14
15 class LookupIterator final BASE_EMBEDDED {
16  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,
29     PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor,
30     DEFAULT = PROTOTYPE_CHAIN
31   };
32
33   enum State {
34     ACCESS_CHECK,
35     INTEGER_INDEXED_EXOTIC,
36     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,
48                  Configuration configuration = DEFAULT)
49       : configuration_(ComputeConfiguration(configuration, name)),
50         state_(NOT_FOUND),
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.
57         index_(kMaxUInt32),
58         receiver_(receiver),
59         holder_(GetRoot(isolate_, receiver)),
60         holder_map_(holder_->map(), isolate_),
61         initial_holder_(holder_),
62         number_(DescriptorArray::kNotFound) {
63 #ifdef DEBUG
64     uint32_t index;  // Assert that the name is not an array index.
65     DCHECK(!name->AsArrayIndex(&index));
66 #endif  // DEBUG
67     Next();
68   }
69
70   LookupIterator(Handle<Object> receiver, Handle<Name> name,
71                  Handle<JSReceiver> holder,
72                  Configuration configuration = DEFAULT)
73       : configuration_(ComputeConfiguration(configuration, name)),
74         state_(NOT_FOUND),
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.
81         index_(kMaxUInt32),
82         receiver_(receiver),
83         holder_(holder),
84         holder_map_(holder_->map(), isolate_),
85         initial_holder_(holder_),
86         number_(DescriptorArray::kNotFound) {
87 #ifdef DEBUG
88     uint32_t index;  // Assert that the name is not an array index.
89     DCHECK(!name->AsArrayIndex(&index));
90 #endif  // DEBUG
91     Next();
92   }
93
94   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   Isolate* isolate() const { return isolate_; }
162   State state() const { return state_; }
163
164   Handle<Name> name() const {
165     DCHECK(!IsElement());
166     return name_;
167   }
168   Handle<Name> GetName() {
169     if (name_.is_null()) {
170       DCHECK(IsElement());
171       name_ = factory()->Uint32ToString(index_);
172     }
173     return name_;
174   }
175   uint32_t index() const { return index_; }
176
177   bool IsElement() const { return index_ != kMaxUInt32; }
178
179   bool IsFound() const { return state_ != NOT_FOUND; }
180   void Next();
181   void NotFound() {
182     has_property_ = false;
183     state_ = NOT_FOUND;
184   }
185
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_);
194   }
195   template <class T>
196   Handle<T> GetHolder() const {
197     DCHECK(IsFound());
198     return Handle<T>::cast(holder_);
199   }
200   static Handle<JSReceiver> GetRoot(Isolate* isolate, Handle<Object> receiver,
201                                     uint32_t index = kMaxUInt32);
202   bool HolderIsReceiverOrHiddenPrototype() const;
203
204   /* ACCESS_CHECK */
205   bool HasAccess() const;
206
207   /* PROPERTY */
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());
217   }
218   void ApplyTransitionToDataProperty();
219   void ReconfigureDataProperty(Handle<Object> value,
220                                PropertyAttributes attributes);
221   void Delete();
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_;
230   }
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();
235   }
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();
247
248  private:
249   enum class InterceptorState {
250     kUninitialized,
251     kSkipNonMasking,
252     kProcessNonMasking
253   };
254
255   Handle<Map> GetReceiverMap() const;
256
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;
267
268   bool check_hidden() const { return (configuration_ & kHidden) != 0; }
269   bool check_interceptor() const {
270     return (configuration_ & kInterceptor) != 0;
271   }
272   bool check_prototype_chain() const {
273     return (configuration_ & kPrototypeChain) != 0;
274   }
275   int descriptor_number() const {
276     DCHECK(has_property_);
277     DCHECK(!holder_map_->is_dictionary_map());
278     return number_;
279   }
280   int dictionary_entry() const {
281     DCHECK(has_property_);
282     DCHECK(holder_map_->is_dictionary_map());
283     return number_;
284   }
285
286   static Configuration ComputeConfiguration(
287       Configuration configuration, Handle<Name> name) {
288     if (name->IsPrivate()) {
289       return static_cast<Configuration>(configuration &
290                                         HIDDEN_SKIP_INTERCEPTOR);
291     } else {
292       return configuration;
293     }
294   }
295
296   enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic };
297   bool IsIntegerIndexedExotic(JSReceiver* holder);
298
299   // If configuration_ becomes mutable, update
300   // HolderIsReceiverOrHiddenPrototype.
301   const Configuration configuration_;
302   State state_;
303   bool has_property_;
304   ExoticIndexState exotic_index_state_;
305   InterceptorState interceptor_state_;
306   PropertyDetails property_details_;
307   Isolate* const isolate_;
308   Handle<Name> name_;
309   uint32_t index_;
310   Handle<Object> transition_;
311   const Handle<Object> receiver_;
312   Handle<JSReceiver> holder_;
313   Handle<Map> holder_map_;
314   const Handle<JSReceiver> initial_holder_;
315   uint32_t number_;
316 };
317
318
319 }  // namespace internal
320 }  // namespace v8
321
322 #endif  // V8_LOOKUP_H_