blob: a2e0d4d79903def1f50889e34195413b6b34a7cb [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),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040049 property_details_(NONE, FIELD, 0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 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),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064 property_details_(NONE, FIELD, 0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 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;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 // Usually returns the value that was passed in, but may perform
140 // non-observable modifications on it, such as internalize strings.
141 Handle<Object> WriteDataValue(Handle<Object> value);
142
143 // Checks whether the receiver is an indexed exotic object
144 // and name is a special numeric index.
145 bool IsSpecialNumericIndex() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146
147 void InternalizeName();
148
149 private:
150 Handle<Map> GetReceiverMap() const;
151
152 MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
153 inline State LookupInHolder(Map* map, JSReceiver* holder);
154 Handle<Object> FetchValue() const;
155 void ReloadPropertyInformation();
156
157 bool IsBootstrapping() const;
158
159 bool check_hidden() const { return (configuration_ & kHidden) != 0; }
160 bool check_interceptor() const {
161 return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
162 }
163 bool check_prototype_chain() const {
164 return (configuration_ & kPrototypeChain) != 0;
165 }
166 int descriptor_number() const {
167 DCHECK(has_property_);
168 DCHECK(!holder_map_->is_dictionary_map());
169 return number_;
170 }
171 int dictionary_entry() const {
172 DCHECK(has_property_);
173 DCHECK(holder_map_->is_dictionary_map());
174 return number_;
175 }
176
177 static Configuration ComputeConfiguration(
178 Configuration configuration, Handle<Name> name) {
179 if (name->IsOwn()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180 return static_cast<Configuration>(configuration &
181 HIDDEN_SKIP_INTERCEPTOR);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 } else {
183 return configuration;
184 }
185 }
186
187 // If configuration_ becomes mutable, update
188 // HolderIsReceiverOrHiddenPrototype.
189 Configuration configuration_;
190 State state_;
191 bool has_property_;
192 PropertyDetails property_details_;
193 Isolate* isolate_;
194 Handle<Name> name_;
195 Handle<Map> holder_map_;
196 Handle<Map> transition_map_;
197 Handle<Object> receiver_;
198 Handle<JSReceiver> holder_;
199
200 int number_;
201};
202
203
204} } // namespace v8::internal
205
206#endif // V8_LOOKUP_H_