1 // Copyright 2012 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 #if V8_TARGET_ARCH_X64 6 7 #include "src/interface-descriptors.h" 8 9 namespace v8 { 10 namespace internal { 11 12 const Register CallInterfaceDescriptor::ContextRegister() { return rsi; } 13 14 void CallInterfaceDescriptor::DefaultInitializePlatformSpecific( 15 CallInterfaceDescriptorData* data, int register_parameter_count) { 16 const Register default_stub_registers[] = {rax, rbx, rcx, rdx, rdi}; 17 CHECK_LE(static_cast<size_t>(register_parameter_count), 18 arraysize(default_stub_registers)); 19 data->InitializePlatformSpecific(register_parameter_count, 20 default_stub_registers); 21 } 22 23 const Register FastNewFunctionContextDescriptor::FunctionRegister() { 24 return rdi; 25 } 26 const Register FastNewFunctionContextDescriptor::SlotsRegister() { return rax; } 27 28 const Register LoadDescriptor::ReceiverRegister() { return rdx; } 29 const Register LoadDescriptor::NameRegister() { return rcx; } 30 const Register LoadDescriptor::SlotRegister() { return rax; } 31 32 const Register LoadWithVectorDescriptor::VectorRegister() { return rbx; } 33 34 const Register LoadICProtoArrayDescriptor::HandlerRegister() { return rdi; } 35 36 const Register StoreDescriptor::ReceiverRegister() { return rdx; } 37 const Register StoreDescriptor::NameRegister() { return rcx; } 38 const Register StoreDescriptor::ValueRegister() { return rax; } 39 const Register StoreDescriptor::SlotRegister() { return rdi; } 40 41 const Register StoreWithVectorDescriptor::VectorRegister() { return rbx; } 42 43 const Register StoreTransitionDescriptor::SlotRegister() { return rdi; } 44 const Register StoreTransitionDescriptor::VectorRegister() { return rbx; } 45 const Register StoreTransitionDescriptor::MapRegister() { return r11; } 46 47 const Register StringCompareDescriptor::LeftRegister() { return rdx; } 48 const Register StringCompareDescriptor::RightRegister() { return rax; } 49 50 const Register ApiGetterDescriptor::HolderRegister() { return rcx; } 51 const Register ApiGetterDescriptor::CallbackRegister() { return rbx; } 52 53 const Register MathPowTaggedDescriptor::exponent() { return rdx; } 54 55 56 const Register MathPowIntegerDescriptor::exponent() { 57 return MathPowTaggedDescriptor::exponent(); 58 } 59 60 61 const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; } 62 const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; } 63 64 65 void FastNewClosureDescriptor::InitializePlatformSpecific( 66 CallInterfaceDescriptorData* data) { 67 Register registers[] = {rbx}; 68 data->InitializePlatformSpecific(arraysize(registers), registers); 69 } 70 71 void FastNewObjectDescriptor::InitializePlatformSpecific( 72 CallInterfaceDescriptorData* data) { 73 Register registers[] = {rdi, rdx}; 74 data->InitializePlatformSpecific(arraysize(registers), registers); 75 } 76 77 void FastNewRestParameterDescriptor::InitializePlatformSpecific( 78 CallInterfaceDescriptorData* data) { 79 Register registers[] = {rdi}; 80 data->InitializePlatformSpecific(arraysize(registers), registers); 81 } 82 83 void FastNewSloppyArgumentsDescriptor::InitializePlatformSpecific( 84 CallInterfaceDescriptorData* data) { 85 Register registers[] = {rdi}; 86 data->InitializePlatformSpecific(arraysize(registers), registers); 87 } 88 89 void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific( 90 CallInterfaceDescriptorData* data) { 91 Register registers[] = {rdi}; 92 data->InitializePlatformSpecific(arraysize(registers), registers); 93 } 94 95 96 void TypeofDescriptor::InitializePlatformSpecific( 97 CallInterfaceDescriptorData* data) { 98 Register registers[] = {rbx}; 99 data->InitializePlatformSpecific(arraysize(registers), registers); 100 } 101 102 103 // static 104 const Register TypeConversionDescriptor::ArgumentRegister() { return rax; } 105 106 void FastCloneRegExpDescriptor::InitializePlatformSpecific( 107 CallInterfaceDescriptorData* data) { 108 Register registers[] = {rdi, rax, rcx, rdx}; 109 data->InitializePlatformSpecific(arraysize(registers), registers); 110 } 111 112 113 void FastCloneShallowArrayDescriptor::InitializePlatformSpecific( 114 CallInterfaceDescriptorData* data) { 115 Register registers[] = {rax, rbx, rcx}; 116 data->InitializePlatformSpecific(arraysize(registers), registers); 117 } 118 119 120 void FastCloneShallowObjectDescriptor::InitializePlatformSpecific( 121 CallInterfaceDescriptorData* data) { 122 Register registers[] = {rax, rbx, rcx, rdx}; 123 data->InitializePlatformSpecific(arraysize(registers), registers); 124 } 125 126 127 void CreateAllocationSiteDescriptor::InitializePlatformSpecific( 128 CallInterfaceDescriptorData* data) { 129 Register registers[] = {rbx, rdx}; 130 data->InitializePlatformSpecific(arraysize(registers), registers); 131 } 132 133 134 void CreateWeakCellDescriptor::InitializePlatformSpecific( 135 CallInterfaceDescriptorData* data) { 136 Register registers[] = {rbx, rdx, rdi}; 137 data->InitializePlatformSpecific(arraysize(registers), registers); 138 } 139 140 141 void CallFunctionDescriptor::InitializePlatformSpecific( 142 CallInterfaceDescriptorData* data) { 143 Register registers[] = {rdi}; 144 data->InitializePlatformSpecific(arraysize(registers), registers); 145 } 146 147 148 void CallFunctionWithFeedbackDescriptor::InitializePlatformSpecific( 149 CallInterfaceDescriptorData* data) { 150 Register registers[] = {rdi, rdx}; 151 data->InitializePlatformSpecific(arraysize(registers), registers); 152 } 153 154 155 void CallFunctionWithFeedbackAndVectorDescriptor::InitializePlatformSpecific( 156 CallInterfaceDescriptorData* data) { 157 Register registers[] = {rdi, rax, rdx, rbx}; 158 data->InitializePlatformSpecific(arraysize(registers), registers); 159 } 160 161 162 void CallConstructDescriptor::InitializePlatformSpecific( 163 CallInterfaceDescriptorData* data) { 164 // rax : number of arguments 165 // rbx : feedback vector 166 // rdx : slot in feedback vector (Smi, for RecordCallTarget) 167 // rdi : constructor function 168 // TODO(turbofan): So far we don't gather type feedback and hence skip the 169 // slot parameter, but ArrayConstructStub needs the vector to be undefined. 170 Register registers[] = {rax, rdi, rbx}; 171 data->InitializePlatformSpecific(arraysize(registers), registers); 172 } 173 174 175 void CallTrampolineDescriptor::InitializePlatformSpecific( 176 CallInterfaceDescriptorData* data) { 177 // rax : number of arguments 178 // rdi : the target to call 179 Register registers[] = {rdi, rax}; 180 data->InitializePlatformSpecific(arraysize(registers), registers); 181 } 182 183 184 void ConstructStubDescriptor::InitializePlatformSpecific( 185 CallInterfaceDescriptorData* data) { 186 // rax : number of arguments 187 // rdx : the new target 188 // rdi : the target to call 189 // rbx : allocation site or undefined 190 Register registers[] = {rdi, rdx, rax, rbx}; 191 data->InitializePlatformSpecific(arraysize(registers), registers); 192 } 193 194 195 void ConstructTrampolineDescriptor::InitializePlatformSpecific( 196 CallInterfaceDescriptorData* data) { 197 // rax : number of arguments 198 // rdx : the new target 199 // rdi : the target to call 200 Register registers[] = {rdi, rdx, rax}; 201 data->InitializePlatformSpecific(arraysize(registers), registers); 202 } 203 204 205 void TransitionElementsKindDescriptor::InitializePlatformSpecific( 206 CallInterfaceDescriptorData* data) { 207 Register registers[] = {rax, rbx}; 208 data->InitializePlatformSpecific(arraysize(registers), registers); 209 } 210 211 212 void AllocateHeapNumberDescriptor::InitializePlatformSpecific( 213 CallInterfaceDescriptorData* data) { 214 data->InitializePlatformSpecific(0, nullptr, nullptr); 215 } 216 217 #define SIMD128_ALLOC_DESC(TYPE, Type, type, lane_count, lane_type) \ 218 void Allocate##Type##Descriptor::InitializePlatformSpecific( \ 219 CallInterfaceDescriptorData* data) { \ 220 data->InitializePlatformSpecific(0, nullptr, nullptr); \ 221 } 222 SIMD128_TYPES(SIMD128_ALLOC_DESC) 223 #undef SIMD128_ALLOC_DESC 224 225 void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific( 226 CallInterfaceDescriptorData* data) { 227 // register state 228 // rax -- number of arguments 229 // rdi -- function 230 // rbx -- allocation site with elements kind 231 Register registers[] = {rdi, rbx, rax}; 232 data->InitializePlatformSpecific(arraysize(registers), registers, NULL); 233 } 234 235 void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific( 236 CallInterfaceDescriptorData* data) { 237 // register state 238 // rax -- number of arguments 239 // rdi -- function 240 // rbx -- allocation site with elements kind 241 Register registers[] = {rdi, rbx, rax}; 242 data->InitializePlatformSpecific(arraysize(registers), registers, NULL); 243 } 244 245 void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific( 246 CallInterfaceDescriptorData* data) { 247 // register state 248 // rax -- number of arguments 249 // rdi -- function 250 // rbx -- allocation site with elements kind 251 Register registers[] = {rdi, rbx, rax}; 252 data->InitializePlatformSpecific(arraysize(registers), registers, NULL); 253 } 254 255 void VarArgFunctionDescriptor::InitializePlatformSpecific( 256 CallInterfaceDescriptorData* data) { 257 // stack param count needs (arg count) 258 Register registers[] = {rax}; 259 data->InitializePlatformSpecific(arraysize(registers), registers); 260 } 261 262 void CompareDescriptor::InitializePlatformSpecific( 263 CallInterfaceDescriptorData* data) { 264 Register registers[] = {rdx, rax}; 265 data->InitializePlatformSpecific(arraysize(registers), registers); 266 } 267 268 269 void BinaryOpDescriptor::InitializePlatformSpecific( 270 CallInterfaceDescriptorData* data) { 271 Register registers[] = {rdx, rax}; 272 data->InitializePlatformSpecific(arraysize(registers), registers); 273 } 274 275 276 void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific( 277 CallInterfaceDescriptorData* data) { 278 Register registers[] = {rcx, rdx, rax}; 279 data->InitializePlatformSpecific(arraysize(registers), registers); 280 } 281 282 void BinaryOpWithVectorDescriptor::InitializePlatformSpecific( 283 CallInterfaceDescriptorData* data) { 284 // register state 285 // rdx -- lhs 286 // rax -- rhs 287 // rdi -- slot id 288 // rbx -- vector 289 Register registers[] = {rdx, rax, rdi, rbx}; 290 data->InitializePlatformSpecific(arraysize(registers), registers); 291 } 292 293 void CountOpDescriptor::InitializePlatformSpecific( 294 CallInterfaceDescriptorData* data) { 295 Register registers[] = {rax}; 296 data->InitializePlatformSpecific(arraysize(registers), registers); 297 } 298 299 void StringAddDescriptor::InitializePlatformSpecific( 300 CallInterfaceDescriptorData* data) { 301 Register registers[] = {rdx, rax}; 302 data->InitializePlatformSpecific(arraysize(registers), registers); 303 } 304 305 306 void KeyedDescriptor::InitializePlatformSpecific( 307 CallInterfaceDescriptorData* data) { 308 Register registers[] = { 309 rcx, // key 310 }; 311 data->InitializePlatformSpecific(arraysize(registers), registers); 312 } 313 314 315 void NamedDescriptor::InitializePlatformSpecific( 316 CallInterfaceDescriptorData* data) { 317 Register registers[] = { 318 rcx, // name 319 }; 320 data->InitializePlatformSpecific(arraysize(registers), registers); 321 } 322 323 324 void CallHandlerDescriptor::InitializePlatformSpecific( 325 CallInterfaceDescriptorData* data) { 326 Register registers[] = { 327 rdx, // receiver 328 }; 329 data->InitializePlatformSpecific(arraysize(registers), registers); 330 } 331 332 333 void ArgumentAdaptorDescriptor::InitializePlatformSpecific( 334 CallInterfaceDescriptorData* data) { 335 Register registers[] = { 336 rdi, // JSFunction 337 rdx, // the new target 338 rax, // actual number of arguments 339 rbx, // expected number of arguments 340 }; 341 data->InitializePlatformSpecific(arraysize(registers), registers); 342 } 343 344 void ApiCallbackDescriptor::InitializePlatformSpecific( 345 CallInterfaceDescriptorData* data) { 346 Register registers[] = { 347 rdi, // callee 348 rbx, // call_data 349 rcx, // holder 350 rdx, // api_function_address 351 }; 352 data->InitializePlatformSpecific(arraysize(registers), registers); 353 } 354 355 void InterpreterDispatchDescriptor::InitializePlatformSpecific( 356 CallInterfaceDescriptorData* data) { 357 Register registers[] = { 358 kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister, 359 kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister}; 360 data->InitializePlatformSpecific(arraysize(registers), registers); 361 } 362 363 void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( 364 CallInterfaceDescriptorData* data) { 365 Register registers[] = { 366 rax, // argument count (not including receiver) 367 rbx, // address of first argument 368 rdi // the target callable to be call 369 }; 370 data->InitializePlatformSpecific(arraysize(registers), registers); 371 } 372 373 void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( 374 CallInterfaceDescriptorData* data) { 375 Register registers[] = { 376 rax, // argument count (not including receiver) 377 rdx, // new target 378 rdi, // constructor 379 rbx, // allocation site feedback if available, undefined otherwise 380 rcx, // address of first argument 381 }; 382 data->InitializePlatformSpecific(arraysize(registers), registers); 383 } 384 385 void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( 386 CallInterfaceDescriptorData* data) { 387 Register registers[] = { 388 rax, // argument count (not including receiver) 389 rdx, // target to the call. It is checked to be Array function. 390 rbx, // allocation site feedback 391 rcx, // address of first argument 392 }; 393 data->InitializePlatformSpecific(arraysize(registers), registers); 394 } 395 396 void InterpreterCEntryDescriptor::InitializePlatformSpecific( 397 CallInterfaceDescriptorData* data) { 398 Register registers[] = { 399 rax, // argument count (argc) 400 r15, // address of first argument (argv) 401 rbx // the runtime function to call 402 }; 403 data->InitializePlatformSpecific(arraysize(registers), registers); 404 } 405 406 void ResumeGeneratorDescriptor::InitializePlatformSpecific( 407 CallInterfaceDescriptorData* data) { 408 Register registers[] = { 409 rax, // the value to pass to the generator 410 rbx, // the JSGeneratorObject to resume 411 rdx // the resume mode (tagged) 412 }; 413 data->InitializePlatformSpecific(arraysize(registers), registers); 414 } 415 416 } // namespace internal 417 } // namespace v8 418 419 #endif // V8_TARGET_ARCH_X64 420