lookup.h 9.66 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_LOOKUP_H_
#define V8_LOOKUP_H_

8
#include "src/globals.h"
9
#include "src/heap/factory.h"
10 11
#include "src/isolate.h"
#include "src/objects.h"
12
#include "src/objects/descriptor-array.h"
13
#include "src/objects/js-objects.h"
14
#include "src/objects/map.h"
15 16 17 18

namespace v8 {
namespace internal {

19
class V8_EXPORT_PRIVATE LookupIterator final {
20
 public:
21
  enum Configuration {
22
    // Configuration bits.
23 24
    kInterceptor = 1 << 0,
    kPrototypeChain = 1 << 1,
25

26
    // Convenience combinations of bits.
27 28
    OWN_SKIP_INTERCEPTOR = 0,
    OWN = kInterceptor,
29 30
    PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
    PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
31
    DEFAULT = PROTOTYPE_CHAIN
32 33 34
  };

  enum State {
35
    ACCESS_CHECK,
36
    INTEGER_INDEXED_EXOTIC,
37 38
    INTERCEPTOR,
    JSPROXY,
39
    NOT_FOUND,
40 41
    ACCESSOR,
    DATA,
42
    TRANSITION,
43 44 45
    // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
    // PROPERTY lookup.
    BEFORE_PROPERTY = INTERCEPTOR
46 47
  };

48 49 50
  inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
                        Handle<Name> name,
                        Configuration configuration = DEFAULT);
51

52 53 54
  inline LookupIterator(Handle<Object> receiver, Handle<Name> name,
                        Handle<JSReceiver> holder,
                        Configuration configuration = DEFAULT);
55

56 57 58
  inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
                        Handle<Name> name, Handle<JSReceiver> holder,
                        Configuration configuration = DEFAULT);
59

60 61
  inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
                        uint32_t index, Configuration configuration = DEFAULT);
62 63 64

  LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
                 Handle<JSReceiver> holder,
65
                 Configuration configuration = DEFAULT)
66 67 68 69 70
      : configuration_(configuration),
        interceptor_state_(InterceptorState::kUninitialized),
        property_details_(PropertyDetails::Empty()),
        isolate_(isolate),
        receiver_(receiver),
71 72
        initial_holder_(holder),
        index_(index),
73
        number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
74 75
    // kMaxUInt32 isn't a valid index.
    DCHECK_NE(kMaxUInt32, index_);
76
    Start<true>();
77 78
  }

79
  static inline LookupIterator PropertyOrElement(
80
      Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
81
      Configuration configuration = DEFAULT);
82

83
  static inline LookupIterator PropertyOrElement(
84
      Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
85
      Handle<JSReceiver> holder, Configuration configuration = DEFAULT);
86

87 88 89 90 91
  static LookupIterator PropertyOrElement(
      Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
      bool* success, Handle<JSReceiver> holder,
      Configuration configuration = DEFAULT);

92 93 94 95
  static LookupIterator PropertyOrElement(
      Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
      bool* success, Configuration configuration = DEFAULT);

96 97 98
  static LookupIterator ForTransitionHandler(
      Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      Handle<Object> value, MaybeHandle<Map> maybe_transition_map);
99

100 101 102 103
  void Restart() {
    InterceptorState state = InterceptorState::kUninitialized;
    IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
  }
104

105 106
  Isolate* isolate() const { return isolate_; }
  State state() const { return state_; }
107

108 109 110 111
  Handle<Name> name() const {
    DCHECK(!IsElement());
    return name_;
  }
112
  inline Handle<Name> GetName();
113 114 115
  uint32_t index() const { return index_; }

  bool IsElement() const { return index_ != kMaxUInt32; }
116 117 118

  bool IsFound() const { return state_ != NOT_FOUND; }
  void Next();
119 120 121 122
  void NotFound() {
    has_property_ = false;
    state_ = NOT_FOUND;
  }
123

124
  Heap* heap() const { return isolate_->heap(); }
125
  Factory* factory() const { return isolate_->factory(); }
126
  Handle<Object> GetReceiver() const { return receiver_; }
127

128
  template <class T>
129
  inline Handle<T> GetStoreTarget() const;
130
  inline bool is_dictionary_holder() const;
131 132
  inline Handle<Map> transition_map() const;
  inline Handle<PropertyCell> transition_cell() const;
133
  template <class T>
134
  inline Handle<T> GetHolder() const;
135

136
  bool HolderIsReceiver() const;
137
  bool HolderIsReceiverOrHiddenPrototype() const;
138

neis's avatar
neis committed
139 140 141 142
  bool check_prototype_chain() const {
    return (configuration_ & kPrototypeChain) != 0;
  }

143
  /* ACCESS_CHECK */
144
  bool HasAccess() const;
145 146

  /* PROPERTY */
147
  inline bool ExtendingNonExtensible(Handle<JSReceiver> receiver);
148
  void PrepareForDataProperty(Handle<Object> value);
149
  void PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
150
                                       Handle<Object> value,
151
                                       PropertyAttributes attributes,
152
                                       StoreOrigin store_origin);
153
  inline bool IsCacheableTransition();
154
  void ApplyTransitionToDataProperty(Handle<JSReceiver> receiver);
