blob: 14ca010d31d8477d531b0215aef03dd4073f1d61 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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_