Check stack limit in ArgumentAdaptorTrampoline.
BUG=353058 LOG=N TEST=mjsunit/regress/regress-353058 R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/215853005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20692 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
49d951d043
commit
4268ce0abd
@ -1284,7 +1284,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Out of stack space.
|
||||
__ ldr(r1, MemOperand(fp, kFunctionOffset));
|
||||
__ Push(r1, r0);
|
||||
__ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
||||
// End of stack check.
|
||||
|
||||
// Push current limit and index.
|
||||
@ -1407,6 +1407,26 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
|
||||
Label* stack_overflow) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : actual number of arguments
|
||||
// -- r1 : function (passed through to callee)
|
||||
// -- r2 : expected number of arguments
|
||||
// -----------------------------------
|
||||
// Check the stack for overflow. We are not trying to catch
|
||||
// interruptions (e.g. debug break and preemption) here, so the "real stack
|
||||
// limit" is checked.
|
||||
__ LoadRoot(r5, Heap::kRealStackLimitRootIndex);
|
||||
// Make r5 the space we have left. The stack might already be overflowed
|
||||
// here which will cause r5 to become negative.
|
||||
__ sub(r5, sp, r5);
|
||||
// Check if the arguments will overflow the stack.
|
||||
__ cmp(r5, Operand(r2, LSL, kPointerSizeLog2));
|
||||
__ b(le, stack_overflow); // Signed comparison.
|
||||
}
|
||||
|
||||
|
||||
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
|
||||
__ SmiTag(r0);
|
||||
__ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
|
||||
@ -1446,6 +1466,8 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// -- r2 : expected number of arguments
|
||||
// -----------------------------------
|
||||
|
||||
Label stack_overflow;
|
||||
ArgumentAdaptorStackCheck(masm, &stack_overflow);
|
||||
Label invoke, dont_adapt_arguments;
|
||||
|
||||
Label enough, too_few;
|
||||
@ -1545,6 +1567,11 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// -------------------------------------------
|
||||
__ bind(&dont_adapt_arguments);
|
||||
__ Jump(r3);
|
||||
|
||||
__ bind(&stack_overflow);
|
||||
EnterArgumentsAdaptorFrame(masm);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, JUMP_FUNCTION);
|
||||
__ bkpt(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1280,7 +1280,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// There is not enough stack space, so use a builtin to throw an appropriate
|
||||
// error.
|
||||
__ Push(function, argc);
|
||||
__ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
||||
// We should never return from the APPLY_OVERFLOW builtin.
|
||||
if (__ emit_debug_code()) {
|
||||
__ Unreachable();
|
||||
@ -1400,6 +1400,28 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
|
||||
Label* stack_overflow) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x0 : actual number of arguments
|
||||
// -- x1 : function (passed through to callee)
|
||||
// -- x2 : expected number of arguments
|
||||
// -----------------------------------
|
||||
// Check the stack for overflow.
|
||||
// We are not trying to catch interruptions (e.g. debug break and
|
||||
// preemption) here, so the "real stack limit" is checked.
|
||||
Label enough_stack_space;
|
||||
__ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
|
||||
// Make x10 the space we have left. The stack might already be overflowed
|
||||
// here which will cause x10 to become negative.
|
||||
__ Sub(x10, jssp, x10);
|
||||
__ Mov(x11, jssp);
|
||||
// Check if the arguments will overflow the stack.
|
||||
__ Cmp(x10, Operand(x2, LSL, kPointerSizeLog2));
|
||||
__ B(le, stack_overflow);
|
||||
}
|
||||
|
||||
|
||||
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
|
||||
__ SmiTag(x10, x0);
|
||||
__ Mov(x11, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
@ -1433,6 +1455,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// -- x2 : expected number of arguments
|
||||
// -----------------------------------
|
||||
|
||||
Label stack_overflow;
|
||||
ArgumentAdaptorStackCheck(masm, &stack_overflow);
|
||||
|
||||
Register argc_actual = x0; // Excluding the receiver.
|
||||
Register argc_expected = x2; // Excluding the receiver.
|
||||
Register function = x1;
|
||||
@ -1552,6 +1577,11 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// Call the entry point without adapting the arguments.
|
||||
__ Bind(&dont_adapt_arguments);
|
||||
__ Jump(code_entry);
|
||||
|
||||
__ Bind(&stack_overflow);
|
||||
EnterArgumentsAdaptorFrame(masm);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, JUMP_FUNCTION);
|
||||
__ Brk(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,7 +260,7 @@ enum BuiltinExtraArguments {
|
||||
V(STRING_ADD_LEFT, 1) \
|
||||
V(STRING_ADD_RIGHT, 1) \
|
||||
V(APPLY_PREPARE, 1) \
|
||||
V(APPLY_OVERFLOW, 1)
|
||||
V(STACK_OVERFLOW, 1)
|
||||
|
||||
class BuiltinFunctionTable;
|
||||
class ObjectVisitor;
|
||||
|
@ -949,7 +949,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Out of stack space.
|
||||
__ push(Operand(ebp, 4 * kPointerSize)); // push this
|
||||
__ push(eax);
|
||||
__ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
||||
__ bind(&okay);
|
||||
// End of stack check.
|
||||
|
||||
@ -1252,6 +1252,33 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
|
||||
Label* stack_overflow) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : actual number of arguments
|
||||
// -- ebx : expected number of arguments
|
||||
// -- edi : function (passed through to callee)
|
||||
// -----------------------------------
|
||||
// Check the stack for overflow. We are not trying to catch
|
||||
// interruptions (e.g. debug break and preemption) here, so the "real stack
|
||||
// limit" is checked.
|
||||
ExternalReference real_stack_limit =
|
||||
ExternalReference::address_of_real_stack_limit(masm->isolate());
|
||||
__ mov(edx, Operand::StaticVariable(real_stack_limit));
|
||||
// Make ecx the space we have left. The stack might already be overflowed
|
||||
// here which will cause ecx to become negative.
|
||||
__ mov(ecx, esp);
|
||||
__ sub(ecx, edx);
|
||||
// Make edx the space we need for the array when it is unrolled onto the
|
||||
// stack.
|
||||
__ mov(edx, ebx);
|
||||
__ shl(edx, kPointerSizeLog2);
|
||||
// Check if the arguments will overflow the stack.
|
||||
__ cmp(ecx, edx);
|
||||
__ j(less_equal, stack_overflow); // Signed comparison.
|
||||
}
|
||||
|
||||
|
||||
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
|
||||
__ push(ebp);
|
||||
__ mov(ebp, esp);
|
||||
@ -1296,6 +1323,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
Label invoke, dont_adapt_arguments;
|
||||
__ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
|
||||
|
||||
Label stack_overflow;
|
||||
ArgumentsAdaptorStackCheck(masm, &stack_overflow);
|
||||
|
||||
Label enough, too_few;
|
||||
__ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
|
||||
__ cmp(eax, ebx);
|
||||
@ -1370,6 +1400,11 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// -------------------------------------------
|
||||
__ bind(&dont_adapt_arguments);
|
||||
__ jmp(edx);
|
||||
|
||||
__ bind(&stack_overflow);
|
||||
EnterArgumentsAdaptorFrame(masm);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, JUMP_FUNCTION);
|
||||
__ int3();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1305,7 +1305,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Out of stack space.
|
||||
__ lw(a1, MemOperand(fp, kFunctionOffset));
|
||||
__ Push(a1, v0);
|
||||
__ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
||||
// End of stack check.
|
||||
|
||||
// Push current limit and index.
|
||||
|
@ -464,7 +464,7 @@ function APPLY_PREPARE(args) {
|
||||
}
|
||||
|
||||
|
||||
function APPLY_OVERFLOW(length) {
|
||||
function STACK_OVERFLOW(length) {
|
||||
throw %MakeRangeError('stack_overflow', []);
|
||||
}
|
||||
|
||||
|
@ -1017,7 +1017,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
|
||||
// Out of stack space.
|
||||
__ Push(Operand(rbp, kFunctionOffset));
|
||||
__ Push(rax);
|
||||
__ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
|
||||
__ bind(&okay);
|
||||
// End of stack check.
|
||||
|
||||
@ -1322,6 +1322,31 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
|
||||
Label* stack_overflow) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : actual number of arguments
|
||||
// -- rbx : expected number of arguments
|
||||
// -- rdi: function (passed through to callee)
|
||||
// -----------------------------------
|
||||
// Check the stack for overflow. We are not trying to catch
|
||||
// interruptions (e.g. debug break and preemption) here, so the "real stack
|
||||
// limit" is checked.
|
||||
Label okay;
|
||||
__ LoadRoot(rdx, Heap::kRealStackLimitRootIndex);
|
||||
__ movp(rcx, rsp);
|
||||
// Make rcx the space we have left. The stack might already be overflowed
|
||||
// here which will cause rcx to become negative.
|
||||
__ subp(rcx, rdx);
|
||||
// Make rdx the space we need for the array when it is unrolled onto the
|
||||
// stack.
|
||||
__ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
|
||||
// Check if the arguments will overflow the stack.
|
||||
__ cmpp(rcx, rdx);
|
||||
__ j(less_equal, stack_overflow); // Signed comparison.
|
||||
}
|
||||
|
||||
|
||||
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
|
||||
__ pushq(rbp);
|
||||
__ movp(rbp, rsp);
|
||||
@ -1367,6 +1392,9 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->arguments_adaptors(), 1);
|
||||
|
||||
Label stack_overflow;
|
||||
ArgumentsAdaptorStackCheck(masm, &stack_overflow);
|
||||
|
||||
Label enough, too_few;
|
||||
__ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
|
||||
__ cmpp(rax, rbx);
|
||||
@ -1439,6 +1467,11 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||
// -------------------------------------------
|
||||
__ bind(&dont_adapt_arguments);
|
||||
__ jmp(rdx);
|
||||
|
||||
__ bind(&stack_overflow);
|
||||
EnterArgumentsAdaptorFrame(masm);
|
||||
__ InvokeBuiltin(Builtins::STACK_OVERFLOW, JUMP_FUNCTION);
|
||||
__ int3();
|
||||
}
|
||||
|
||||
|
||||
|
27
test/mjsunit/regress/regress-353058.js
Normal file
27
test/mjsunit/regress/regress-353058.js
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 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: --stack-size=150
|
||||
// Requries ASAN.
|
||||
|
||||
function runNearStackLimit(f) { function t() { try { t(); } catch(e) { f(); } }; try { t(); } catch(e) {} }
|
||||
function __f_0(
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
|
||||
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
|
||||
) { }
|
||||
runNearStackLimit(__f_0);
|
Loading…
Reference in New Issue
Block a user