Index: src/x64/macro-assembler-x64.cc |
=================================================================== |
--- src/x64/macro-assembler-x64.cc (revision 3911) |
+++ src/x64/macro-assembler-x64.cc (working copy) |
@@ -37,6 +37,15 @@ |
namespace v8 { |
namespace internal { |
+const Register kCArgRegs[kCArgRegsCount] = { |
+#ifdef _WIN64 |
+ rcx, rdx, r8, r9 |
+#else |
+ rdi, rsi, rdx, rcx, r8, r9 |
+#endif |
+}; |
+ |
+ |
MacroAssembler::MacroAssembler(void* buffer, int size) |
: Assembler(buffer, size), |
generating_stub_(false), |
@@ -371,18 +380,35 @@ |
// constant, we check that the actual number of arguments match the |
// expectation. |
if (f->nargs >= 0 && f->nargs != num_arguments) { |
- IllegalOperation(num_arguments); |
+ int num_args_on_stack = |
+ (Runtime::EXIT_FRAME_CALL == f->calling_convention) ? 0 : num_arguments; |
+ IllegalOperation(num_args_on_stack); |
return; |
} |
- // TODO(1236192): Most runtime routines don't need the number of |
- // arguments passed in because it is constant. At some point we |
- // should remove this need and make the runtime routine entry code |
- // smarter. |
- movq(rax, Immediate(num_arguments)); |
- movq(rbx, ExternalReference(f)); |
- CEntryStub ces(f->result_size); |
- CallStub(&ces); |
+ switch (f->calling_convention) { |
+ case Runtime::EXIT_FRAME_CALL: { |
+ // Arguments are expected to be pushed on stack in left-to-right order. |
+ // The stub will pass reference to them as Arguments into the function. |
+ |
+ // TODO(1236192): Most runtime routines don't need the number of |
+ // arguments passed in because it is constant. At some point we |
+ // should remove this need and make the runtime routine entry code |
+ // smarter. |
+ movq(rax, Immediate(num_arguments)); |
+ movq(rbx, ExternalReference(f)); |
+ CEntryStub ces(f->result_size); |
+ CallStub(&ces); |
+ break; |
+ } |
+ case Runtime::DIRECT_CALL_NOT_FAILS: |
+ // Arguments are expected to be put into the registers in order of |
+ // kCArgRegs. |
+ ASSERT(num_arguments <= kCArgRegsCount); |
+ PrepareCallCFunction(num_arguments); |
+ CallCFunction(ExternalReference(f), num_arguments); |
+ break; |
+ } |
} |
@@ -395,8 +421,30 @@ |
CallStub(&stub); |
} |
+void MacroAssembler::TailCallRuntime(Runtime::FunctionId id, |
+ int num_arguments, |
+ int result_size) { |
+ Runtime::Function* f = Runtime::FunctionForId(id); |
-void MacroAssembler::TailCallRuntime(ExternalReference const& ext, |
+ ASSERT(f->nargs == -1 || f->nargs == num_arguments); |
+ if (f->calling_convention == Runtime::EXIT_FRAME_CALL) { |
+ TailCallExternalReference(ExternalReference(f), num_arguments, result_size); |
+ } else if (f->calling_convention == Runtime::DIRECT_CALL_NOT_FAILS) { |
+ // Move arguments to registers |
+ ASSERT(kCArgRegsCount >= num_arguments); |
+ pop(rax); // get return address |
+ for (int i = 0; i < num_arguments; i++) { |
+ pop(kCArgRegs[num_arguments - 1 - i]); |
+ } |
+ PrepareCallCFunction(num_arguments); // align stack |
+ movq(kScratchRegister, ExternalReference(f)); |
+ push(rax); // return |
+ jmp(kScratchRegister); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::TailCallExternalReference(ExternalReference const& ext, |
int num_arguments, |
int result_size) { |
// ----------- S t a t e ------------- |