handler-configuration.h 14.6 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_IC_HANDLER_CONFIGURATION_H_
#define V8_IC_HANDLER_CONFIGURATION_H_

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 13
#include "src/objects/elements-kind.h"
#include "src/objects/field-index.h"
14
#include "src/objects/objects.h"
15
#include "src/utils/utils.h"
16

17 18 19
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

20 21 22
namespace v8 {
namespace internal {

23 24
class JSProxy;

25 26 27 28 29 30 31 32 33 34 35
enum class WasmValueType {
  kI8,
  kI16,
  kI32,
  kU32,  // Used only for loading WasmArray length.
  kI64,
  kF32,
  kF64,
  kS128,

  kRef,
36
  kRefNull,
37 38 39 40

  kNumTypes
};

41 42 43 44
// A set of bit fields representing Smi handlers for loads and a HeapObject
// that represents load handlers that can't be encoded in a Smi.
// TODO(ishell): move to load-handler.h
class LoadHandler final : public DataHandler {
45
 public:
46
  DECL_CAST(LoadHandler)
47 48 49 50

  DECL_PRINTER(LoadHandler)
  DECL_VERIFIER(LoadHandler)

51
  enum class Kind {
52
    kElement,
53
    kIndexedString,
54
    kNormal,
55
    kGlobal,
56
    kField,
57
    kConstantFromPrototype,
58
    kAccessorFromPrototype,
59 60 61
    kNativeDataProperty,
    kApiGetter,
    kApiGetterHolderIsPrototype,
62
    kInterceptor,
63
    kSlow,
64
    kProxy,
65 66
    kNonExistent,
    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 73
  // chain. Ignored when loading from lookup start object.
  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 78 79 80
  // when loading value from prototype chain. Ignored when loading from lookup
  // start object.
  using LookupOnLookupStartObjectBits =
      DoAccessCheckOnLookupStartObjectBits::Next<bool, 1>;
81

82
  //
83
  // Encoding when KindBits contains 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 96 97 98 99 100
  using IsWasmStructBits = LookupOnLookupStartObjectBits::Next<bool, 1>;

  //
  // Encoding when KindBits contains kField and IsWasmStructBits is 0.
  //
  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 110 111 112 113
  //
  // Encoding when KindBits contains kField and IsWasmStructBits is 1.
  //
  using WasmFieldTypeBits = IsWasmStructBits::Next<WasmValueType, 4>;
  using WasmFieldOffsetBits = WasmFieldTypeBits::Next<unsigned, 20>;
  // Make sure we don't overflow the smi.
114
  static_assert(WasmFieldOffsetBits::kLastUsedBit < kSmiValueSize);
115

116 117 118
  //
  // Encoding when KindBits contains kElement or kIndexedString.
  //
119
  using AllowOutOfBoundsBits = LookupOnLookupStartObjectBits::Next<bool, 1>;
120

121
  //
122
  // Encoding when KindBits contains kElement.
123
  //
124 125 126 127 128 129
  using IsWasmArrayBits = AllowOutOfBoundsBits::Next<bool, 1>;

  //
  // Encoding when KindBits contains kElement and IsWasmArrayBits is 0.
  //
  using IsJsArrayBits = IsWasmArrayBits::Next<bool, 1>;
130 131
  using ConvertHoleBits = IsJsArrayBits::Next<bool, 1>;
  using ElementsKindBits = ConvertHoleBits::Next<ElementsKind, 8>;
132
  // Make sure we don't overflow the smi.
133
  static_assert(ElementsKindBits::kLastUsedBit < kSmiValueSize);
134

135 136 137 138 139
  //
  // Encoding when KindBits contains kElement and IsWasmArrayBits is 1.
  //
  using WasmArrayTypeBits = IsWasmArrayBits::Next<WasmValueType, 4>;
  // Make sure we don't overflow the smi.
140
  static_assert(WasmArrayTypeBits::kLastUsedBit < kSmiValueSize);
141

142 143 144
  //
  // Encoding when KindBits contains kModuleExport.
  //
145 146 147
  using ExportsIndexBits = LookupOnLookupStartObjectBits::Next<
      unsigned,
      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 155
  static inline Handle<Smi> LoadNormal(Isolate* isolate);

156 157 158
  // Creates a Smi-handler for loading a property from a global object.
  static inline Handle<Smi> LoadGlobal(Isolate* isolate);

159 160 161
  // Creates a Smi-handler for loading a property from an object with an
  // interceptor.
  static inline Handle<Smi> LoadInterceptor(Isolate* isolate);
162

163 164 165
  // Creates a Smi-handler for loading a property from a object.
  static inline Handle<Smi> LoadSlow(Isolate* isolate);

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 170
  // Creates a Smi-handler for loading a cached constant from fast
  // 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> LoadAccessorFromPrototype(Isolate* isolate);
175

176 177 178
  // Creates a Smi-handler for calling a getter on a proxy.
  static inline Handle<Smi> LoadProxy(Isolate* isolate);

179 180 181 182 183 184 185
  // Creates a Smi-handler for loading a native data property from fast object.
  static inline Handle<Smi> LoadNativeDataProperty(Isolate* isolate,
                                                   int descriptor);

