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