• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/globals.h"
9 #include "src/heap/factory.h"
10 #include "src/isolate.h"
11 #include "src/objects.h"
12 #include "src/objects/descriptor-array.h"
13 #include "src/objects/map.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
19  public:
20   enum Configuration {
21     // Configuration bits.
22     kInterceptor = 1 << 0,
23     kPrototypeChain = 1 << 1,
24 
25     // Convenience combinations of bits.
26     OWN_SKIP_INTERCEPTOR = 0,
27     OWN = kInterceptor,
28     PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
29     PROTOTYPE_CHAIN = 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(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
48                  Configuration configuration = DEFAULT)
LookupIterator(isolate,receiver,name,GetRoot (isolate,receiver),configuration)49       : LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
50                        configuration) {}
51 
52   inline LookupIterator(Handle<Object> receiver, Handle<Name> name,
53                         Handle<JSReceiver> holder,
54                         Configuration configuration = DEFAULT);
55 
56   inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
57                         Handle<Name> name, Handle<JSReceiver> holder,
58                         Configuration configuration = DEFAULT);
59 
60   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
61                  Configuration configuration = DEFAULT)
LookupIterator(isolate,receiver,index,GetRoot (isolate,receiver,index),configuration)62       : LookupIterator(isolate, receiver, index,
63                        GetRoot(isolate, receiver, index), configuration) {}
64 
65   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
66                  Handle<JSReceiver> holder,
67                  Configuration configuration = DEFAULT)
configuration_(configuration)68       : configuration_(configuration),
69         interceptor_state_(InterceptorState::kUninitialized),
70         property_details_(PropertyDetails::Empty()),
71         isolate_(isolate),
72         receiver_(receiver),
73         initial_holder_(holder),
74         index_(index),
75         number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
76     // kMaxUInt32 isn't a valid index.
77     DCHECK_NE(kMaxUInt32, index_);
78     Start<true>();
79   }
80 
81   static inline LookupIterator PropertyOrElement(
82       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
83       Configuration configuration = DEFAULT);
84 
85   static inline LookupIterator PropertyOrElement(
86       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
87       Handle<JSReceiver> holder, Configuration configuration = DEFAULT);
88 
89   static LookupIterator PropertyOrElement(
90       Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
91       bool* success, Handle<JSReceiver> holder,
92       Configuration configuration = DEFAULT);
93 
94   static LookupIterator PropertyOrElement(
95       Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
96       bool* success, Configuration configuration = DEFAULT);
97 
98   static LookupIterator ForTransitionHandler(
99       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
100       Handle<Object> value, MaybeHandle<Map> maybe_transition_map);
101 
Restart()102   void Restart() {
103     InterceptorState state = InterceptorState::kUninitialized;
104     IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
105   }
106 
isolate()107   Isolate* isolate() const { return isolate_; }
state()108   State state() const { return state_; }
109 
name()110   Handle<Name> name() const {
111     DCHECK(!IsElement());
112     return name_;
113   }
114   inline Handle<Name> GetName();
index()115   uint32_t index() const { return index_; }
116 
IsElement()117   bool IsElement() const { return index_ != kMaxUInt32; }
118 
IsFound()119   bool IsFound() const { return state_ != NOT_FOUND; }
120   void Next();
NotFound()121   void NotFound() {
122     has_property_ = false;
123     state_ = NOT_FOUND;
124   }
125 
heap()126   Heap* heap() const { return isolate_->heap(); }
factory()127   Factory* factory() const { return isolate_->factory(); }
GetReceiver()128   Handle<Object> GetReceiver() const { return receiver_; }
129 
130   template <class T>
131   inline Handle<T> GetStoreTarget() const;
132   inline bool is_dictionary_holder() const;
transition_map()133   Handle<Map> transition_map() const {
134     DCHECK_EQ(TRANSITION, state_);
135     return Handle<Map>::cast(transition_);
136   }
transition_cell()137   Handle<PropertyCell> transition_cell() const {
138     DCHECK_EQ(TRANSITION, state_);
139     return Handle<PropertyCell>::cast(transition_);
140   }
141   template <class T>
GetHolder()142   Handle<T> GetHolder() const {
143     DCHECK(IsFound());
144     return Handle<T>::cast(holder_);
145   }
146 
147   bool HolderIsReceiver() const;
148   bool HolderIsReceiverOrHiddenPrototype() const;
149 
check_prototype_chain()150   bool check_prototype_chain() const {
151     return (configuration_ & kPrototypeChain) != 0;
152   }
153 
154   /* ACCESS_CHECK */
155   bool HasAccess() const;
156 
157   /* PROPERTY */
158   inline bool ExtendingNonExtensible(Handle<JSReceiver> receiver);
159   void PrepareForDataProperty(Handle<Object> value);
160   void PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
161                                        Handle<Object> value,
162                                        PropertyAttributes attributes,
163                                        Object::StoreFromKeyed store_mode);
164   inline bool IsCacheableTransition();
165   void ApplyTransitionToDataProperty(Handle<JSReceiver> receiver);
166   void ReconfigureDataProperty(Handle<Object> value,
167                                PropertyAttributes attributes);
168   void Delete();
169   void TransitionToAccessorProperty(Handle<Object> getter,
170                                     Handle<Object> setter,
171                                     PropertyAttributes attributes);
172   void TransitionToAccessorPair(Handle<Object> pair,
173                                 PropertyAttributes attributes);
property_details()174   PropertyDetails property_details() const {
175     DCHECK(has_property_);
176     return property_details_;
177   }
property_attributes()178   PropertyAttributes property_attributes() const {
179     return property_details().attributes();
180   }
IsConfigurable()181   bool IsConfigurable() const { return property_details().IsConfigurable(); }
IsReadOnly()182   bool IsReadOnly() const { return property_details().IsReadOnly(); }
IsEnumerable()183   bool IsEnumerable() const { return property_details().IsEnumerable(); }
representation()184   Representation representation() const {
185     return property_details().representation();
186   }
location()187   PropertyLocation location() const { return property_details().location(); }
constness()188   PropertyConstness constness() const { return property_details().constness(); }
189   Handle<Map> GetFieldOwnerMap() const;
190   FieldIndex GetFieldIndex() const;
191   Handle<FieldType> GetFieldType() const;
192   int GetFieldDescriptorIndex() const;
193   int GetAccessorIndex() const;
194   int GetConstantIndex() const;
195   Handle<PropertyCell> GetPropertyCell() const;
196   Handle<Object> GetAccessors() const;
197   inline Handle<InterceptorInfo> GetInterceptor() const;
198   Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
199   Handle<Object> GetDataValue() const;
200   void WriteDataValue(Handle<Object> value, bool initializing_store);
201   inline void UpdateProtector();
202 
203   // Lookup a 'cached' private property for an accessor.
204   // If not found returns false and leaves the LookupIterator unmodified.
205   bool TryLookupCachedProperty();
206   bool LookupCachedProperty();
207 
208  private:
209   // For |ForTransitionHandler|.
210   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
211                  Handle<Map> transition_map, PropertyDetails details,
212                  bool has_property);
213 
214   void InternalUpdateProtector();
215 
216   enum class InterceptorState {
217     kUninitialized,
218     kSkipNonMasking,
219     kProcessNonMasking
220   };
221 
222   Handle<Map> GetReceiverMap() const;
223 
224   V8_WARN_UNUSED_RESULT inline JSReceiver* NextHolder(Map* map);
225 
226   template <bool is_element>
227   V8_EXPORT_PRIVATE void Start();
228   template <bool is_element>
229   void NextInternal(Map* map, JSReceiver* holder);
230   template <bool is_element>
LookupInHolder(Map * map,JSReceiver * holder)231   inline State LookupInHolder(Map* map, JSReceiver* holder) {
232     return map->IsSpecialReceiverMap()
233                ? LookupInSpecialHolder<is_element>(map, holder)
234                : LookupInRegularHolder<is_element>(map, holder);
235   }
236   template <bool is_element>
237   State LookupInRegularHolder(Map* map, JSReceiver* holder);
238   template <bool is_element>
239   State LookupInSpecialHolder(Map* map, JSReceiver* holder);
240   template <bool is_element>
RestartLookupForNonMaskingInterceptors()241   void RestartLookupForNonMaskingInterceptors() {
242     RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
243   }
244   template <bool is_element>
245   void RestartInternal(InterceptorState interceptor_state);
246   Handle<Object> FetchValue() const;
247   bool IsConstFieldValueEqualTo(Object* value) const;
248   template <bool is_element>
249   void ReloadPropertyInformation();
250 
251   template <bool is_element>
252   bool SkipInterceptor(JSObject* holder);
253   template <bool is_element>
GetInterceptor(JSObject * holder)254   inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
255     return is_element ? holder->GetIndexedInterceptor()
256                       : holder->GetNamedInterceptor();
257   }
258 
check_interceptor()259   bool check_interceptor() const {
260     return (configuration_ & kInterceptor) != 0;
261   }
descriptor_number()262   int descriptor_number() const {
263     DCHECK(!IsElement());
264     DCHECK(has_property_);
265     DCHECK(holder_->HasFastProperties());
266     return number_;
267   }
dictionary_entry()268   int dictionary_entry() const {
269     DCHECK(!IsElement());
270     DCHECK(has_property_);
271     DCHECK(!holder_->HasFastProperties());
272     return number_;
273   }
274 
275   static inline Configuration ComputeConfiguration(
276       Configuration configuration, Handle<Name> name);
277 
278   static Handle<JSReceiver> GetRootForNonJSReceiver(
279       Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
280   static inline Handle<JSReceiver> GetRoot(Isolate* isolate,
281                                            Handle<Object> receiver,
282                                            uint32_t index = kMaxUInt32);
283 
284   State NotFound(JSReceiver* const holder) const;
285 
286   // If configuration_ becomes mutable, update
287   // HolderIsReceiverOrHiddenPrototype.
288   const Configuration configuration_;
289   State state_;
290   bool has_property_;
291   InterceptorState interceptor_state_;
292   PropertyDetails property_details_;
293   Isolate* const isolate_;
294   Handle<Name> name_;
295   Handle<Object> transition_;
296   const Handle<Object> receiver_;
297   Handle<JSReceiver> holder_;
298   const Handle<JSReceiver> initial_holder_;
299   const uint32_t index_;
300   uint32_t number_;
301 };
302 
303 
304 }  // namespace internal
305 }  // namespace v8
306 
307 #endif  // V8_LOOKUP_H_
308