Index: src/arm/builtins-arm.cc |
=================================================================== |
--- src/arm/builtins-arm.cc (revision 3854) |
+++ src/arm/builtins-arm.cc (working copy) |
@@ -915,7 +915,7 @@ |
} |
// 2. Get the function to call from the stack. |
- // r0: actual number of argument |
+ // r0: actual number of arguments |
{ Label done, non_function, function; |
__ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
__ tst(r1, Operand(kSmiTagMask)); |
@@ -997,13 +997,27 @@ |
__ bind(&done); |
} |
- // 4. Shift stuff one slot down the stack |
+ // 4. Handle non-functions. |
// r0: actual number of arguments (including call() receiver) |
// r1: function |
+ { Label done; |
+ __ tst(r1, r1); |
+ __ b(ne, &done); |
+ __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION |
+ // Transfer the receiver from the first argument to the top of the |
+ // caller's expression stack simply by decrementing argc. |
+ __ sub(r0, r0, Operand(1)); |
+ __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
+ __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), |
+ RelocInfo::CODE_TARGET); |
+ __ bind(&done); |
+ } |
+ |
+ // 5. Shift arguments one slot toward the bottom of the |
+ // stack, overwriting the receiver. |
{ Label loop; |
// Calculate the copy start address (destination). Copy end address is sp. |
__ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); |
- __ add(r2, r2, Operand(kPointerSize)); // copy receiver too |
__ bind(&loop); |
__ ldr(ip, MemOperand(r2, -kPointerSize)); |
@@ -1011,43 +1025,28 @@ |
__ sub(r2, r2, Operand(kPointerSize)); |
__ cmp(r2, sp); |
__ b(ne, &loop); |
+ // Adjust the actual number of arguments and remove the top element. |
+ __ sub(r0, r0, Operand(1)); |
+ __ pop(); |
} |
- // 5. Adjust the actual number of arguments and remove the top element. |
- // r0: actual number of arguments (including call() receiver) |
- // r1: function |
- __ sub(r0, r0, Operand(1)); |
- __ add(sp, sp, Operand(kPointerSize)); |
- |
// 6. Get the code for the function or the non-function builtin. |
// If number of expected arguments matches, then call. Otherwise restart |
// the arguments adaptor stub. |
// r0: actual number of arguments |
// r1: function |
- { Label invoke; |
- __ tst(r1, r1); |
- __ b(ne, &invoke); |
- __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION |
- __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
- __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), |
- RelocInfo::CODE_TARGET); |
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
+ __ ldr(r2, |
+ FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); |
+ __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset)); |
+ __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
+ __ cmp(r2, r0); // Check formal and actual parameter counts. |
+ __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), |
+ RelocInfo::CODE_TARGET, ne); |
- __ bind(&invoke); |
- __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
- __ ldr(r2, |
- FieldMemOperand(r3, |
- SharedFunctionInfo::kFormalParameterCountOffset)); |
- __ ldr(r3, |
- MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag)); |
- __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
- __ cmp(r2, r0); // Check formal and actual parameter counts. |
- __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), |
- RelocInfo::CODE_TARGET, ne); |
- |
- // 7. Jump to the code in r3 without checking arguments. |
- ParameterCount expected(0); |
- __ InvokeCode(r3, expected, expected, JUMP_FUNCTION); |
- } |
+ // 7. Jump (tail-call) to the code in r3 without checking arguments. |
+ ParameterCount expected(0); |
+ __ InvokeCode(r3, expected, expected, JUMP_FUNCTION); |
} |