handler-configuration.h 11.8 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/objects/data-handler.h"
11 12
#include "src/objects/elements-kind.h"
#include "src/objects/field-index.h"
13
#include "src/objects/objects.h"
14
#include "src/utils/utils.h"
15

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

19 20 21
namespace v8 {
namespace internal {

22 23
class JSProxy;

24 25 26 27
// 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 {
28
 public:
29
  DECL_CAST(LoadHandler)
30 31 32 33

  DECL_PRINTER(LoadHandler)
  DECL_VERIFIER(LoadHandler)

34
  enum Kind {
35
    kElement,
36
    kIndexedString,
37
    kNormal,
38
    kGlobal,
39
    kField,
40
    kConstantFromPrototype,
41
    kAccessor,
42 43 44
    kNativeDataProperty,
    kApiGetter,
    kApiGetterHolderIsPrototype,
45
    kInterceptor,
46
    kSlow,
47
    kProxy,
48 49
    kNonExistent,
    kModuleExport
50
  };
51
  using KindBits = BitField<Kind, 0, 4>;
52

53
  // Defines whether access rights check should be done on receiver object.
54 55
  // Applicable to named property kinds only when loading value from prototype
  // chain. Ignored when loading from holder.
56
  using DoAccessCheckOnReceiverBits = KindBits::Next<bool, 1>;
57

58
  // Defines whether a lookup should be done on receiver object before
59 60
  // proceeding to the prototype chain. Applicable to named property kinds only
  // when loading value from prototype chain. Ignored when loading from holder.
61
  using LookupOnReceiverBits = DoAccessCheckOnReceiverBits::Next<bool, 1>;
62

63 64 65
  //
  // Encoding when KindBits contains kForConstants.
  //
66

67
  // Index of a value entry in the descriptor array.
68
  using DescriptorBits =
69
      LookupOnReceiverBits::Next<unsigned, kDescriptorIndexBitCount>;
70
  // Make sure we don't overflow the smi.
71
  STATIC_ASSERT(DescriptorBits::kLastUsedBit < kSmiValueSize);
72

73
  //
74
  // Encoding when KindBits contains kField.
75
  //
76 77
  using IsInobjectBits = LookupOnReceiverBits::Next<bool, 1>;
  using IsDoubleBits = IsInobjectBits::Next<bool, 1>;
78
  // +1 here is to cover all possible JSObject header sizes.
79
  using FieldIndexBits =
80
      IsDoubleBits::Next<unsigned, kDescriptorIndexBitCount + 1>;
81
  // Make sure we don't overflow the smi.
82
  STATIC_ASSERT(FieldIndexBits::kLastUsedBit < kSmiValueSize);
83

84 85 86
  //
  // Encoding when KindBits contains kElement or kIndexedString.
  //
87
  using AllowOutOfBoundsBits = LookupOnReceiverBits::Next<bool, 1>;
88

89
  //
90
  // Encoding when KindBits contains kElement.
91
  //
92 93 94
  using IsJsArrayBits = AllowOutOfBoundsBits::Next<bool, 1>;
  using ConvertHoleBits = IsJsArrayBits::Next<bool, 1>;
  using ElementsKindBits = ConvertHoleBits::Next<ElementsKind, 8>;
95
  // Make sure we don't overflow the smi.
96
  STATIC_ASSERT(ElementsKindBits::kLastUsedBit < kSmiValueSize);
97

98 99 100
  //
  // Encoding when KindBits contains kModuleExport.
  //
101 102
  using ExportsIndexBits = LookupOnReceiverBits::Next<
      unsigned, kSmiValueSize - LookupOnReceiverBits::kLastUsedBit - 1>;
103

104
  // Decodes kind from Smi-handler.
105
  static inline Kind GetHandlerKind(Smi smi_handler);
106

107
  // Creates a Smi-handler for loading a property from a slow object.
108 109
  static inline Handle<Smi> LoadNormal(Isolate* isolate);

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

113 114 115
  // Creates a Smi-handler for loading a property from an object with an
  // interceptor.
  static inline Handle<Smi> LoadInterceptor(Isolate* isolate);
116

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

120
  // Creates a Smi-handler for loading a field from fast object.
121
  static inline Handle<Smi> LoadField(Isolate* isolate, FieldIndex field_index);
122

123 124 125
  // Creates a Smi-handler for loading a cached constant from fast
  // prototype object.
  static inline Handle<Smi> LoadConstantFromPrototype(Isolate* isolate);
126

127 128 129
  // Creates a Smi-handler for calling a getter on a fast object.
  static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor);

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

133 134 135 136 137 138 139
  // 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);
140

141 142 143 144 145
  // 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);

146 147 148 149 150
  // 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,
151
                                      const MaybeObjectHandle& holder,
152 153 154 155 156
                                      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.
  // Can be used only if GetPrototypeCheckCount() returns non negative value.
157 158
  static Handle<Object> LoadFromPrototype(
      Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
159
      Handle<Smi> smi_handler,
160 161
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
162

163 164
  // Creates a Smi-handler for loading a non-existent property. Works only as
  // a part of prototype chain check.
165
  static inline Handle<Smi> LoadNonExistent(Isolate* isolate);
166

167
  // Creates a Smi-handler for loading an element.
168 169 170
  static inline Handle<Smi> LoadElement(Isolate* isolate,
                                        ElementsKind elements_kind,
                                        bool convert_hole_to_undefined,
171 172
                                        bool is_js_array,
                                        KeyedAccessLoadMode load_mode);
173

174
  // Creates a Smi-handler for loading from a String.
175
  static inline Handle<Smi> LoadIndexedString(Isolate* isolate,
176 177 178
                                              KeyedAccessLoadMode load_mode);

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

181
  OBJECT_CONSTRUCTORS(LoadHandler, DataHandler);
182 183
};

184 185 186 187
// 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 {
188
 public:
189
  DECL_CAST(StoreHandler)
190 191 192 193

