Index: src/x64/virtual-frame-x64.cc |
=================================================================== |
--- src/x64/virtual-frame-x64.cc (revision 3911) |
+++ src/x64/virtual-frame-x64.cc (working copy) |
@@ -976,9 +976,41 @@ |
Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { |
- PrepareForCall(arg_count, arg_count); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ CallRuntime(f, arg_count); |
+ if (Runtime::DIRECT_CALL_NOT_FAILS == f->calling_convention) { |
+ ASSERT(height() >= arg_count); |
+ if (arg_count > kCArgRegsCount) { |
+ Forget(arg_count); |
+ return Result(Factory::undefined_value()); |
+ } |
+ |
+ for (int i = arg_count - 1; i >= 0; i--) { |
+ Result arg = Pop(); |
+ Register reg = kCArgRegs[i]; |
+ if (RegisterAllocator::IsReserved(reg)) { |
+ arg.ToRegister(); |
+ __ movq(reg, arg.reg()); |
+ arg.Unuse(); |
+ } else { |
+ arg.ToRegister(reg); |
+ arg.Unuse(); |
+ } |
+ } |
+ |
+ // TODO(serya): do not spill out C callee saved registers |
+ PrepareForCall(0, 0); |
+ |
+ ASSERT(cgen()->HasValidEntryRegisters()); |
+ __ CallRuntime(f, arg_count); |
+ if ((1 << rsi.code()) & kCCallerSaved) { |
+ RestoreContextRegister(); |
+ } |
+ } else { |
+ ASSERT(Runtime::EXIT_FRAME_CALL == f->calling_convention); |
+ PrepareForCall(arg_count, arg_count); |
+ ASSERT(cgen()->HasValidEntryRegisters()); |
+ __ CallRuntime(f, arg_count); |
+ } |
+ |
Result result = cgen()->allocator()->Allocate(rax); |
ASSERT(result.is_valid()); |
return result; |
@@ -986,12 +1018,7 @@ |
Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { |
- PrepareForCall(arg_count, arg_count); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ CallRuntime(id, arg_count); |
- Result result = cgen()->allocator()->Allocate(rax); |
- ASSERT(result.is_valid()); |
- return result; |
+ return CallRuntime(Runtime::FunctionForId(id), arg_count); |
} |