  // Creates a Smi-handler for calling a native getter on a fast object.
  static inline Handle<Smi> LoadApiGetter(Isolate* isolate,
                                          bool holder_is_receiver);
186

187 188 189 190 191
  // Creates a Smi-handler for loading a Module export.
  // |index| is the index to the "value" slot in the Module's "exports"
  // dictionary.
  static inline Handle<Smi> LoadModuleExport(Isolate* isolate, int index);

192 193 194 195 196
  static inline Handle<Smi> LoadWasmStructField(Isolate* isolate,
                                                WasmValueType type, int offset);
  static inline Handle<Smi> LoadWasmArrayElement(Isolate* isolate,
                                                 WasmValueType type);

197 198 199 200 201
  // Creates a data handler that represents a load of a non-existent property.
  // {holder} is the object from which the property is loaded. If no holder is
  // needed (e.g., for "nonexistent"), null_value() may be passed in.
  static Handle<Object> LoadFullChain(Isolate* isolate,
                                      Handle<Map> receiver_map,
202
                                      const MaybeObjectHandle& holder,
203 204 205 206
                                      Handle<Smi> smi_handler);

  // Creates a data handler that represents a prototype chain check followed
  // by given Smi-handler that encoded a load from the holder.
207 208
  static Handle<Object> LoadFromPrototype(
      Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
209
      Handle<Smi> smi_handler,
210 211
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
212

213 214
  // Creates a Smi-handler for loading a non-existent property. Works only as
  // 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 219 220
  static inline Handle<Smi> LoadElement(Isolate* isolate,
                                        ElementsKind elements_kind,
                                        bool convert_hole_to_undefined,
221 222
                                        bool is_js_array,
                                        KeyedAccessLoadMode load_mode);
223

224
  // Creates a Smi-handler for loading from a String.
225
  static inline Handle<Smi> LoadIndexedString(Isolate* isolate,
226 227 228
                                              KeyedAccessLoadMode load_mode);

  // Decodes the KeyedAccessLoadMode from a {handler}.
229
  static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject handler);
230

231 232 233 234
#if defined(OBJECT_PRINT)
  static void PrintHandler(Object handler, std::ostream& os);
#endif  // defined(OBJECT_PRINT)

235
  OBJECT_CONSTRUCTORS(LoadHandler, DataHandler);
236 237
};

238 239 240 241
// A set of bit fields representing Smi handlers for stores and a HeapObject
// that represents store handlers that can't be encoded in a Smi.
// TODO(ishell): move to store-handler.h
class StoreHandler final : public DataHandler {
242
 public:
243
  DECL_CAST(StoreHandler)
244 245 246 247

