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