[builtins] Make sure argument count is always valid for C++ builtins.

When calling into C++ builtins, we need to make sure that the argument
count register contains the correct number of arguments, otherwise the
CEntryStub will not be able to leave the stack in the correct state.

R=ishell@chromium.org
BUG=v8:4413
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#31120}
This commit is contained in:
bmeurer 2015-10-06 01:23:41 -07:00 committed by Commit bot
parent 299c72bc88
commit 9c8262f11e
7 changed files with 114 additions and 22 deletions

View File

@ -22,11 +22,12 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- r0 : number of arguments excluding receiver
// -- r1 : called function (only guaranteed when
// extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- r1 : called function
// -- sp[0] : last argument
// -- ...
// -- sp[4 * (argc - 1)] : first argument (argc == r0)
// -- sp[4 * (argc - 1)] : first argument
// -- sp[4 * argc] : receiver
// -----------------------------------
__ AssertFunction(r1);
@ -48,8 +49,17 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects r0 to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But r0 is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
__ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r2,
FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ SmiUntag(r2);
__ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ mov(r0, r2, LeaveCC, ne);
__ add(r0, r0, Operand(num_extra_args + 1));
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
}

View File

@ -49,11 +49,12 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- x0 : number of arguments excluding receiver
// -- x1 : called function (only guaranteed when
// extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- x1 : called function
// -- sp[0] : last argument
// -- ...
// -- sp[4 * (argc - 1)] : first argument (argc == x0)
// -- sp[4 * (argc - 1)] : first argument
// -- sp[4 * argc] : receiver
// -----------------------------------
__ AssertFunction(x1);
@ -75,8 +76,16 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects x0 to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But x0 is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
__ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldrsw(
x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
__ Cmp(x2, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
__ Csel(x0, x0, x2, eq);
__ Add(x0, x0, num_extra_args + 1);
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
}

View File

@ -22,12 +22,13 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- eax : number of arguments excluding receiver
// -- edi : called function (only guaranteed when
// extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- edi : called function
// -- esp[0] : return address
// -- esp[4] : last argument
// -- ...
// -- esp[4 * argc] : first argument (argc == eax)
// -- esp[4 * argc] : first argument
// -- esp[4 * (argc +1)] : receiver
// -----------------------------------
__ AssertFunction(edi);
@ -52,8 +53,22 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects eax to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But eax is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
Label argc, done_argc;
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(ebx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ SmiUntag(ebx);
__ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
__ j(equal, &argc, Label::kNear);
__ lea(eax, Operand(ebx, num_extra_args + 1));
__ jmp(&done_argc, Label::kNear);
__ bind(&argc);
__ add(eax, Immediate(num_extra_args + 1));
__ bind(&done_argc);
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
}

View File

@ -23,8 +23,9 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- a0 : number of arguments excluding receiver
// -- a1 : called function (only guaranteed when
// -- extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- a1 : called function
// -- sp[0] : last argument
// -- ...
// -- sp[4 * (argc - 1)] : first argument
@ -49,8 +50,22 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects a0 to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But a0 is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
Label argc, done_argc;
__ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ SmiUntag(a2);
__ Branch(&argc, ne, a2,
Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ Addu(a0, a2, num_extra_args + 1);
__ jmp(&done_argc);
__ bind(&argc);
__ Addu(a0, a0, num_extra_args + 1);
__ bind(&done_argc);
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
}

View File

@ -22,8 +22,9 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- a0 : number of arguments excluding receiver
// -- a1 : called function (only guaranteed when
// -- extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- a1 : called function
// -- sp[0] : last argument
// -- ...
// -- sp[8 * (argc - 1)] : first argument
@ -48,8 +49,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects a0 to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But a0 is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
Label argc, done_argc;
__ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
__ Branch(&argc, ne, a2,
Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ Daddu(a0, a2, num_extra_args + 1);
__ jmp(&done_argc);
__ bind(&argc);
__ Daddu(a0, a0, num_extra_args + 1);
__ bind(&done_argc);
__ JumpToExternalReference(ExternalReference(id, masm->isolate()));
}

View File

@ -21,12 +21,13 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
BuiltinExtraArguments extra_args) {
// ----------- S t a t e -------------
// -- rax : number of arguments excluding receiver
// -- rdi : called function (only guaranteed when
// extra_args requires it)
// (only guaranteed when the called function
// is not marked as DontAdaptArguments)
// -- rdi : called function
// -- rsp[0] : return address
// -- rsp[8] : last argument
// -- ...
// -- rsp[8 * argc] : first argument (argc == rax)
// -- rsp[8 * argc] : first argument
// -- rsp[8 * (argc + 1)] : receiver
// -----------------------------------
__ AssertFunction(rdi);
@ -50,8 +51,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
}
// JumpToExternalReference expects rax to contain the number of arguments
// including the receiver and the extra arguments.
// including the receiver and the extra arguments. But rax is only valid
// if the called function is marked as DontAdaptArguments, otherwise we
// need to load the argument count from the SharedFunctionInfo.
Label argc, done_argc;
__ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ LoadSharedFunctionInfoSpecialField(
rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset);
__ cmpp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
__ j(equal, &argc, Label::kNear);
__ leap(rax, Operand(rbx, num_extra_args + 1));
__ jmp(&done_argc, Label::kNear);
__ bind(&argc);
__ addp(rax, Immediate(num_extra_args + 1));
__ bind(&done_argc);
__ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1);
}

View File

@ -0,0 +1,15 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --turbo-asm
var foo = (function(stdlib) {
"use asm";
var bar = stdlib.Symbol;
function foo() { return bar("lala"); }
return foo;
})(this);
%OptimizeFunctionOnNextCall(foo);
foo();