  DECL_PRINTER(StoreHandler)
  DECL_VERIFIER(StoreHandler)

248
  enum class Kind {
249 250
    kField,
    kConstField,
251
    kAccessor,
252
    kNativeDataProperty,
253
    kSharedStructField,
254 255 256 257
    kApiSetter,
    kApiSetterHolderIsPrototype,
    kGlobalProxy,
    kNormal,
258 259
    kInterceptor,
    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 268
  // Defines whether access rights check should be done on lookup start object.
  using DoAccessCheckOnLookupStartObjectBits = KindBits::Next<bool, 1>;
269

270
  // Defines whether a lookup should be done on lookup start object before
271 272
  // proceeding to the prototype chain. Applicable to named property kinds only
  // when storing through prototype chain. Ignored when storing to holder.
273 274
  using LookupOnLookupStartObjectBits =
      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 301 302 303
  static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
                                       FieldIndex field_index,
                                       PropertyConstness constness,
                                       Representation representation);
304

305 306 307 308 309
  // Creates a Smi-handler for storing a field to a JSSharedStruct.
  static inline Handle<Smi> StoreSharedStructField(
      Isolate* isolate, int descriptor, FieldIndex field_index,
      Representation representation);

310 311 312 313 314
  // Create a store transition handler which doesn't check prototype chain.
  static MaybeObjectHandle StoreOwnTransition(Isolate* isolate,
                                              Handle<Map> transition_map);

  // Create a store transition handler with prototype chain validity cell check.
315 316
  static MaybeObjectHandle StoreTransition(Isolate* isolate,
                                           Handle<Map> transition_map);
317

318 319 320 321
  // Creates a Smi-handler for storing a native data property on a fast object.
  static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate,
                                                    int descriptor);

322 323 324
  // Creates a Smi-handler for calling a setter on a fast object.
  static inline Handle<Smi> StoreAccessor(Isolate* isolate, int descriptor);

325 326 327 328 329 330
  // Creates a Smi-handler for calling a native setter on a fast object.
  static inline Handle<Smi> StoreApiSetter(Isolate* isolate,
                                           bool holder_is_receiver);

  static Handle<Object> StoreThroughPrototype(
      Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
331
      Handle<Smi> smi_handler,
332 333
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
334

335 336 337 338
  static Handle<Object> StoreElementTransition(
      Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
      KeyedAccessStoreMode store_mode,
      MaybeHandle<Object> prev_validity_cell = MaybeHandle<Object>());
339

340 341
  static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map,
                                   Handle<JSProxy> proxy,
342
                                   Handle<JSReceiver> receiver);
343

344 345
  // Creates a handler for storing a property to the property cell of a global
  // object.
346
  static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell);
347 348 349 350

  // Creates a Smi-handler for storing a property to a global proxy object.
  static inline Handle<Smi> StoreGlobalProxy(Isolate* isolate);

351
  // Creates a Smi-handler for storing a property to a slow object.
352
  static inline Handle<Smi> StoreNormal(Isolate* isolate);
353

354 355 356
  // Creates a Smi-handler for storing a property to an interceptor.
  static inline Handle<Smi> StoreInterceptor(Isolate* isolate);

357 358 359 360 361 362
  static inline Handle<CodeT> StoreSloppyArgumentsBuiltin(
      Isolate* isolate, KeyedAccessStoreMode mode);
  static inline Handle<CodeT> StoreFastElementBuiltin(
      Isolate* isolate, KeyedAccessStoreMode mode);
  static inline Handle<CodeT> ElementsTransitionAndStoreBuiltin(
      Isolate* isolate, KeyedAccessStoreMode mode);
363

364
  // Creates a Smi-handler for storing a property.
365 366
  static inline Handle<Smi> StoreSlow(
      Isolate* isolate, KeyedAccessStoreMode store_mode = STANDARD_STORE);
367

368 369
  // Creates a Smi-handler for storing a property on a proxy.
  static inline Handle<Smi> StoreProxy(Isolate* isolate);
370
  static inline Smi StoreProxy();
371

372 373 374
  // Decodes the KeyedAccessStoreMode from a {handler}.
  static KeyedAccessStoreMode GetKeyedAccessStoreMode(MaybeObject handler);

375 376 377 378
#if defined(OBJECT_PRINT)
  static void PrintHandler(Object handler, std::ostream& os);
#endif  // defined(OBJECT_PRINT)

379 380 381
 private:
  static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind,
                                       int descriptor, FieldIndex field_index,
382
                                       Representation representation);
383

384
  OBJECT_CONSTRUCTORS(StoreHandler, DataHandler);
385 386
};

387 388 389 390
inline const char* WasmValueType2String(WasmValueType type);

std::ostream& operator<<(std::ostream& os, WasmValueType type);

391 392 393
}  // namespace internal
}  // namespace v8

394 395
#include "src/objects/object-macros-undef.h"

396
#endif  // V8_IC_HANDLER_CONFIGURATION_H_