  DECL_PRINTER(StoreHandler)
  DECL_VERIFIER(StoreHandler)

194
  enum Kind {
195 196 197
    kElement,
    kField,
    kConstField,
198
    kAccessor,
199
    kNativeDataProperty,
200 201 202 203
    kApiSetter,
    kApiSetterHolderIsPrototype,
    kGlobalProxy,
    kNormal,
204 205
    kInterceptor,
    kSlow,
206
    kProxy,
207
    kKindsNumber  // Keep last
208
  };
209
  using KindBits = BitField<Kind, 0, 4>;
210

211
  // Applicable to kGlobalProxy, kProxy kinds.
212 213

  // Defines whether access rights check should be done on receiver object.
214
  using DoAccessCheckOnReceiverBits = KindBits::Next<bool, 1>;
215

216 217 218
  // Defines whether a lookup should be done on receiver object before
  // proceeding to the prototype chain. Applicable to named property kinds only
  // when storing through prototype chain. Ignored when storing to holder.
219
  using LookupOnReceiverBits = DoAccessCheckOnReceiverBits::Next<bool, 1>;
220

221
  // Applicable to kField, kTransitionToField and kTransitionToConstant
222 223 224
  // kinds.

  // Index of a value entry in the descriptor array.
225
  using DescriptorBits =
226
      LookupOnReceiverBits::Next<unsigned, kDescriptorIndexBitCount>;
227
  //
228
  // Encoding when KindBits contains kTransitionToConstant.
229
  //
230 231

  // Make sure we don't overflow the smi.
232
  STATIC_ASSERT(DescriptorBits::kLastUsedBit < kSmiValueSize);
233 234

  //
235
  // Encoding when KindBits contains kField or kTransitionToField.
236
  //
237
  using IsInobjectBits = DescriptorBits::Next<bool, 1>;
238
  using RepresentationBits = IsInobjectBits::Next<Representation::Kind, 3>;
239
  // +1 here is to cover all possible JSObject header sizes.
240
  using FieldIndexBits =
241
      RepresentationBits::Next<unsigned, kDescriptorIndexBitCount + 1>;
242
  // Make sure we don't overflow the smi.
243
  STATIC_ASSERT(FieldIndexBits::kLastUsedBit < kSmiValueSize);
244 245

  // Creates a Smi-handler for storing a field to fast object.
246 247 248 249
  static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
                                       FieldIndex field_index,
                                       PropertyConstness constness,
                                       Representation representation);
250

251 252
  static MaybeObjectHandle StoreTransition(Isolate* isolate,
                                           Handle<Map> transition_map);
253

254 255 256 257
  // Creates a Smi-handler for storing a native data property on a fast object.
  static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate,
                                                    int descriptor);

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

261 262 263 264 265 266
  // 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,
267
      Handle<Smi> smi_handler,
268 269
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
270

271 272 273 274 275
  static Handle<Object> StoreElementTransition(Isolate* isolate,
                                               Handle<Map> receiver_map,
                                               Handle<Map> transition,
                                               KeyedAccessStoreMode store_mode);

276 277
  static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map,
                                   Handle<JSProxy> proxy,
278
                                   Handle<JSReceiver> receiver);
279

280 281
  // Creates a handler for storing a property to the property cell of a global
  // object.
282
  static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell);
283 284 285 286

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

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

290 291 292 293 294 295
  // Creates a Smi-handler for storing a property to an interceptor.
  static inline Handle<Smi> StoreInterceptor(Isolate* isolate);

  // Creates a Smi-handler for storing a property.
  static inline Handle<Smi> StoreSlow(Isolate* isolate);

296 297 298
  // Creates a Smi-handler for storing a property on a proxy.
  static inline Handle<Smi> StoreProxy(Isolate* isolate);

299 300 301
 private:
  static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind,
                                       int descriptor, FieldIndex field_index,
302
                                       Representation representation);
303

304
  OBJECT_CONSTRUCTORS(StoreHandler, DataHandler);
305 306
};

307 308 309
}  // namespace internal
}  // namespace v8

310 311
#include "src/objects/object-macros-undef.h"

312
#endif  // V8_IC_HANDLER_CONFIGURATION_H_