| Index: src/x64/builtins-x64.cc
|
| ===================================================================
|
| --- src/x64/builtins-x64.cc (revision 3837)
|
| +++ src/x64/builtins-x64.cc (working copy)
|
| @@ -276,44 +276,48 @@
|
| __ bind(&done);
|
| }
|
|
|
| - // 4. Shift stuff one slot down the stack.
|
| + // 4. Check that the function really is a function.
|
| + { Label real_function;
|
| + __ testq(rdi, rdi);
|
| + __ j(not_zero, &real_function);
|
| + __ xor_(rbx, rbx);
|
| + // CALL_NON_FUNCTION will expect to find the non-function callee on the
|
| + // expression stack of the caller. Transfer it from receiver to the
|
| + // caller's expression stack (and make the first argument the receiver
|
| + // for CALL_NON_FUNCTION) by decrementing the argument count.
|
| + __ decq(rax);
|
| + __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
|
| + __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
|
| + RelocInfo::CODE_TARGET);
|
| +
|
| + __ bind(&real_function);
|
| + }
|
| +
|
| + // 5. Shift arguments and return address one slot down on the stack
|
| + // (overwriting the receiver).
|
| { Label loop;
|
| - __ lea(rcx, Operand(rax, +1)); // +1 ~ copy receiver too
|
| + __ movq(rcx, rax);
|
| __ bind(&loop);
|
| __ movq(rbx, Operand(rsp, rcx, times_pointer_size, 0));
|
| __ movq(Operand(rsp, rcx, times_pointer_size, 1 * kPointerSize), rbx);
|
| __ decq(rcx);
|
| - __ j(not_zero, &loop);
|
| + __ j(not_sign, &loop);
|
| + __ pop(rbx); // Discard copy of return address.
|
| + __ decq(rax); // One fewer argument (first argument is new receiver).
|
| }
|
|
|
| - // 5. Remove TOS (copy of last arguments), but keep return address.
|
| - __ pop(rbx);
|
| - __ pop(rcx);
|
| - __ push(rbx);
|
| - __ decq(rax);
|
| + // 6. Get the code to call from the function and check that the number of
|
| + // expected arguments matches what we're providing.
|
| + __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
| + __ movsxlq(rbx,
|
| + FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
|
| + __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
|
| + __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
|
| + __ cmpq(rax, rbx);
|
| + __ j(not_equal,
|
| + Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
|
| + RelocInfo::CODE_TARGET);
|
|
|
| - // 6. Check that function really was a function and get the code to
|
| - // call from the function and check that the number of expected
|
| - // arguments matches what we're providing.
|
| - { Label invoke, trampoline;
|
| - __ testq(rdi, rdi);
|
| - __ j(not_zero, &invoke);
|
| - __ xor_(rbx, rbx);
|
| - __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
|
| - __ bind(&trampoline);
|
| - __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
|
| - RelocInfo::CODE_TARGET);
|
| -
|
| - __ bind(&invoke);
|
| - __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
| - __ movsxlq(rbx,
|
| - FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
|
| - __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
|
| - __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
|
| - __ cmpq(rax, rbx);
|
| - __ j(not_equal, &trampoline);
|
| - }
|
| -
|
| // 7. Jump (tail-call) to the code in register edx without checking arguments.
|
| ParameterCount expected(0);
|
| __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION);
|
|
|