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