Commit fbad6366 authored by bmeurer's avatar bmeurer Committed by Commit bot

[builtins] Pass correct number of arguments after adapting arguments.

The call protocol requires that the register dedicated to the number of
actual arguments (i.e. rax on x64) always contains the actual arguments.
That means after adapting arguments it should match the number of
expected arguments.  But currently we pass some semi-random value
(usually some stack address) after adapting arguments.

It looks like this is currently not observable anywhere, because our
builtins and functions either don't look at the number of arguments and
just make hard coded (unchecked) assumptions, or are marked as "don't
adapt arguments", which bypasses the broken code in the trampoline for
arguments adaption.  Nevertheless this should be fixed.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/1306423003

Cr-Commit-Position: refs/heads/master@{#30467}
parent 44a93bcb
...@@ -1755,7 +1755,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1755,7 +1755,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ bind(&enough); __ bind(&enough);
EnterArgumentsAdaptorFrame(masm); EnterArgumentsAdaptorFrame(masm);
// Calculate copy start address into r0 and copy end address into r2. // Calculate copy start address into r0 and copy end address into r4.
// r0: actual number of arguments as a smi // r0: actual number of arguments as a smi
// r1: function // r1: function
// r2: expected number of arguments // r2: expected number of arguments
...@@ -1763,19 +1763,20 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1763,19 +1763,20 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0)); __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0));
// adjust for return address and receiver // adjust for return address and receiver
__ add(r0, r0, Operand(2 * kPointerSize)); __ add(r0, r0, Operand(2 * kPointerSize));
__ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); __ sub(r4, r0, Operand(r2, LSL, kPointerSizeLog2));
// Copy the arguments (including the receiver) to the new stack frame. // Copy the arguments (including the receiver) to the new stack frame.
// r0: copy start address // r0: copy start address
// r1: function // r1: function
// r2: copy end address // r2: expected number of arguments
// r3: code entry to call // r3: code entry to call
// r4: copy end address
Label copy; Label copy;
__ bind(&copy); __ bind(&copy);
__ ldr(ip, MemOperand(r0, 0)); __ ldr(ip, MemOperand(r0, 0));
__ push(ip); __ push(ip);
__ cmp(r0, r2); // Compare before moving to next argument. __ cmp(r0, r4); // Compare before moving to next argument.
__ sub(r0, r0, Operand(kPointerSize)); __ sub(r0, r0, Operand(kPointerSize));
__ b(ne, &copy); __ b(ne, &copy);
...@@ -1833,20 +1834,23 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1833,20 +1834,23 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// r2: expected number of arguments // r2: expected number of arguments
// r3: code entry to call // r3: code entry to call
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex); __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2)); __ sub(r4, fp, Operand(r2, LSL, kPointerSizeLog2));
// Adjust for frame. // Adjust for frame.
__ sub(r2, r2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp + __ sub(r4, r4, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
2 * kPointerSize)); 2 * kPointerSize));
Label fill; Label fill;
__ bind(&fill); __ bind(&fill);
__ push(ip); __ push(ip);
__ cmp(sp, r2); __ cmp(sp, r4);
__ b(ne, &fill); __ b(ne, &fill);
} }
// Call the entry point. // Call the entry point.
__ bind(&invoke); __ bind(&invoke);
__ mov(r0, r2);
// r0 : expected number of arguments
// r1 : function (passed through to callee)
__ Call(r3); __ Call(r3);
// Store offset of return address for deoptimizer. // Store offset of return address for deoptimizer.
......
...@@ -1803,19 +1803,19 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1803,19 +1803,19 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
Register copy_to = x12; Register copy_to = x12;
Register scratch1 = x13, scratch2 = x14; Register scratch1 = x13, scratch2 = x14;
__ Lsl(argc_expected, argc_expected, kPointerSizeLog2); __ Lsl(scratch2, argc_expected, kPointerSizeLog2);
// Adjust for fp, lr, and the receiver. // Adjust for fp, lr, and the receiver.
__ Add(copy_start, fp, 3 * kPointerSize); __ Add(copy_start, fp, 3 * kPointerSize);
__ Add(copy_start, copy_start, Operand(argc_actual, LSL, kPointerSizeLog2)); __ Add(copy_start, copy_start, Operand(argc_actual, LSL, kPointerSizeLog2));
__ Sub(copy_end, copy_start, argc_expected); __ Sub(copy_end, copy_start, scratch2);
__ Sub(copy_end, copy_end, kPointerSize); __ Sub(copy_end, copy_end, kPointerSize);
__ Mov(copy_to, jssp); __ Mov(copy_to, jssp);
// Claim space for the arguments, the receiver, and one extra slot. // Claim space for the arguments, the receiver, and one extra slot.
// The extra slot ensures we do not write under jssp. It will be popped // The extra slot ensures we do not write under jssp. It will be popped
// later. // later.
__ Add(scratch1, argc_expected, 2 * kPointerSize); __ Add(scratch1, scratch2, 2 * kPointerSize);
__ Claim(scratch1, 1); __ Claim(scratch1, 1);
// Copy the arguments (including the receiver) to the new stack frame. // Copy the arguments (including the receiver) to the new stack frame.
...@@ -1868,7 +1868,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1868,7 +1868,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ Bind(&no_strong_error); __ Bind(&no_strong_error);
EnterArgumentsAdaptorFrame(masm); EnterArgumentsAdaptorFrame(masm);
__ Lsl(argc_expected, argc_expected, kPointerSizeLog2); __ Lsl(scratch2, argc_expected, kPointerSizeLog2);
__ Lsl(argc_actual, argc_actual, kPointerSizeLog2); __ Lsl(argc_actual, argc_actual, kPointerSizeLog2);
// Adjust for fp, lr, and the receiver. // Adjust for fp, lr, and the receiver.
...@@ -1881,7 +1881,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1881,7 +1881,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// Claim space for the arguments, the receiver, and one extra slot. // Claim space for the arguments, the receiver, and one extra slot.
// The extra slot ensures we do not write under jssp. It will be popped // The extra slot ensures we do not write under jssp. It will be popped
// later. // later.
__ Add(scratch1, argc_expected, 2 * kPointerSize); __ Add(scratch1, scratch2, 2 * kPointerSize);
__ Claim(scratch1, 1); __ Claim(scratch1, 1);
// Copy the arguments (including the receiver) to the new stack frame. // Copy the arguments (including the receiver) to the new stack frame.
...@@ -1913,6 +1913,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1913,6 +1913,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// Arguments have been adapted. Now call the entry point. // Arguments have been adapted. Now call the entry point.
__ Bind(&invoke); __ Bind(&invoke);
__ Mov(argc_actual, argc_expected);
// x0 : expected number of arguments
// x1 : function (passed through to callee)
__ Call(code_entry); __ Call(code_entry);
// Store offset of return address for deoptimizer. // Store offset of return address for deoptimizer.
......
...@@ -1643,16 +1643,17 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1643,16 +1643,17 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// Copy receiver and all expected arguments. // Copy receiver and all expected arguments.
const int offset = StandardFrameConstants::kCallerSPOffset; const int offset = StandardFrameConstants::kCallerSPOffset;
__ lea(eax, Operand(ebp, eax, times_4, offset)); __ lea(edi, Operand(ebp, eax, times_4, offset));
__ mov(edi, -1); // account for receiver __ mov(eax, -1); // account for receiver
Label copy; Label copy;
__ bind(&copy); __ bind(&copy);
__ inc(edi); __ inc(eax);
__ push(Operand(eax, 0)); __ push(Operand(edi, 0));
__ sub(eax, Immediate(kPointerSize)); __ sub(edi, Immediate(kPointerSize));
__ cmp(edi, ebx); __ cmp(eax, ebx);
__ j(less, &copy); __ j(less, &copy);
// eax now contains the expected number of arguments.
__ jmp(&invoke); __ jmp(&invoke);
} }
...@@ -1681,6 +1682,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1681,6 +1682,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ bind(&no_strong_error); __ bind(&no_strong_error);
EnterArgumentsAdaptorFrame(masm); EnterArgumentsAdaptorFrame(masm);
// Remember expected arguments in ecx.
__ mov(ecx, ebx);
// Copy receiver and all actual arguments. // Copy receiver and all actual arguments.
const int offset = StandardFrameConstants::kCallerSPOffset; const int offset = StandardFrameConstants::kCallerSPOffset;
__ lea(edi, Operand(ebp, eax, times_4, offset)); __ lea(edi, Operand(ebp, eax, times_4, offset));
...@@ -1705,12 +1709,17 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1705,12 +1709,17 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ push(Immediate(masm->isolate()->factory()->undefined_value())); __ push(Immediate(masm->isolate()->factory()->undefined_value()));
__ cmp(eax, ebx); __ cmp(eax, ebx);
__ j(less, &fill); __ j(less, &fill);
// Restore expected arguments.
__ mov(eax, ecx);
} }
// Call the entry point. // Call the entry point.
__ bind(&invoke); __ bind(&invoke);
// Restore function pointer. // Restore function pointer.
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
// eax : expected number of arguments
// edi : function (passed through to callee)
__ call(edx); __ call(edx);
// Store offset of return address for deoptimizer. // Store offset of return address for deoptimizer.
......
...@@ -1780,6 +1780,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1780,6 +1780,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// Call the entry point. // Call the entry point.
__ bind(&invoke); __ bind(&invoke);
__ movp(rax, rbx);
// rax : expected number of arguments
// rdi: function (passed through to callee)
__ call(rdx); __ call(rdx);
// Store offset of return address for deoptimizer. // Store offset of return address for deoptimizer.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment