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/elements-kind.h" 9 #include "src/field-index.h" 10 #include "src/globals.h" 11 #include "src/maybe-handles.h" 12 #include "src/objects.h" 13 #include "src/objects/data-handler.h" 14 #include "src/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 kConstant, 41 kAccessor, 42 kNativeDataProperty, 43 kApiGetter, 44 kApiGetterHolderIsPrototype, 45 kInterceptor, 46 kProxy, 47 kNonExistent, 48 kModuleExport 49 }; 50 class KindBits : public BitField<Kind, 0, 4> {}; 51 52 // Defines whether access rights check should be done on receiver object. 53 // Applicable to named property kinds only when loading value from prototype 54 // chain. Ignored when loading from holder. 55 class DoAccessCheckOnReceiverBits 56 : public BitField<bool, KindBits::kNext, 1> {}; 57 58 // Defines whether a lookup should be done on receiver 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 holder. 61 class LookupOnReceiverBits 62 : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {}; 63 64 // 65 // Encoding when KindBits contains kForConstants. 66 // 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 class IsInobjectBits : public BitField<bool, LookupOnReceiverBits::kNext, 1> { 78 }; 79 class IsDoubleBits : public BitField<bool, IsInobjectBits::kNext, 1> {}; 80 // +1 here is to cover all possible JSObject header sizes. 81 class FieldIndexBits : public BitField<unsigned, IsDoubleBits::kNext, 82 kDescriptorIndexBitCount + 1> {}; 83 // Make sure we don't overflow the smi. 84 STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize); 85 86 // 87 // Encoding when KindBits contains kElement or kIndexedString. 88 // 89 class AllowOutOfBoundsBits 90 : public BitField<bool, LookupOnReceiverBits::kNext, 1> {}; 91 92 // 93 // Encoding when KindBits contains kElement. 94 // 95 class IsJsArrayBits : public BitField<bool, AllowOutOfBoundsBits::kNext, 1> { 96 }; 97 class ConvertHoleBits : public BitField<bool, IsJsArrayBits::kNext, 1> {}; 98 class ElementsKindBits 99 : public BitField<ElementsKind, ConvertHoleBits::kNext, 8> {}; 100 // Make sure we don't overflow the smi. 101 STATIC_ASSERT(ElementsKindBits::kNext <= kSmiValueSize); 102 103 // 104 // Encoding when KindBits contains kModuleExport. 105 // 106 class ExportsIndexBits 107 : public BitField<unsigned, LookupOnReceiverBits::kNext, 108 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 static inline Handle<Smi> LoadNormal(Isolate* isolate); 115 116 // Creates a Smi-handler for loading a property from a global object. 117 static inline Handle<Smi> LoadGlobal(Isolate* isolate); 118 119 // Creates a Smi-handler for loading a property from an object with an 120 // interceptor. 121 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 // Creates a Smi-handler for calling a getter on a fast object. 130 static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor); 131 132 // Creates a Smi-handler for calling a getter on a proxy. 133 static inline Handle<Smi> LoadProxy(Isolate* isolate); 134 135 // Creates a Smi-handler for loading a native data property from fast object. 136 static inline Handle<Smi> LoadNativeDataProperty(Isolate* isolate, 137 int descriptor); 138 139 // Creates a Smi-handler for calling a native getter on a fast object. 140 static inline Handle<Smi> LoadApiGetter(Isolate* isolate, 141 bool holder_is_receiver); 142 143 // Creates a Smi-handler for loading a Module export. 144 // |index| is the index to the "value" slot in the Module's "exports" 145 // dictionary. 146 static inline Handle<Smi> LoadModuleExport(Isolate* isolate, int index); 147 148 // Creates a data handler that represents a load of a non-existent property. 149 // {holder} is the object from which the property is loaded. If no holder is 150 // needed (e.g., for "nonexistent"), null_value() may be passed in. 151 static Handle<Object> LoadFullChain(Isolate* isolate, 152 Handle<Map> receiver_map, 153 MaybeObjectHandle holder, 154 Handle<Smi> smi_handler); 155 156 // Creates a data handler that represents a prototype chain check followed 157 // by given Smi-handler that encoded a load from the holder. 158 // Can be used only if GetPrototypeCheckCount() returns non negative value. 159 static Handle<Object> LoadFromPrototype( 160 Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder, 161 Handle<Smi> smi_handler, 162 MaybeObjectHandle maybe_data1 = MaybeObjectHandle(), 163 MaybeObjectHandle maybe_data2 = MaybeObjectHandle()); 164 165 // Creates a Smi-handler for loading a non-existent property. Works only as 166 // 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 static inline Handle<Smi> LoadElement(Isolate* isolate, 171 ElementsKind elements_kind, 172 bool convert_hole_to_undefined, 173 bool is_js_array, 174 KeyedAccessLoadMode load_mode); 175 176 // Creates a Smi-handler for loading from a String. 177 static inline Handle<Smi> LoadIndexedString(Isolate* isolate, 178 KeyedAccessLoadMode load_mode); 179 180 // Decodes the KeyedAccessLoadMode from a {handler}. 181 static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject* handler); 182 }; 183 184 // A set of bit fields representing Smi handlers for stores and a HeapObject 185 // that represents store handlers that can't be encoded in a Smi. 186 // TODO(ishell): move to store-handler.h 187 class StoreHandler final : public DataHandler { 188 public: 189 DECL_CAST(StoreHandler) 190 191 DECL_PRINTER(StoreHandler) 192 DECL_VERIFIER(StoreHandler) 193 194 enum Kind { 195 kElement, 196 kField, 197 kConstField, 198 kAccessor, 199 kNativeDataProperty, 200 kApiSetter, 201 kApiSetterHolderIsPrototype, 202 kGlobalProxy, 203 kNormal, 204 kProxy, 205 kKindsNumber // Keep last 206 }; 207 class KindBits : public BitField<Kind, 0, 4> {}; 208 209 enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged }; 210 211 // Applicable to kGlobalProxy, kProxy kinds. 212 213 // Defines whether access rights check should be done on receiver object. 214 class DoAccessCheckOnReceiverBits 215 : public BitField<bool, KindBits::kNext, 1> {}; 216 217 // Defines whether a lookup should be done on receiver object before 218 // proceeding to the prototype chain. Applicable to named property kinds only 219 // when storing through prototype chain. Ignored when storing to holder. 220 class LookupOnReceiverBits 221 : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {}; 222 223 // Applicable to kField, kTransitionToField and kTransitionToConstant 224 // kinds. 225 226 // Index of a value entry in the descriptor array. 227 class DescriptorBits : public BitField<unsigned, LookupOnReceiverBits::kNext, 228 kDescriptorIndexBitCount> {}; 229 // 230 // Encoding when KindBits contains kTransitionToConstant. 231 // 232 233 // Make sure we don't overflow the smi. 234 STATIC_ASSERT(DescriptorBits::kNext <= kSmiValueSize); 235 236 // 237 // Encoding when KindBits contains kField or kTransitionToField. 238 // 239 class IsInobjectBits : public BitField<bool, DescriptorBits::kNext, 1> {}; 240 class FieldRepresentationBits 241 : public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {}; 242 // +1 here is to cover all possible JSObject header sizes. 243 class FieldIndexBits 244 : public BitField<unsigned, FieldRepresentationBits::kNext, 245 kDescriptorIndexBitCount + 1> {}; 246 // Make sure we don't overflow the smi. 247 STATIC_ASSERT(FieldIndexBits::kNext <= kSmiValueSize); 248 249 // Creates a Smi-handler for storing a field to fast object. 250 static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor, 251 FieldIndex field_index, 252 PropertyConstness constness, 253 Representation representation); 254 255 static MaybeObjectHandle StoreTransition(Isolate* isolate, 256 Handle<Map> transition_map); 257 258 // Creates a Smi-handler for storing a native data property on a fast object. 259 static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate, 260 int descriptor); 261 262 // Creates a Smi-handler for calling a setter on a fast object. 263 static inline Handle<Smi> StoreAccessor(Isolate* isolate, int descriptor); 264 265 // Creates a Smi-handler for calling a native setter on a fast object. 266 static inline Handle<Smi> StoreApiSetter(Isolate* isolate, 267 bool holder_is_receiver); 268 269 static Handle<Object> StoreThroughPrototype( 270 Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder, 271 Handle<Smi> smi_handler, 272 MaybeObjectHandle maybe_data1 = MaybeObjectHandle(), 273 MaybeObjectHandle maybe_data2 = MaybeObjectHandle()); 274 275 static Handle<Object> StoreElementTransition(Isolate* isolate, 276 Handle<Map> receiver_map, 277 Handle<Map> transition, 278 KeyedAccessStoreMode store_mode); 279 280 static Handle<Object> StoreProxy(Isolate* isolate, Handle<Map> receiver_map, 281 Handle<JSProxy> proxy, 282 Handle<JSReceiver> receiver); 283 284 // Creates a handler for storing a property to the property cell of a global 285 // object. 286 static MaybeObjectHandle StoreGlobal(Handle<PropertyCell> cell); 287 288 // Creates a Smi-handler for storing a property to a global proxy object. 289 static inline Handle<Smi> StoreGlobalProxy(Isolate* isolate); 290 291 // Creates a Smi-handler for storing a property to a slow object. 292 static inline Handle<Smi> StoreNormal(Isolate* isolate); 293 294 // Creates a Smi-handler for storing a property on a proxy. 295 static inline Handle<Smi> StoreProxy(Isolate* isolate); 296 297 private: 298 static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind, 299 int descriptor, FieldIndex field_index, 300 Representation representation); 301 }; 302 303 } // namespace internal 304 } // namespace v8 305 306 #include "src/objects/object-macros-undef.h" 307 308 #endif // V8_IC_HANDLER_CONFIGURATION_H_ 309