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