handler-configuration.h 12 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 40
    kField,
    kConstant,
41
    kAccessor,
42 43 44
    kNativeDataProperty,
    kApiGetter,
    kApiGetterHolderIsPrototype,
45
    kInterceptor,
46
    kProxy,
47 48
    kNonExistent,
    kModuleExport
49
  };
50
  class KindBits : public BitField<Kind, 0, 4> {};
51

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

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
  class LookupOnReceiverBits
62
      : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};
63

64 65 66
  //
  // Encoding when KindBits contains kForConstants.
  //
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 78
  class IsInobjectBits : public BitField<bool, LookupOnReceiverBits::kNext, 1> {
  };
79 80
  class IsDoubleBits : public BitField<bool, IsInobjectBits::kNext, 1> {};
  // +1 here is to cover all possible JSObject header sizes.
81 82
  class FieldIndexBits : public BitField<unsigned, IsDoubleBits::kNext,
                                         kDescriptorIndexBitCount + 1> {};
83
  // Make sure we don't overflow the smi.
84
  STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize);
85

86 87 88
  //
  // Encoding when KindBits contains kElement or kIndexedString.
  //
89 90
  class AllowOutOfBoundsBits
      : public BitField<bool, LookupOnReceiverBits::kNext, 1> {};
91

92
  //
93
  // Encoding when KindBits contains kElement.
94
  //
95 96
  class IsJsArrayBits : public BitField<bool, AllowOutOfBoundsBits::kNext, 1> {
  };
97 98 99 100 101
  class ConvertHoleBits : public BitField<bool, IsJsArrayBits::kNext, 1> {};
  class ElementsKindBits
      : public BitField<ElementsKind, ConvertHoleBits::kNext, 8> {};
  // Make sure we don't overflow the smi.
  STATIC_ASSERT(ElementsKindBits::kNext <= kSmiValueSize);
102

103 104 105
  //
  // Encoding when KindBits contains kModuleExport.
  //
106 107 108
  class ExportsIndexBits
      : public BitField<unsigned, LookupOnReceiverBits::kNext,
                        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 115
  static inline Handle<Smi> LoadNormal(Isolate* isolate);

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

119 120 121
  // Creates a Smi-handler for loading a property from an object with an
  // interceptor.
  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 130 131
  // Creates a Smi-handler for calling a getter on a fast object.
  static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor);

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

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

143 144 145 146 147
  // 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);

148 149 150 151 152
  // 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,
153
                                      const MaybeObjectHandle& holder,
154 155 156 157 158
                                      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.
159 160
  static Handle<Object> LoadFromPrototype(
      Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
161
      Handle<Smi> smi_handler,
162 163
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
164

165 166
  // Creates a Smi-handler for loading a non-existent property. Works only as
  // 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 171 172
  static inline Handle<Smi> LoadElement(Isolate* isolate,
                                        ElementsKind elements_kind,
                                        bool convert_hole_to_undefined,
173 174
                                        bool is_js_array,
                                        KeyedAccessLoadMode load_mode);
175

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

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

183
  OBJECT_CONSTRUCTORS(LoadHandler, DataHandler);
184 185
};

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

  DECL_PRINTER(StoreHandler)
  DECL_VERIFIER(StoreHandler)

196
  enum Kind {
197 198 199
    kElement,
    kField,
    kConstField,
200
    kAccessor,
201
    kNativeDataProperty,
202 203 204 205
    kApiSetter,
    kApiSetterHolderIsPrototype,
    kGlobalProxy,
    kNormal,
206
    kProxy,
207
    kKindsNumber  // Keep last
208
  };
209
  class KindBits : public BitField<Kind, 0, 4> {};
210 211 212

  enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };

213
  // Applicable to kGlobalProxy, kProxy kinds.
214 215 216 217 218

  // Defines whether access rights check should be done on receiver object.
  class DoAccessCheckOnReceiverBits
      : public BitField<bool, KindBits::kNext, 1> {};

219 220 221 222 223 224
  // 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.
  class LookupOnReceiverBits
      : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};

225
  // Applicable to kField, kTransitionToField and kTransitionToConstant
226 227 228
  // kinds.

  // Index of a value entry in the descriptor array.
229 230
  class DescriptorBits : public BitField<unsigned, LookupOnReceiverBits::kNext,
                                         kDescriptorIndexBitCount> {};
231
  //
232
  // Encoding when KindBits contains kTransitionToConstant.
233
  //
234 235

  // Make sure we don't overflow the smi.
236
  STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize);
237 238

  //
239
  // Encoding when KindBits contains kField or kTransitionToField.
240
  //
241
  class IsInobjectBits : public BitField<bool, DescriptorBits::kNext, 1> {};
242 243 244
  class FieldRepresentationBits
      : public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {};
  // +1 here is to cover all possible JSObject header sizes.
245
  class FieldIndexBits
246
      : public BitField<unsigned, FieldRepresentationBits::kNext,
247
                        kDescriptorIndexBitCount + 1> {};
248
  // Make sure we don't overflow the smi.
249
  STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize);
250 251

  // Creates a Smi-handler for storing a field to fast object.
252 253 254 255
  static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
                                       FieldIndex field_index,
                                       PropertyConstness constness,
                                       Representation representation);
256

257 258
  static MaybeObjectHandle StoreTransition(Isolate* isolate,
                                           Handle<Map> transition_map);
259

260 261 262 263
  // Creates a Smi-handler for storing a native data property on a fast object.
  static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate,
                                                    int descriptor);

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

267 268 269 270 271 272
  // 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,
273
      Handle<Smi> smi_handler,
274 275
      MaybeObjectHandle maybe_data1 = MaybeObjectHandle(),
      MaybeObjectHandle maybe_data2 = MaybeObjectHandle());
276

277 278 279 280 281
  static Handle<Object> StoreElementTransition(Isolate* isolate,
                                               Handle<Map> receiver_map,
                                               Handle<Map> transition,
                                               KeyedAccessStoreMode store_mode);

282 283
  static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map,
                                   Handle<JSProxy> proxy,
284
                                   Handle<JSReceiver> receiver);
285

286 287
  // Creates a handler for storing a property to the property cell of a global
  // object.
288
  static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell);
289 290 291 292

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

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

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_