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