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
12namespace v8 {
13namespace internal {
14
15class 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  };
31
32  enum State {
33    ACCESS_CHECK,
34    INTERCEPTOR,
35    JSPROXY,
36    NOT_FOUND,
37    ACCESSOR,
38    DATA,
39    TRANSITION,
40    // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
41    // PROPERTY lookup.
42    BEFORE_PROPERTY = INTERCEPTOR
43  };
44
45  LookupIterator(Handle<Object> receiver, Handle<Name> name,
46                 Configuration configuration = PROTOTYPE_CHAIN)
47      : configuration_(ComputeConfiguration(configuration, name)),
48        state_(NOT_FOUND),
49        property_details_(NONE, NORMAL, Representation::None()),
50        isolate_(name->GetIsolate()),
51        name_(name),
52        receiver_(receiver),
53        number_(DescriptorArray::kNotFound) {
54    holder_ = GetRoot();
55    holder_map_ = handle(holder_->map(), isolate_);
56    Next();
57  }
58
59  LookupIterator(Handle<Object> receiver, Handle<Name> name,
60                 Handle<JSReceiver> holder,
61                 Configuration configuration = PROTOTYPE_CHAIN)
62      : configuration_(ComputeConfiguration(configuration, name)),
63        state_(NOT_FOUND),
64        property_details_(NONE, NORMAL, Representation::None()),
65        isolate_(name->GetIsolate()),
66        name_(name),
67        holder_map_(holder->map(), isolate_),
68        receiver_(receiver),
69        holder_(holder),
70        number_(DescriptorArray::kNotFound) {
71    Next();
72  }
73
74  Isolate* isolate() const { return isolate_; }
75  State state() const { return state_; }
76  Handle<Name> name() const { return name_; }
77
78  bool IsFound() const { return state_ != NOT_FOUND; }
79  void Next();
80  void NotFound() {
81    has_property_ = false;
82    state_ = NOT_FOUND;
83  }
84
85  Factory* factory() const { return isolate_->factory(); }
86  Handle<Object> GetReceiver() const { return receiver_; }
87  Handle<JSObject> GetStoreTarget() const;
88  bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
89  Handle<Map> transition_map() const {
90    DCHECK_EQ(TRANSITION, state_);
91    return transition_map_;
92  }
93  template <class T>
94  Handle<T> GetHolder() const {
95    DCHECK(IsFound());
96    return Handle<T>::cast(holder_);
97  }
98  Handle<JSReceiver> GetRoot() const;
99  bool HolderIsReceiverOrHiddenPrototype() const;
100
101  /* ACCESS_CHECK */
102  bool HasAccess(v8::AccessType access_type) const;
103
104  /* PROPERTY */
105  void PrepareForDataProperty(Handle<Object> value);
106  void PrepareTransitionToDataProperty(Handle<Object> value,
107                                       PropertyAttributes attributes,
108                                       Object::StoreFromKeyed store_mode);
109  bool IsCacheableTransition() {
110    bool cacheable =
111        state_ == TRANSITION && transition_map()->GetBackPointer()->IsMap();
112    if (cacheable) {
113      property_details_ = transition_map_->GetLastDescriptorDetails();
114      has_property_ = true;
115    }
116    return cacheable;
117  }
118  void ApplyTransitionToDataProperty();
119  void ReconfigureDataProperty(Handle<Object> value,
120                               PropertyAttributes attributes);
121  void TransitionToAccessorProperty(AccessorComponent component,
122                                    Handle<Object> accessor,
123                                    PropertyAttributes attributes);
124  PropertyDetails property_details() const {
125    DCHECK(has_property_);
126    return property_details_;
127  }
128  bool IsConfigurable() const { return property_details().IsConfigurable(); }
129  bool IsReadOnly() const { return property_details().IsReadOnly(); }
130  Representation representation() const {
131    return property_details().representation();
132  }
133  FieldIndex GetFieldIndex() const;
134  Handle<HeapType> GetFieldType() const;
135  int GetConstantIndex() const;
136  Handle<PropertyCell> GetPropertyCell() const;
137  Handle<Object> GetAccessors() const;
138  Handle<Object> GetDataValue() const;
139  void WriteDataValue(Handle<Object> value);
140
141  void InternalizeName();
142
143 private:
144  Handle<Map> GetReceiverMap() const;
145
146  MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
147  inline State LookupInHolder(Map* map, JSReceiver* holder);
148  Handle<Object> FetchValue() const;
149  void ReloadPropertyInformation();
150
151  bool IsBootstrapping() const;
152
153  bool check_hidden() const { return (configuration_ & kHidden) != 0; }
154  bool check_interceptor() const {
155    return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
156  }
157  bool check_prototype_chain() const {
158    return (configuration_ & kPrototypeChain) != 0;
159  }
160  int descriptor_number() const {
161    DCHECK(has_property_);
162    DCHECK(!holder_map_->is_dictionary_map());
163    return number_;
164  }
165  int dictionary_entry() const {
166    DCHECK(has_property_);
167    DCHECK(holder_map_->is_dictionary_map());
168    return number_;
169  }
170
171  static Configuration ComputeConfiguration(
172      Configuration configuration, Handle<Name> name) {
173    if (name->IsOwn()) {
174      return static_cast<Configuration>(configuration & HIDDEN);
175    } else {
176      return configuration;
177    }
178  }
179
180  // If configuration_ becomes mutable, update
181  // HolderIsReceiverOrHiddenPrototype.
182  Configuration configuration_;
183  State state_;
184  bool has_property_;
185  PropertyDetails property_details_;
186  Isolate* isolate_;
187  Handle<Name> name_;
188  Handle<Map> holder_map_;
189  Handle<Map> transition_map_;
190  Handle<Object> receiver_;
191  Handle<JSReceiver> holder_;
192
193  int number_;
194};
195
196
197} }  // namespace v8::internal
198
199#endif  // V8_LOOKUP_H_
200