155 156
  void ReconfigureDataProperty(Handle<Object> value,
                               PropertyAttributes attributes);
157
  void Delete();
158 159
  void TransitionToAccessorProperty(Handle<Object> getter,
                                    Handle<Object> setter,
160
                                    PropertyAttributes attributes);
161 162
  void TransitionToAccessorPair(Handle<Object> pair,
                                PropertyAttributes attributes);
163
  PropertyDetails property_details() const {
164
    DCHECK(has_property_);
165 166
    return property_details_;
  }
167 168 169
  PropertyAttributes property_attributes() const {
    return property_details().attributes();
  }
170
  bool IsConfigurable() const { return property_details().IsConfigurable(); }
171
  bool IsReadOnly() const { return property_details().IsReadOnly(); }
172
  bool IsEnumerable() const { return property_details().IsEnumerable(); }
173 174
  Representation representation() const {
    return property_details().representation();
175
  }
176
  PropertyLocation location() const { return property_details().location(); }
177
  PropertyConstness constness() const { return property_details().constness(); }
178
  Handle<Map> GetFieldOwnerMap() const;
179
  FieldIndex GetFieldIndex() const;
180
  Handle<FieldType> GetFieldType() const;
181
  int GetFieldDescriptorIndex() const;
182
  int GetAccessorIndex() const;
183
  int GetConstantIndex() const;
184
  Handle<PropertyCell> GetPropertyCell() const;
185
  Handle<Object> GetAccessors() const;
186
  inline Handle<InterceptorInfo> GetInterceptor() const;
187
  Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
188
  Handle<Object> GetDataValue() const;
189
  void WriteDataValue(Handle<Object> value, bool initializing_store);
190
  inline void UpdateProtector();
191

192 193 194 195 196
  // Lookup a 'cached' private property for an accessor.
  // If not found returns false and leaves the LookupIterator unmodified.
  bool TryLookupCachedProperty();
  bool LookupCachedProperty();

197
 private:
198 199 200 201 202
  // For |ForTransitionHandler|.
  LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
                 Handle<Map> transition_map, PropertyDetails details,
                 bool has_property);

203 204
  void InternalUpdateProtector();

205 206 207 208 209 210
  enum class InterceptorState {
    kUninitialized,
    kSkipNonMasking,
    kProcessNonMasking
  };

211 212
  Handle<Map> GetReceiverMap() const;

213
  V8_WARN_UNUSED_RESULT inline JSReceiver NextHolder(Map map);
214 215

  template <bool is_element>
216
  V8_EXPORT_PRIVATE void Start();
217
  template <bool is_element>
218
  void NextInternal(Map map, JSReceiver holder);
219
  template <bool is_element>
220
  inline State LookupInHolder(Map map, JSReceiver holder) {
221
    return map->IsSpecialReceiverMap()
222 223 224 225
               ? LookupInSpecialHolder<is_element>(map, holder)
               : LookupInRegularHolder<is_element>(map, holder);
  }
  template <bool is_element>
226
  State LookupInRegularHolder(Map map, JSReceiver holder);
227
  template <bool is_element>
228
  State LookupInSpecialHolder(Map map, JSReceiver holder);
229
  template <bool is_element>
230
  void RestartLookupForNonMaskingInterceptors() {
231
    RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
232
  }
233
  template <bool is_element>
234
  void RestartInternal(InterceptorState interceptor_state);
235
  Handle<Object> FetchValue() const;
236
  bool IsConstFieldValueEqualTo(Object value) const;
237
  template <bool is_element>
238
  void ReloadPropertyInformation();
239

240
  template <bool is_element>
241
  bool SkipInterceptor(JSObject holder);
242
  template <bool is_element>
243
  static inline InterceptorInfo GetInterceptor(JSObject holder);
244

245
  bool check_interceptor() const {
246
    return (configuration_ & kInterceptor) != 0;
247
  }
248 249
  inline int descriptor_number() const;
  inline int dictionary_entry() const;
250

251 252
  static inline Configuration ComputeConfiguration(
      Configuration configuration, Handle<Name> name);
253

254 255
  static Handle<JSReceiver> GetRootForNonJSReceiver(
      Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
256
  static inline Handle<JSReceiver> GetRoot(Isolate* isolate,
257
                                           Handle<Object> receiver,
258
                                           uint32_t index = kMaxUInt32);
259

260
  State NotFound(JSReceiver const holder) const;
261

262 263
  // If configuration_ becomes mutable, update
  // HolderIsReceiverOrHiddenPrototype.
264
  const Configuration configuration_;
265 266
  State state_;
  bool has_property_;
267
  InterceptorState interceptor_state_;
268
  PropertyDetails property_details_;
269
  Isolate* const isolate_;
270
  Handle<Name> name_;
271
  Handle<Object> transition_;
272
  const Handle<Object> receiver_;
273
  Handle<JSReceiver> holder_;
274
  const Handle<JSReceiver> initial_holder_;
275
  const uint32_t index_;
276
  uint32_t number_;
277 278 279
};


280 281
}  // namespace internal
}  // namespace v8
282 283

#endif  // V8_LOOKUP_H_