Delegate throwing in RegExpExecStub to CEntryStub.

This ensures that there is only one stub that deals with unwinding the
stack. Having more than one place containing that logic is brittle and
error prone, especially when it is a corner case only for RangeErrors.

R=titzer@chromium.org
TEST=mjsunit/regress/regress-crbug-467047
BUG=chromium:467047
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#27243}
This commit is contained in:
mstarzinger 2015-03-17 08:49:24 -07:00 committed by Commit bot
parent 683f43d31b
commit 86b391ecad
11 changed files with 413 additions and 444 deletions

View File

@ -938,60 +938,6 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set r0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, r0);
__ mov(r0, Operand(0));
__ mov(r1, Operand(0));
__ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(cp, Operand(pending_handler_context_address));
__ ldr(cp, MemOperand(cp));
__ mov(sp, Operand(pending_handler_sp_address));
__ ldr(sp, MemOperand(sp));
__ mov(fp, Operand(pending_handler_fp_address));
__ ldr(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
__ cmp(cp, Operand(0));
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
// Compute the handler entry address and jump to it.
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ mov(r1, Operand(pending_handler_code_address));
__ ldr(r1, MemOperand(r1));
__ mov(r2, Operand(pending_handler_offset_address));
__ ldr(r2, MemOperand(r2));
if (FLAG_enable_ool_constant_pool) {
__ ldr(pp, FieldMemOperand(r1, Code::kConstantPoolOffset));
}
__ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ add(pc, r1, r2);
}
void CEntryStub::Generate(MacroAssembler* masm) {
// Called from JavaScript; parameters are on stack as if calling JS function.
// r0: number of arguments including receiver
@ -1098,7 +1044,55 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set r0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, r0);
__ mov(r0, Operand(0));
__ mov(r1, Operand(0));
__ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(cp, Operand(pending_handler_context_address));
__ ldr(cp, MemOperand(cp));
__ mov(sp, Operand(pending_handler_sp_address));
__ ldr(sp, MemOperand(sp));
__ mov(fp, Operand(pending_handler_fp_address));
__ ldr(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
__ cmp(cp, Operand(0));
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
// Compute the handler entry address and jump to it.
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ mov(r1, Operand(pending_handler_code_address));
__ ldr(r1, MemOperand(r1));
__ mov(r2, Operand(pending_handler_offset_address));
__ ldr(r2, MemOperand(r2));
if (FLAG_enable_ool_constant_pool) {
__ ldr(pp, FieldMemOperand(r1, Code::kConstantPoolOffset));
}
__ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ add(pc, r1, r2);
}
@ -2236,8 +2230,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ b(eq, &runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure and exception return null.

View File

@ -1022,66 +1022,6 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
}
static void ThrowPendingException(MacroAssembler* masm, Register scratch1,
Register scratch2) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set x0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
DCHECK(csp.Is(masm->StackPointer()));
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Mov(x0, 0); // argc.
__ Mov(x1, 0); // argv.
__ Mov(x2, ExternalReference::isolate_address(isolate));
__ CallCFunction(find_handler, 3);
}
// We didn't execute a return case, so the stack frame hasn't been updated
// (except for the return address slot). However, we don't need to initialize
// jssp because the throw method will immediately overwrite it when it
// unwinds the stack.
__ SetStackPointer(jssp);
// Retrieve the handler context, SP and FP.
__ Mov(cp, Operand(pending_handler_context_address));
__ Ldr(cp, MemOperand(cp));
__ Mov(jssp, Operand(pending_handler_sp_address));
__ Ldr(jssp, MemOperand(jssp));
__ Mov(fp, Operand(pending_handler_fp_address));
__ Ldr(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label not_js_frame;
__ Cbz(cp, &not_js_frame);
__ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Bind(&not_js_frame);
// Compute the handler entry address and jump to it.
__ Mov(scratch1, Operand(pending_handler_code_address));
__ Ldr(scratch1, MemOperand(scratch1));
__ Mov(scratch2, Operand(pending_handler_offset_address));
__ Ldr(scratch2, MemOperand(scratch2));
__ Add(scratch1, scratch1, Code::kHeaderSize - kHeapObjectTag);
__ Add(scratch1, scratch1, scratch2);
__ Br(scratch1);
}
void CEntryStub::Generate(MacroAssembler* masm) {
// The Abort mechanism relies on CallRuntime, which in turn relies on
// CEntryStub, so until this stub has been generated, we have to use a
@ -1248,7 +1188,60 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ Bind(&exception_returned);
ThrowPendingException(masm, x10, x11);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set x0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
DCHECK(csp.Is(masm->StackPointer()));
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Mov(x0, 0); // argc.
__ Mov(x1, 0); // argv.
__ Mov(x2, ExternalReference::isolate_address(isolate()));
__ CallCFunction(find_handler, 3);
}
// We didn't execute a return case, so the stack frame hasn't been updated
// (except for the return address slot). However, we don't need to initialize
// jssp because the throw method will immediately overwrite it when it
// unwinds the stack.
__ SetStackPointer(jssp);
// Retrieve the handler context, SP and FP.
__ Mov(cp, Operand(pending_handler_context_address));
__ Ldr(cp, MemOperand(cp));
__ Mov(jssp, Operand(pending_handler_sp_address));
__ Ldr(jssp, MemOperand(jssp));
__ Mov(fp, Operand(pending_handler_fp_address));
__ Ldr(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label not_js_frame;
__ Cbz(cp, &not_js_frame);
__ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ Bind(&not_js_frame);
// Compute the handler entry address and jump to it.
__ Mov(x10, Operand(pending_handler_code_address));
__ Ldr(x10, MemOperand(x10));
__ Mov(x11, Operand(pending_handler_offset_address));
__ Ldr(x11, MemOperand(x11));
__ Add(x10, x10, Code::kHeaderSize - kHeapObjectTag);
__ Add(x10, x10, x11);
__ Br(x10);
}
@ -2682,8 +2675,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ B(eq, &runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false, x10);
ThrowPendingException(masm, x10, x11);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ Bind(&failure);
__ Mov(x0, Operand(isolate()->factory()->null_value()));

