deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / 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/factory.h"
9 #include "src/isolate.h"
10 #include "src/objects.h"
11
12 namespace v8 {
13 namespace internal {
14
15 class 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     INTEGER_INDEXED_EXOTIC,
35     INTERCEPTOR,
36     JSPROXY,
37     NOT_FOUND,
38     ACCESSOR,
39     DATA,
40     TRANSITION,
41     // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
42     // PROPERTY lookup.
43     BEFORE_PROPERTY = INTERCEPTOR
44   };
45
46   LookupIterator(Handle<Object> receiver, Handle<Name> name,
47                  Configuration configuration = PROTOTYPE_CHAIN)
48       : configuration_(ComputeConfiguration(configuration, name)),
49         state_(NOT_FOUND),
50         exotic_index_state_(ExoticIndexState::kUninitialized),
51         interceptor_state_(InterceptorState::kUninitialized),
52         property_details_(PropertyDetails::Empty()),
53         isolate_(name->GetIsolate()),
54         name_(name),
55         receiver_(receiver),
56         holder_(GetRoot(receiver_, isolate_)),
57         holder_map_(holder_->map(), isolate_),
58         initial_holder_(holder_),
59         number_(DescriptorArray::kNotFound) {
60     Next();
61   }
62
63   LookupIterator(Handle<Object> receiver, Handle<Name> name,
64                  Handle<JSReceiver> holder,
65                  Configuration configuration = PROTOTYPE_CHAIN)
66       : configuration_(ComputeConfiguration(configuration, name)),
67         state_(NOT_FOUND),
68         exotic_index_state_(ExoticIndexState::kUninitialized),
69         interceptor_state_(InterceptorState::kUninitialized),
70         property_details_(PropertyDetails::Empty()),
71         isolate_(name->GetIsolate()),
72         name_(name),
73         receiver_(receiver),
74         holder_(holder),
75         holder_map_(holder_->map(), isolate_),
76         initial_holder_(holder_),
77         number_(DescriptorArray::kNotFound) {
78     Next();
79   }
80
81   Isolate* isolate() const { return isolate_; }
82   State state() const { return state_; }
83   Handle<Name> name() const { return name_; }
84
85   bool IsFound() const { return state_ != NOT_FOUND; }
86   void Next();
87   void NotFound() {
88     has_property_ = false;
89     state_ = NOT_FOUND;
90   }
91
92   Factory* factory() const { return isolate_->factory(); }
93   Handle<Object> GetReceiver() const { return receiver_; }
94   Handle<JSObject> GetStoreTarget() const;
95   bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
96   Handle<Map> transition_map() const {
97     DCHECK_EQ(TRANSITION, state_);
98     return Handle<Map>::cast(transition_);
99   }
100   template <class T>
101   Handle<T> GetHolder() const {
102     DCHECK(IsFound());
103     return Handle<T>::cast(holder_);
104   }
105   static Handle<JSReceiver> GetRoot(Handle<Object> receiver, Isolate* isolate);
106   bool HolderIsReceiverOrHiddenPrototype() const;
107
108   /* ACCESS_CHECK */
109   bool HasAccess() const;
110
111   /* PROPERTY */
112   void PrepareForDataProperty(Handle<Object> value);
113   void PrepareTransitionToDataProperty(Handle<Object> value,
114                                        PropertyAttributes attributes,
115                                        Object::StoreFromKeyed store_mode);
116   bool IsCacheableTransition() {
117     if (state_ != TRANSITION) return false;
118     return transition_->IsPropertyCell() ||
119            transition_map()->GetBackPointer()->IsMap();
120   }
121   void ApplyTransitionToDataProperty();
122   void ReconfigureDataProperty(Handle<Object> value,
123                                PropertyAttributes attributes);
124   void TransitionToAccessorProperty(AccessorComponent component,
125                                     Handle<Object> accessor,
126                                     PropertyAttributes attributes);
127   PropertyDetails property_details() const {
128     DCHECK(has_property_);
129     return property_details_;
130   }
131   bool IsConfigurable() const { return property_details().IsConfigurable(); }
132   bool IsReadOnly() const { return property_details().IsReadOnly(); }
133   Representation representation() const {
134     return property_details().representation();
135   }
136   FieldIndex GetFieldIndex() const;
137   Handle<HeapType> GetFieldType() const;
138   int GetAccessorIndex() const;
139   int GetConstantIndex() const;
140   Handle<PropertyCell> GetPropertyCell() const;
141   Handle<Object> GetAccessors() const;
142   Handle<Object> GetDataValue() const;
143   // Usually returns the value that was passed in, but may perform
144   // non-observable modifications on it, such as internalize strings.
145   Handle<Object> WriteDataValue(Handle<Object> value);
146   void InternalizeName();
147
148  private:
149   enum class InterceptorState {
150     kUninitialized,
151     kSkipNonMasking,
152     kProcessNonMasking
153   };
154
155   Handle<Map> GetReceiverMap() const;
156
157   MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
158   inline State LookupInHolder(Map* map, JSReceiver* holder);
159   void RestartLookupForNonMaskingInterceptors();
160   State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
161   Handle<Object> FetchValue() const;
162   void ReloadPropertyInformation();
163   bool SkipInterceptor(JSObject* holder);
164
165   bool IsBootstrapping() const;
166
167   bool check_hidden() const { return (configuration_ & kHidden) != 0; }
168   bool check_interceptor() const {
169     return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
170   }
171   bool check_prototype_chain() const {
172     return (configuration_ & kPrototypeChain) != 0;
173   }
174   int descriptor_number() const {
175     DCHECK(has_property_);
176     DCHECK(!holder_map_->is_dictionary_map());
177     return number_;
178   }
179   int dictionary_entry() const {
180     DCHECK(has_property_);
181     DCHECK(holder_map_->is_dictionary_map());
182     return number_;
183   }
184
185   static Configuration ComputeConfiguration(
186       Configuration configuration, Handle<Name> name) {
187     if (name->IsOwn()) {
188       return static_cast<Configuration>(configuration &
189                                         HIDDEN_SKIP_INTERCEPTOR);
190     } else {
191       return configuration;
192     }
193   }
194
195   enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex };
196   bool IsIntegerIndexedExotic(JSReceiver* holder);
197
198   // If configuration_ becomes mutable, update
199   // HolderIsReceiverOrHiddenPrototype.
200   const Configuration configuration_;
201   State state_;
202   bool has_property_;
203   ExoticIndexState exotic_index_state_;
204   InterceptorState interceptor_state_;
205   PropertyDetails property_details_;
206   Isolate* const isolate_;
207   Handle<Name> name_;
208   Handle<Object> transition_;
209   const Handle<Object> receiver_;
210   Handle<JSReceiver> holder_;
211   Handle<Map> holder_map_;
212   const Handle<JSReceiver> initial_holder_;
213   int number_;
214 };
215
216
217 } }  // namespace v8::internal
218
219 #endif  // V8_LOOKUP_H_