| 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 -------------
 | 
| 
 |