• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_IC_HANDLER_CONFIGURATION_H_
6 #define V8_IC_HANDLER_CONFIGURATION_H_
7 
8 #include "src/elements-kind.h"
9 #include "src/field-index.h"
10 #include "src/globals.h"
11 #include "src/maybe-handles.h"
12 #include "src/objects.h"
13 #include "src/objects/data-handler.h"
14 #include "src/utils.h"
15 
16 // Has to be the last include (doesn't have include guards):
17 #include "src/objects/object-macros.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 class JSProxy;
23 
24 // A set of bit fields representing Smi handlers for loads and a HeapObject
25 // that represents load handlers that can't be encoded in a Smi.
26 // TODO(ishell): move to load-handler.h
27 class LoadHandler final : public DataHandler {
28  public:
29   DECL_CAST(LoadHandler)
30 
31   DECL_PRINTER(LoadHandler)
32   DECL_VERIFIER(LoadHandler)
33 
34   enum Kind {
35     kElement,
36     kIndexedString,
37     kNormal,
38     kGlobal,
39     kField,
40     kConstant,
41     kAccessor,
42     kNativeDataProperty,
43     kApiGetter,
44     kApiGetterHolderIsPrototype,
45     kInterceptor,
46     kProxy,
47     kNonExistent,
48     kModuleExport
49   };
50   class KindBits : public BitField<Kind, 0, 4> {};
51 
52   // Defines whether access rights check should be done on receiver object.
53   // Applicable to named property kinds only when loading value from prototype
54   // chain. Ignored when loading from holder.
55   class DoAccessCheckOnReceiverBits
56       : public BitField<bool, KindBits::kNext, 1> {};
57 
58   // Defines whether a lookup should be done on receiver object before
59   // proceeding to the prototype chain. Applicable to named property kinds only
60   // when loading value from prototype chain. Ignored when loading from holder.
61   class LookupOnReceiverBits
62       : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};
63 
64   //
65   // Encoding when KindBits contains kForConstants.
66   //
67 
68   // Index of a value entry in the descriptor array.
69   class DescriptorBits : public BitField<unsigned, LookupOnReceiverBits::kNext,
70                                          kDescriptorIndexBitCount> {};
71   // Make sure we don't overflow the smi.
72   STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
73 
74   //
75   // Encoding when KindBits contains kField.
76   //
77   class IsInobjectBits : public BitField<bool, LookupOnReceiverBits::kNext, 1> {
78   };
79   class IsDoubleBits : public BitField<bool, IsInobjectBits::kNext, 1> {};
80   // +1 here is to cover all possible JSObject header sizes.
81   class FieldIndexBits : public BitField<unsigned, IsDoubleBits::kNext,
82                                          kDescriptorIndexBitCount + 1> {};
83   // Make sure we don't overflow the smi.
84   STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize);
85 
86   //
87   // Encoding when KindBits contains kElement or kIndexedString.
88   //
89   class AllowOutOfBoundsBits
90       : public BitField<bool, LookupOnReceiverBits::kNext, 1> {};
91 
92   //
93   // Encoding when KindBits contains kElement.
94   //
95   class IsJsArrayBits : public BitField<bool, AllowOutOfBoundsBits::kNext, 1> {
96   };
97   class ConvertHoleBits : public BitField<bool, IsJsArrayBits::kNext, 1> {};
98   class ElementsKindBits
99       : public BitField<ElementsKind, ConvertHoleBits::kNext, 8> {};
100   // Make sure we don't overflow the smi.
101   STATIC_ASSERT(ElementsKindBits::kNext <= kSmiValueSize);
102 
103   //
104   // Encoding when KindBits contains kModuleExport.
105   //
106   class ExportsIndexBits
107       : public BitField<unsigned, LookupOnReceiverBits::kNext,
108                         kSmiValueSize - LookupOnReceiverBits::kNext> {};
109 
110   // Decodes kind from Smi-handler.
111   static inline Kind GetHandlerKind(Smi* smi_handler);
112 
113   // Creates a Smi-handler for loading a property from a slow object.
114   static inline Handle<Smi> LoadNormal(Isolate* isolate);
115 
116   // Creates a Smi-handler for loading a property from a global object.
117   static inline Handle<Smi> LoadGlobal(Isolate* isolate);
118 
119   // Creates a Smi-handler for loading a property from an object with an
120   // interceptor.
121   static inline Handle<Smi> LoadInterceptor(Isolate* isolate);
122 
123   // Creates a Smi-handler for loading a field from fast object.
124   static inline Handle<Smi> LoadField(Isolate* isolate, FieldIndex field_index);
125 
126   // Creates a Smi-handler for loading a constant from fast object.
127   static inline Handle<Smi> LoadConstant(Isolate* isolate, int descriptor);
128 
129   // Creates a Smi-handler for calling a getter on a fast object.
130   static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor);
131 
132   // Creates a Smi-handler for calling a getter on a proxy.
133   static inline Handle<Smi> LoadProxy(Isolate* isolate);
134 
135   // Creates a Smi-handler for loading a native data property from fast object.
136   static inline Handle<Smi> LoadNativeDataProperty(Isolate* isolate,
137                                                    int descriptor);
138 
139   // Creates a Smi-handler for calling a native getter on a fast object.
140   static inline Handle<Smi> LoadApiGetter(Isolate* isolate,
141                                           bool holder_is_receiver);
142 
143   // Creates a Smi-handler for loading a Module export.
144   // |index| is the index to the "value" slot in the Module's "exports"
145   // dictionary.
146   static inline Handle<Smi> LoadModuleExport(Isolate* isolate, int index);
147 
148   // Creates a data handler that represents a load of a non-existent property.
149   // {holder} is the object from which the property is loaded. If no holder is
150   // needed (e.g., for "nonexistent"), null_value() may be passed in.
151   static Handle<Object> LoadFullChain(Isolate* isolate,
152                                       Handle<Map> receiver_map,
153                                       MaybeObjectHandle holder,
154                                       Handle<Smi> smi_handler);
155 
156   // Creates a data handler that represents a prototype chain check followed
157   // by given Smi-handler that encoded a load from the holder.
158   // Can be used only if GetPrototypeCheckCount() returns non negative value.
159   static Handle<Object> LoadFromPrototype(
160       Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
161       Handle<Smi> smi_handler,
162       MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
163       MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
164 
165   // Creates a Smi-handler for loading a non-existent property. Works only as
166   // a part of prototype chain check.
167   static inline Handle<Smi> LoadNonExistent(Isolate* isolate);
168 
169   // Creates a Smi-handler for loading an element.
170   static inline Handle<Smi> LoadElement(Isolate* isolate,
171                                         ElementsKind elements_kind,
172                                         bool convert_hole_to_undefined,
173                                         bool is_js_array,
174                                         KeyedAccessLoadMode load_mode);
175 
176   // Creates a Smi-handler for loading from a String.
177   static inline Handle<Smi> LoadIndexedString(Isolate* isolate,
178                                               KeyedAccessLoadMode load_mode);
179 
180   // Decodes the KeyedAccessLoadMode from a {handler}.
181   static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject* handler);
182 };
183 
184 // A set of bit fields representing Smi handlers for stores and a HeapObject
185 // that represents store handlers that can't be encoded in a Smi.
186 // TODO(ishell): move to store-handler.h
187 class StoreHandler final : public DataHandler {
188  public:
189   DECL_CAST(StoreHandler)
190 
191   DECL_PRINTER(StoreHandler)
192   DECL_VERIFIER(StoreHandler)
193 
194   enum Kind {
195     kElement,
196     kField,
197     kConstField,
198     kAccessor,
199     kNativeDataProperty,
200     kApiSetter,
201     kApiSetterHolderIsPrototype,
202     kGlobalProxy,
203     kNormal,
204     kProxy,
205     kKindsNumber  // Keep last
206   };
207   class KindBits : public BitField<Kind, 0, 4> {};
208 
209   enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
210 
211   // Applicable to kGlobalProxy, kProxy kinds.
212 
213   // Defines whether access rights check should be done on receiver object.
214   class DoAccessCheckOnReceiverBits
215       : public BitField<bool, KindBits::kNext, 1> {};
216 
217   // Defines whether a lookup should be done on receiver object before
218   // proceeding to the prototype chain. Applicable to named property kinds only
219   // when storing through prototype chain. Ignored when storing to holder.
220   class LookupOnReceiverBits
221       : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};
222 
223   // Applicable to kField, kTransitionToField and kTransitionToConstant
224   // kinds.
225 
226   // Index of a value entry in the descriptor array.
227   class DescriptorBits : public BitField<unsigned, LookupOnReceiverBits::kNext,
228                                          kDescriptorIndexBitCount> {};
229   //
230   // Encoding when KindBits contains kTransitionToConstant.
231   //
232 
233   // Make sure we don't overflow the smi.
234   STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
235 
236   //
237   // Encoding when KindBits contains kField or kTransitionToField.
238   //
239   class IsInobjectBits : public BitField<bool, DescriptorBits::kNext, 1> {};
240   class FieldRepresentationBits
241       : public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {};
242   // +1 here is to cover all possible JSObject header sizes.
243   class FieldIndexBits
244       : public BitField<unsigned, FieldRepresentationBits::kNext,
245                         kDescriptorIndexBitCount + 1> {};
246   // Make sure we don't overflow the smi.
247   STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize);
248 
249   // Creates a Smi-handler for storing a field to fast object.
250   static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
251                                        FieldIndex field_index,
252                                        PropertyConstness constness,
253                                        Representation representation);
254 
255   static MaybeObjectHandle StoreTransition(Isolate* isolate,
256                                            Handle<Map> transition_map);
257 
258   // Creates a Smi-handler for storing a native data property on a fast object.
259   static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate,
260                                                     int descriptor);
261 
262   // Creates a Smi-handler for calling a setter on a fast object.
263   static inline Handle<Smi> StoreAccessor(Isolate* isolate, int descriptor);
264 
265   // Creates a Smi-handler for calling a native setter on a fast object.
266   static inline Handle<Smi> StoreApiSetter(Isolate* isolate,
267                                            bool holder_is_receiver);
268 
269   static Handle<Object> StoreThroughPrototype(
270       Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
271       Handle<Smi> smi_handler,
272       MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
273       MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
274 
275   static Handle<Object> StoreElementTransition(Isolate* isolate,
276                                                Handle<Map> receiver_map,
277                                                Handle<Map> transition,
278                                                KeyedAccessStoreMode store_mode);
279 
280   static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map,
281                                    Handle<JSProxy> proxy,
282                                    Handle<JSReceiver> receiver);
283 
284   // Creates a handler for storing a property to the property cell of a global
285   // object.
286   static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell);
287 
288   // Creates a Smi-handler for storing a property to a global proxy object.
289   static inline Handle<Smi> StoreGlobalProxy(Isolate* isolate);
290 
291   // Creates a Smi-handler for storing a property to a slow object.
292   static inline Handle<Smi> StoreNormal(Isolate* isolate);
293 
294   // Creates a Smi-handler for storing a property on a proxy.
295   static inline Handle<Smi> StoreProxy(Isolate* isolate);
296 
297  private:
298   static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind,
299                                        int descriptor, FieldIndex field_index,
300                                        Representation representation);
301 };
302 
303 }  // namespace internal
304 }  // namespace v8
305 
306 #include "src/objects/object-macros-undef.h"
307 
308 #endif  // V8_IC_HANDLER_CONFIGURATION_H_
309