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