5a5466ebe4e991193be0aa7d790d71f5faab1d44
[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     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, v8::internal::DATA, 0),
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, v8::internal::DATA, 0),
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 Handle<Map>::cast(transition_);
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     if (state_ != TRANSITION) return false;
111     return transition_->IsPropertyCell() ||
112            transition_map()->GetBackPointer()->IsMap();
113   }
114   void ApplyTransitionToDataProperty();
115   void ReconfigureDataProperty(Handle<Object> value,
116                                PropertyAttributes attributes);
117   void TransitionToAccessorProperty(AccessorComponent component,
118                                     Handle<Object> accessor,
119                                     PropertyAttributes attributes);
120   PropertyDetails property_details() const {
121     DCHECK(has_property_);
122     return property_details_;
123   }
124   bool IsConfigurable() const { return property_details().IsConfigurable(); }
125   bool IsReadOnly() const { return property_details().IsReadOnly(); }
126   Representation representation() const {
127     return property_details().representation();
128   }
129   FieldIndex GetFieldIndex() const;
130   Handle<HeapType> GetFieldType() const;
131   int GetAccessorIndex() const;
132   int GetConstantIndex() const;
133   Handle<PropertyCell> GetPropertyCell() const;
134   Handle<PropertyCell> GetTransitionPropertyCell() const {
135     DCHECK_EQ(TRANSITION, state_);
136     return Handle<PropertyCell>::cast(transition_);
137   }
138   Handle<Object> GetAccessors() const;
139   Handle<Object> GetDataValue() const;
140   // Usually returns the value that was passed in, but may perform
141   // non-observable modifications on it, such as internalize strings.
142   Handle<Object> WriteDataValue(Handle<Object> value);
143
144   // Checks whether the receiver is an indexed exotic object
145   // and name is a special numeric index.
146   bool IsSpecialNumericIndex() const;
147
148   void InternalizeName();
149
150  private:
151   Handle<Map> GetReceiverMap() const;
152
153   MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
154   inline State LookupInHolder(Map* map, JSReceiver* holder);
155   Handle<Object> FetchValue() const;
156   void ReloadPropertyInformation();
157
158   bool IsBootstrapping() const;
159
160   bool check_hidden() const { return (configuration_ & kHidden) != 0; }
161   bool check_interceptor() const {
162     return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
163   }
164   bool check_prototype_chain() const {
165     return (configuration_ & kPrototypeChain) != 0;
166   }
167   int descriptor_number() const {
168     DCHECK(has_property_);
169     DCHECK(!holder_map_->is_dictionary_map());
170     return number_;
171   }
172   int dictionary_entry() const {
173     DCHECK(has_property_);
174     DCHECK(holder_map_->is_dictionary_map());
175     return number_;
176   }
177
178   static Configuration ComputeConfiguration(
179       Configuration configuration, Handle<Name> name) {
180     if (name->IsOwn()) {
181       return static_cast<Configuration>(configuration &
182                                         HIDDEN_SKIP_INTERCEPTOR);
183     } else {
184       return configuration;
185     }
186   }
187
188   // If configuration_ becomes mutable, update
189   // HolderIsReceiverOrHiddenPrototype.
190   Configuration configuration_;
191   State state_;
192   bool has_property_;
193   PropertyDetails property_details_;
194   Isolate* isolate_;
195   Handle<Name> name_;
196   Handle<Map> holder_map_;
197   Handle<Object> transition_;
198   Handle<Object> receiver_;
199   Handle<JSReceiver> holder_;
200
201   int number_;
202 };
203
204
205 } }  // namespace v8::internal
206
207 #endif  // V8_LOOKUP_H_