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:
parent
683f43d31b
commit
86b391ecad
@ -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.
|
||||
|
@ -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, ¬_js_frame);
|
||||
__ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ Bind(¬_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, ¬_js_frame);
|
||||
__ Str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
__ Bind(¬_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()));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
17
test/mjsunit/regress/regress-crbug-467047.js
Normal file
17
test/mjsunit/regress/regress-crbug-467047.js
Normal 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);
|
Loading…
Reference in New Issue
Block a user