1 // Copyright 2014 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_CALL_INTERFACE_DESCRIPTOR_H_ 6 #define V8_CALL_INTERFACE_DESCRIPTOR_H_ 7 8 #include "src/assembler.h" 9 #include "src/macro-assembler.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class PlatformInterfaceDescriptor; 15 16 #define INTERFACE_DESCRIPTOR_LIST(V) \ 17 V(Load) \ 18 V(Store) \ 19 V(ElementTransitionAndStore) \ 20 V(Instanceof) \ 21 V(VectorLoadICTrampoline) \ 22 V(VectorLoadIC) \ 23 V(FastNewClosure) \ 24 V(FastNewContext) \ 25 V(ToNumber) \ 26 V(NumberToString) \ 27 V(FastCloneShallowArray) \ 28 V(FastCloneShallowObject) \ 29 V(CreateAllocationSite) \ 30 V(CallFunction) \ 31 V(CallFunctionWithFeedback) \ 32 V(CallConstruct) \ 33 V(RegExpConstructResult) \ 34 V(TransitionElementsKind) \ 35 V(ArrayConstructorConstantArgCount) \ 36 V(ArrayConstructor) \ 37 V(InternalArrayConstructorConstantArgCount) \ 38 V(InternalArrayConstructor) \ 39 V(CompareNil) \ 40 V(ToBoolean) \ 41 V(BinaryOp) \ 42 V(BinaryOpWithAllocationSite) \ 43 V(StringAdd) \ 44 V(Keyed) \ 45 V(Named) \ 46 V(CallHandler) \ 47 V(ArgumentAdaptor) \ 48 V(ApiGetter) \ 49 V(ApiFunction) \ 50 V(ArgumentsAccessRead) \ 51 V(StoreArrayLiteralElement) \ 52 V(MathPowTagged) \ 53 V(MathPowInteger) \ 54 V(ContextOnly) 55 56 57 class CallInterfaceDescriptorData { 58 public: CallInterfaceDescriptorData()59 CallInterfaceDescriptorData() : register_param_count_(-1) {} 60 61 // A copy of the passed in registers and param_representations is made 62 // and owned by the CallInterfaceDescriptorData. 63 64 // TODO(mvstanton): Instead of taking parallel arrays register and 65 // param_representations, how about a struct that puts the representation 66 // and register side by side (eg, RegRep(r1, Representation::Tagged()). 67 // The same should go for the CodeStubDescriptor class. 68 void Initialize(int register_parameter_count, Register* registers, 69 Representation* param_representations, 70 PlatformInterfaceDescriptor* platform_descriptor = NULL); 71 IsInitialized()72 bool IsInitialized() const { return register_param_count_ >= 0; } 73 register_param_count()74 int register_param_count() const { return register_param_count_; } register_param(int index)75 Register register_param(int index) const { return register_params_[index]; } register_params()76 Register* register_params() const { return register_params_.get(); } register_param_representation(int index)77 Representation register_param_representation(int index) const { 78 return register_param_representations_[index]; 79 } register_param_representations()80 Representation* register_param_representations() const { 81 return register_param_representations_.get(); 82 } platform_specific_descriptor()83 PlatformInterfaceDescriptor* platform_specific_descriptor() const { 84 return platform_specific_descriptor_; 85 } 86 87 private: 88 int register_param_count_; 89 90 // The Register params are allocated dynamically by the 91 // InterfaceDescriptor, and freed on destruction. This is because static 92 // arrays of Registers cause creation of runtime static initializers 93 // which we don't want. 94 SmartArrayPointer<Register> register_params_; 95 // Specifies Representations for the stub's parameter. Points to an array of 96 // Representations of the same length of the numbers of parameters to the 97 // stub, or if NULL (the default value), Representation of each parameter 98 // assumed to be Tagged(). 99 SmartArrayPointer<Representation> register_param_representations_; 100 101 PlatformInterfaceDescriptor* platform_specific_descriptor_; 102 103 DISALLOW_COPY_AND_ASSIGN(CallInterfaceDescriptorData); 104 }; 105 106 107 class CallDescriptors { 108 public: 109 enum Key { 110 #define DEF_ENUM(name) name, 111 INTERFACE_DESCRIPTOR_LIST(DEF_ENUM) 112 #undef DEF_ENUM 113 NUMBER_OF_DESCRIPTORS 114 }; 115 }; 116 117 118 class CallInterfaceDescriptor { 119 public: CallInterfaceDescriptor()120 CallInterfaceDescriptor() : data_(NULL) {} 121 CallInterfaceDescriptor(Isolate * isolate,CallDescriptors::Key key)122 CallInterfaceDescriptor(Isolate* isolate, CallDescriptors::Key key) 123 : data_(isolate->call_descriptor_data(key)) {} 124 GetEnvironmentLength()125 int GetEnvironmentLength() const { return data()->register_param_count(); } 126 GetRegisterParameterCount()127 int GetRegisterParameterCount() const { 128 return data()->register_param_count(); 129 } 130 GetParameterRegister(int index)131 Register GetParameterRegister(int index) const { 132 return data()->register_param(index); 133 } 134 GetParameterRepresentation(int index)135 Representation GetParameterRepresentation(int index) const { 136 DCHECK(index < data()->register_param_count()); 137 if (data()->register_param_representations() == NULL) { 138 return Representation::Tagged(); 139 } 140 141 return data()->register_param_representation(index); 142 } 143 144 // "Environment" versions of parameter functions. The first register 145 // parameter (context) is not included. GetEnvironmentParameterCount()146 int GetEnvironmentParameterCount() const { 147 return GetEnvironmentLength() - 1; 148 } 149 GetEnvironmentParameterRegister(int index)150 Register GetEnvironmentParameterRegister(int index) const { 151 return GetParameterRegister(index + 1); 152 } 153 GetEnvironmentParameterRepresentation(int index)154 Representation GetEnvironmentParameterRepresentation(int index) const { 155 return GetParameterRepresentation(index + 1); 156 } 157 158 // Some platforms have extra information to associate with the descriptor. platform_specific_descriptor()159 PlatformInterfaceDescriptor* platform_specific_descriptor() const { 160 return data()->platform_specific_descriptor(); 161 } 162 163 static const Register ContextRegister(); 164 165 const char* DebugName(Isolate* isolate); 166 167 protected: data()168 const CallInterfaceDescriptorData* data() const { return data_; } 169 170 private: 171 const CallInterfaceDescriptorData* data_; 172 }; 173 174 175 #define DECLARE_DESCRIPTOR(name, base) \ 176 explicit name(Isolate* isolate) : base(isolate, key()) { \ 177 if (!data()->IsInitialized()) \ 178 Initialize(isolate->call_descriptor_data(key())); \ 179 } \ 180 \ 181 protected: \ 182 void Initialize(CallInterfaceDescriptorData* data); \ 183 name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \ 184 \ 185 public: \ 186 static inline CallDescriptors::Key key(); 187 188 189 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs. 190 class LoadDescriptor : public CallInterfaceDescriptor { 191 public: 192 DECLARE_DESCRIPTOR(LoadDescriptor, CallInterfaceDescriptor) 193 194 enum ParameterIndices { kReceiverIndex, kNameIndex }; 195 static const Register ReceiverRegister(); 196 static const Register NameRegister(); 197 }; 198 199 200 class StoreDescriptor : public CallInterfaceDescriptor { 201 public: 202 DECLARE_DESCRIPTOR(StoreDescriptor, CallInterfaceDescriptor) 203 204 enum ParameterIndices { 205 kReceiverIndex, 206 kNameIndex, 207 kValueIndex, 208 kParameterCount 209 }; 210 static const Register ReceiverRegister(); 211 static const Register NameRegister(); 212 static const Register ValueRegister(); 213 }; 214 215 216 class ElementTransitionAndStoreDescriptor : public StoreDescriptor { 217 public: 218 DECLARE_DESCRIPTOR(ElementTransitionAndStoreDescriptor, StoreDescriptor) 219 220 static const Register MapRegister(); 221 }; 222 223 224 class InstanceofDescriptor : public CallInterfaceDescriptor { 225 public: 226 DECLARE_DESCRIPTOR(InstanceofDescriptor, CallInterfaceDescriptor) 227 228 enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount }; 229 static const Register left(); 230 static const Register right(); 231 }; 232 233 234 class VectorLoadICTrampolineDescriptor : public LoadDescriptor { 235 public: 236 DECLARE_DESCRIPTOR(VectorLoadICTrampolineDescriptor, LoadDescriptor) 237 238 enum ParameterIndices { kReceiverIndex, kNameIndex, kSlotIndex }; 239 240 static const Register SlotRegister(); 241 }; 242 243 244 class VectorLoadICDescriptor : public VectorLoadICTrampolineDescriptor { 245 public: 246 DECLARE_DESCRIPTOR(VectorLoadICDescriptor, VectorLoadICTrampolineDescriptor) 247 248 enum ParameterIndices { 249 kReceiverIndex, 250 kNameIndex, 251 kSlotIndex, 252 kVectorIndex 253 }; 254 255 static const Register VectorRegister(); 256 }; 257 258 259 class FastNewClosureDescriptor : public CallInterfaceDescriptor { 260 public: 261 DECLARE_DESCRIPTOR(FastNewClosureDescriptor, CallInterfaceDescriptor) 262 }; 263 264 265 class FastNewContextDescriptor : public CallInterfaceDescriptor { 266 public: 267 DECLARE_DESCRIPTOR(FastNewContextDescriptor, CallInterfaceDescriptor) 268 }; 269 270 271 class ToNumberDescriptor : public CallInterfaceDescriptor { 272 public: 273 DECLARE_DESCRIPTOR(ToNumberDescriptor, CallInterfaceDescriptor) 274 }; 275 276 277 class NumberToStringDescriptor : public CallInterfaceDescriptor { 278 public: 279 DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor) 280 }; 281 282 283 class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor { 284 public: 285 DECLARE_DESCRIPTOR(FastCloneShallowArrayDescriptor, CallInterfaceDescriptor) 286 }; 287 288 289 class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor { 290 public: 291 DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor) 292 }; 293 294 295 class CreateAllocationSiteDescriptor : public CallInterfaceDescriptor { 296 public: 297 DECLARE_DESCRIPTOR(CreateAllocationSiteDescriptor, CallInterfaceDescriptor) 298 }; 299 300 301 class CallFunctionDescriptor : public CallInterfaceDescriptor { 302 public: 303 DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor) 304 }; 305 306 307 class CallFunctionWithFeedbackDescriptor : public CallInterfaceDescriptor { 308 public: 309 DECLARE_DESCRIPTOR(CallFunctionWithFeedbackDescriptor, 310 CallInterfaceDescriptor) 311 }; 312 313 314 class CallConstructDescriptor : public CallInterfaceDescriptor { 315 public: 316 DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor) 317 }; 318 319 320 class RegExpConstructResultDescriptor : public CallInterfaceDescriptor { 321 public: 322 DECLARE_DESCRIPTOR(RegExpConstructResultDescriptor, CallInterfaceDescriptor) 323 }; 324 325 326 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor { 327 public: 328 DECLARE_DESCRIPTOR(TransitionElementsKindDescriptor, CallInterfaceDescriptor) 329 }; 330 331 332 class ArrayConstructorConstantArgCountDescriptor 333 : public CallInterfaceDescriptor { 334 public: 335 DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor, 336 CallInterfaceDescriptor) 337 }; 338 339 340 class ArrayConstructorDescriptor : public CallInterfaceDescriptor { 341 public: 342 DECLARE_DESCRIPTOR(ArrayConstructorDescriptor, CallInterfaceDescriptor) 343 }; 344 345 346 class InternalArrayConstructorConstantArgCountDescriptor 347 : public CallInterfaceDescriptor { 348 public: 349 DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor, 350 CallInterfaceDescriptor) 351 }; 352 353 354 class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor { 355 public: 356 DECLARE_DESCRIPTOR(InternalArrayConstructorDescriptor, 357 CallInterfaceDescriptor) 358 }; 359 360 361 class CompareNilDescriptor : public CallInterfaceDescriptor { 362 public: 363 DECLARE_DESCRIPTOR(CompareNilDescriptor, CallInterfaceDescriptor) 364 }; 365 366 367 class ToBooleanDescriptor : public CallInterfaceDescriptor { 368 public: 369 DECLARE_DESCRIPTOR(ToBooleanDescriptor, CallInterfaceDescriptor) 370 }; 371 372 373 class BinaryOpDescriptor : public CallInterfaceDescriptor { 374 public: 375 DECLARE_DESCRIPTOR(BinaryOpDescriptor, CallInterfaceDescriptor) 376 }; 377 378 379 class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor { 380 public: 381 DECLARE_DESCRIPTOR(BinaryOpWithAllocationSiteDescriptor, 382 CallInterfaceDescriptor) 383 }; 384 385 386 class StringAddDescriptor : public CallInterfaceDescriptor { 387 public: 388 DECLARE_DESCRIPTOR(StringAddDescriptor, CallInterfaceDescriptor) 389 }; 390 391 392 class KeyedDescriptor : public CallInterfaceDescriptor { 393 public: 394 DECLARE_DESCRIPTOR(KeyedDescriptor, CallInterfaceDescriptor) 395 }; 396 397 398 class NamedDescriptor : public CallInterfaceDescriptor { 399 public: 400 DECLARE_DESCRIPTOR(NamedDescriptor, CallInterfaceDescriptor) 401 }; 402 403 404 class CallHandlerDescriptor : public CallInterfaceDescriptor { 405 public: 406 DECLARE_DESCRIPTOR(CallHandlerDescriptor, CallInterfaceDescriptor) 407 }; 408 409 410 class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor { 411 public: 412 DECLARE_DESCRIPTOR(ArgumentAdaptorDescriptor, CallInterfaceDescriptor) 413 }; 414 415 416 class ApiFunctionDescriptor : public CallInterfaceDescriptor { 417 public: 418 DECLARE_DESCRIPTOR(ApiFunctionDescriptor, CallInterfaceDescriptor) 419 }; 420 421 422 class ApiGetterDescriptor : public CallInterfaceDescriptor { 423 public: 424 DECLARE_DESCRIPTOR(ApiGetterDescriptor, CallInterfaceDescriptor) 425 426 static const Register function_address(); 427 }; 428 429 430 class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor { 431 public: 432 DECLARE_DESCRIPTOR(ArgumentsAccessReadDescriptor, CallInterfaceDescriptor) 433 434 static const Register index(); 435 static const Register parameter_count(); 436 }; 437 438 439 class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor { 440 public: 441 DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor, 442 CallInterfaceDescriptor) 443 }; 444 445 446 class MathPowTaggedDescriptor : public CallInterfaceDescriptor { 447 public: 448 DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor) 449 450 static const Register exponent(); 451 }; 452 453 454 class MathPowIntegerDescriptor : public CallInterfaceDescriptor { 455 public: 456 DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor) 457 458 static const Register exponent(); 459 }; 460 461 462 class ContextOnlyDescriptor : public CallInterfaceDescriptor { 463 public: 464 DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor) 465 }; 466 467 #undef DECLARE_DESCRIPTOR 468 469 470 // We define the association between CallDescriptors::Key and the specialized 471 // descriptor here to reduce boilerplate and mistakes. 472 #define DEF_KEY(name) \ 473 CallDescriptors::Key name##Descriptor::key() { return CallDescriptors::name; } 474 INTERFACE_DESCRIPTOR_LIST(DEF_KEY) 475 #undef DEF_KEY 476 } 477 } // namespace v8::internal 478 479 480 #if V8_TARGET_ARCH_ARM64 481 #include "src/arm64/interface-descriptors-arm64.h" 482 #elif V8_TARGET_ARCH_ARM 483 #include "src/arm/interface-descriptors-arm.h" 484 #endif 485 486 #endif // V8_CALL_INTERFACE_DESCRIPTOR_H_ 487