View File

@ -1185,55 +1185,6 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set eax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, eax);
__ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); // argc.
__ mov(Operand(esp, 1 * kPointerSize), Immediate(0)); // argv.
__ mov(Operand(esp, 2 * kPointerSize),
Immediate(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(esi, Operand::StaticVariable(pending_handler_context_address));
__ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
__ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
// ebp or esi.
Label skip;
__ test(esi, esi);
__ j(zero, &skip, Label::kNear);
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(edi, Operand::StaticVariable(pending_handler_code_address));
__ mov(edx, Operand::StaticVariable(pending_handler_offset_address));
__ lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
__ jmp(edi);
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1517,8 +1468,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ j(equal, &runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure to match, return null.
@ -2576,7 +2526,50 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set eax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, eax);
__ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); // argc.
__ mov(Operand(esp, 1 * kPointerSize), Immediate(0)); // argv.
__ mov(Operand(esp, 2 * kPointerSize),
Immediate(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(esi, Operand::StaticVariable(pending_handler_context_address));
__ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
__ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
// ebp or esi.
Label skip;
__ test(esi, esi);
__ j(zero, &skip, Label::kNear);
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(edi, Operand::StaticVariable(pending_handler_code_address));
__ mov(edx, Operand::StaticVariable(pending_handler_offset_address));
__ lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
__ jmp(edi);
}

View File

@ -1037,59 +1037,6 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set v0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, a0);
__ mov(a0, zero_reg);
__ mov(a1, zero_reg);
__ li(a2, Operand(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ li(cp, Operand(pending_handler_context_address));
__ lw(cp, MemOperand(cp));
__ li(sp, Operand(pending_handler_sp_address));
__ lw(sp, MemOperand(sp));
__ li(fp, Operand(pending_handler_fp_address));
__ lw(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label zero;
__ Branch(&zero, eq, cp, Operand(zero_reg));
__ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero);
// Compute the handler entry address and jump to it.
__ li(a1, Operand(pending_handler_code_address));
__ lw(a1, MemOperand(a1));
__ li(a2, Operand(pending_handler_offset_address));
__ lw(a2, MemOperand(a2));
__ Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Addu(t9, a1, a2);
__ Jump(t9);
}
void CEntryStub::Generate(MacroAssembler* masm) {
// Called from JavaScript; parameters are on stack as if calling JS function
// a0: number of arguments including receiver
@ -1199,7 +1146,54 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set v0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, a0);
__ mov(a0, zero_reg);
__ mov(a1, zero_reg);
__ li(a2, Operand(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ li(cp, Operand(pending_handler_context_address));
__ lw(cp, MemOperand(cp));
__ li(sp, Operand(pending_handler_sp_address));
__ lw(sp, MemOperand(sp));
__ li(fp, Operand(pending_handler_fp_address));
__ lw(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label zero;
__ Branch(&zero, eq, cp, Operand(zero_reg));
__ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero);
// Compute the handler entry address and jump to it.
__ li(a1, Operand(pending_handler_code_address));
__ lw(a1, MemOperand(a1));
__ li(a2, Operand(pending_handler_offset_address));
__ lw(a2, MemOperand(a2));
__ Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Addu(t9, a1, a2);
__ Jump(t9);
}
@ -2373,8 +2367,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ Branch(&runtime, eq, v0, Operand(a1));
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure and exception return null.

View File

@ -1033,59 +1033,6 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set v0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, a0);
__ mov(a0, zero_reg);
__ mov(a1, zero_reg);
__ li(a2, Operand(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ li(cp, Operand(pending_handler_context_address));
__ ld(cp, MemOperand(cp));
__ li(sp, Operand(pending_handler_sp_address));
__ ld(sp, MemOperand(sp));
__ li(fp, Operand(pending_handler_fp_address));
__ ld(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label zero;
__ Branch(&zero, eq, cp, Operand(zero_reg));
__ sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero);
// Compute the handler entry address and jump to it.
__ li(a1, Operand(pending_handler_code_address));
__ ld(a1, MemOperand(a1));
__ li(a2, Operand(pending_handler_offset_address));
__ ld(a2, MemOperand(a2));
__ Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Daddu(t9, a1, a2);
__ Jump(t9);
}
void CEntryStub::Generate(MacroAssembler* masm) {
// Called from JavaScript; parameters are on stack as if calling JS function
// a0: number of arguments including receiver
@ -1194,7 +1141,54 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set v0 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, a0);
__ mov(a0, zero_reg);
__ mov(a1, zero_reg);
__ li(a2, Operand(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ li(cp, Operand(pending_handler_context_address));
__ ld(cp, MemOperand(cp));
__ li(sp, Operand(pending_handler_sp_address));
__ ld(sp, MemOperand(sp));
__ li(fp, Operand(pending_handler_fp_address));
__ ld(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label zero;
__ Branch(&zero, eq, cp, Operand(zero_reg));
__ sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero);
// Compute the handler entry address and jump to it.
__ li(a1, Operand(pending_handler_code_address));
__ ld(a1, MemOperand(a1));
__ li(a2, Operand(pending_handler_offset_address));
__ ld(a2, MemOperand(a2));
__ Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Daddu(t9, a1, a2);
__ Jump(t9);
}
@ -2409,8 +2403,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ Branch(&runtime, eq, v0, Operand(a1));
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure and exception return null.

View File

@ -995,60 +995,6 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set r3 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, r3);
__ li(r3, Operand::Zero());
__ li(r4, Operand::Zero());
__ mov(r5, Operand(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(cp, Operand(pending_handler_context_address));
__ LoadP(cp, MemOperand(cp));
__ mov(sp, Operand(pending_handler_sp_address));
__ LoadP(sp, MemOperand(sp));
__ mov(fp, Operand(pending_handler_fp_address));
__ LoadP(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label skip;
__ cmpi(cp, Operand::Zero());
__ beq(&skip);
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(r4, Operand(pending_handler_code_address));
__ LoadP(r4, MemOperand(r4));
__ mov(r5, Operand(pending_handler_offset_address));
__ LoadP(r5, MemOperand(r5));
__ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start
__ add(ip, r4, r5);
__ Jump(ip);
}
void CEntryStub::Generate(MacroAssembler* masm) {
// Called from JavaScript; parameters are on stack as if calling JS function.
// r3: number of arguments including receiver
@ -1180,7 +1126,54 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set r3 to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, 0, r3);
__ li(r3, Operand::Zero());
__ li(r4, Operand::Zero());
__ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(cp, Operand(pending_handler_context_address));
__ LoadP(cp, MemOperand(cp));
__ mov(sp, Operand(pending_handler_sp_address));
__ LoadP(sp, MemOperand(sp));
__ mov(fp, Operand(pending_handler_fp_address));
__ LoadP(fp, MemOperand(fp));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
// or cp.
Label skip;
__ cmpi(cp, Operand::Zero());
__ beq(&skip);
__ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(r4, Operand(pending_handler_code_address));
__ LoadP(r4, MemOperand(r4));
__ mov(r5, Operand(pending_handler_offset_address));
__ LoadP(r5, MemOperand(r5));
__ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start
__ add(ip, r4, r5);
__ Jump(ip);
}
@ -2401,8 +2394,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ beq(&runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure and exception return null.

View File

@ -1110,6 +1110,15 @@ RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
}
RUNTIME_FUNCTION(Runtime_RegExpExecReThrow) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 4);
Object* exception = isolate->pending_exception();
isolate->clear_pending_exception();
return isolate->ReThrow(exception);
}
RUNTIME_FUNCTION(Runtime_IsRegExp) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);

View File

@ -153,6 +153,7 @@ namespace internal {
/* Regular expressions */ \
F(RegExpInitializeAndCompile, 3, 1) \
F(RegExpExecMultiple, 4, 1) \
F(RegExpExecReThrow, 4, 1) \
\
/* JSON */ \
F(ParseJson, 1, 1) \

View File

@ -1044,54 +1044,6 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set rax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ movp(arg_reg_1, Immediate(0)); // argc.
__ movp(arg_reg_2, Immediate(0)); // argv.
__ Move(arg_reg_3, ExternalReference::isolate_address(isolate));
__ PrepareCallCFunction(3);
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ movp(rsi, masm->ExternalOperand(pending_handler_context_address));
__ movp(rsp, masm->ExternalOperand(pending_handler_sp_address));
__ movp(rbp, masm->ExternalOperand(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either
// rbp or rsi.
Label skip;
__ testp(rsi, rsi);
__ j(zero, &skip, Label::kNear);
__ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ movp(rdi, masm->ExternalOperand(pending_handler_code_address));
__ movp(rdx, masm->ExternalOperand(pending_handler_offset_address));
__ leap(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize));
__ jmp(rdi);
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1480,8 +1432,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ j(equal, &runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
// Do the runtime call to execute the regexp.
__ bind(&runtime);
@ -2492,7 +2443,49 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set rax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ movp(arg_reg_1, Immediate(0)); // argc.
__ movp(arg_reg_2, Immediate(0)); // argv.
__ Move(arg_reg_3, ExternalReference::isolate_address(isolate()));
__ PrepareCallCFunction(3);
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ movp(rsi, masm->ExternalOperand(pending_handler_context_address));
__ movp(rsp, masm->ExternalOperand(pending_handler_sp_address));
__ movp(rbp, masm->ExternalOperand(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either
// rbp or rsi.
Label skip;
__ testp(rsi, rsi);
__ j(zero, &skip, Label::kNear);
__ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ movp(rdi, masm->ExternalOperand(pending_handler_code_address));
__ movp(rdx, masm->ExternalOperand(pending_handler_offset_address));
__ leap(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize));
__ jmp(rdi);
}

View File

@ -865,55 +865,6 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
}
static void ThrowPendingException(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate);
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate);
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate);
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate);
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate);
// Ask the runtime for help to determine the handler. This will set eax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, eax);
__ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); // argc.
__ mov(Operand(esp, 1 * kPointerSize), Immediate(0)); // argv.
__ mov(Operand(esp, 2 * kPointerSize),
Immediate(ExternalReference::isolate_address(isolate)));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(esi, Operand::StaticVariable(pending_handler_context_address));
__ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
__ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
// ebp or esi.
Label skip;
__ test(esi, esi);
__ j(zero, &skip, Label::kNear);
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(edi, Operand::StaticVariable(pending_handler_code_address));
__ mov(edx, Operand::StaticVariable(pending_handler_offset_address));
__ lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
__ jmp(edi);
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1197,8 +1148,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ j(equal, &runtime);
// For exception, throw the exception again.
__ EnterExitFrame(false);
ThrowPendingException(masm);
__ TailCallRuntime(Runtime::kRegExpExecReThrow, 4, 1);
__ bind(&failure);
// For failure to match, return null.
@ -2267,7 +2217,50 @@ void CEntryStub::Generate(MacroAssembler* masm) {
// Handling of exception.
__ bind(&exception_returned);
ThrowPendingException(masm);
ExternalReference pending_handler_context_address(
Isolate::kPendingHandlerContextAddress, isolate());
ExternalReference pending_handler_code_address(
Isolate::kPendingHandlerCodeAddress, isolate());
ExternalReference pending_handler_offset_address(
Isolate::kPendingHandlerOffsetAddress, isolate());
ExternalReference pending_handler_fp_address(
Isolate::kPendingHandlerFPAddress, isolate());
ExternalReference pending_handler_sp_address(
Isolate::kPendingHandlerSPAddress, isolate());
// Ask the runtime for help to determine the handler. This will set eax to
// contain the current pending exception, don't clobber it.
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
{
FrameScope scope(masm, StackFrame::MANUAL);
__ PrepareCallCFunction(3, eax);
__ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); // argc.
__ mov(Operand(esp, 1 * kPointerSize), Immediate(0)); // argv.
__ mov(Operand(esp, 2 * kPointerSize),
Immediate(ExternalReference::isolate_address(isolate())));
__ CallCFunction(find_handler, 3);
}
// Retrieve the handler context, SP and FP.
__ mov(esi, Operand::StaticVariable(pending_handler_context_address));
__ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
__ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
// If the handler is a JS frame, restore the context to the frame.
// (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
// ebp or esi.
Label skip;
__ test(esi, esi);
__ j(zero, &skip, Label::kNear);
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
__ bind(&skip);
// Compute the handler entry address and jump to it.
__ mov(edi, Operand::StaticVariable(pending_handler_code_address));
__ mov(edx, Operand::StaticVariable(pending_handler_offset_address));
__ lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
__ jmp(edi);
}

View File

@ -0,0 +1,17 @@
// 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: --stack-size=100
function captureMatch(re) {
var local_variable = 0;
"abcd".replace(re, function() { });
assertEquals("abcd", RegExp.input);
assertEquals("a", RegExp.leftContext);
assertEquals("bc", RegExp.lastMatch);
assertEquals("d", RegExp.rightContext);
assertEquals("foo", captureMatch(/^bar/));
}
assertThrows(function() { captureMatch(/(bc)/) }, RangeError);