Tighten the code for MacroAssembler::ThrowUncatchable.

Test at the bottom in the unwind loop.  Eliminate the possibility of a
useless move to the eax/rax/r0 register (currently impossible because
this function has two call sites).  Do not explicitly zero the context
because we've already saved 0 as the context in the handler.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/8493008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9909 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-11-08 11:09:00 +00:00
parent 59a472a742
commit aee8ae0548
3 changed files with 79 additions and 105 deletions

View File

@ -1258,37 +1258,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
// r0 is expected to hold the exception.
if (!value.is(r0)) {
mov(r0, value);
}
// Drop sp to the top stack handler.
mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
ldr(sp, MemOperand(r3));
// Unwind the handlers until the ENTRY handler is found.
Label loop, done;
bind(&loop);
// Load the type of the current stack handler.
const int kStateOffset = StackHandlerConstants::kStateOffset;
ldr(r2, MemOperand(sp, kStateOffset));
cmp(r2, Operand(StackHandler::ENTRY));
b(eq, &done);
// Fetch the next handler in the list.
const int kNextOffset = StackHandlerConstants::kNextOffset;
ldr(sp, MemOperand(sp, kNextOffset));
jmp(&loop);
bind(&done);
// Set the top handler address to next handler past the current ENTRY handler.
pop(r2);
str(r2, MemOperand(r3));
// The exception is expected in r0.
if (type == OUT_OF_MEMORY) {
// Set external caught exception to false.
ExternalReference external_caught(
Isolate::kExternalCaughtExceptionAddress, isolate());
ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
isolate());
mov(r0, Operand(false, RelocInfo::NONE));
mov(r2, Operand(external_caught));
str(r0, MemOperand(r2));
@ -1299,21 +1274,33 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
isolate())));
str(r0, MemOperand(r2));
} else if (!value.is(r0)) {
mov(r0, value);
}
// Stack layout at this point. See also StackHandlerConstants.
// sp -> state (ENTRY)
// cp
// fp
// lr
// Drop the stack pointer to the top of the top stack handler.
mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
ldr(sp, MemOperand(r3));
// Restore context and frame pointer, discard state (r2).
// Unwind the handlers until the top ENTRY handler is found.
Label fetch_next, check_kind;
jmp(&check_kind);
bind(&fetch_next);
ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset));
cmp(r2, Operand(StackHandler::ENTRY));
b(ne, &fetch_next);
// Set the top handler address to next handler past the top ENTRY handler.
pop(r2);
str(r2, MemOperand(r3));
// Clear the context and frame pointer (0 was saved in the handler), and
// discard the state (r2).
ldm(ia_w, sp, r2.bit() | cp.bit() | fp.bit());
#ifdef DEBUG
if (emit_debug_code()) {
mov(lr, Operand(pc));
}
#endif
pop(pc);
}

View File

@ -816,52 +816,43 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
// eax must hold the exception.
if (!value.is(eax)) {
mov(eax, value);
}
// Drop sp to the top stack handler.
ExternalReference handler_address(Isolate::kHandlerAddress,
isolate());
mov(esp, Operand::StaticVariable(handler_address));
// Unwind the handlers until the ENTRY handler is found.
Label loop, done;
bind(&loop);
// Load the type of the current stack handler.
const int kStateOffset = StackHandlerConstants::kStateOffset;
cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
j(equal, &done, Label::kNear);
// Fetch the next handler in the list.
const int kNextOffset = StackHandlerConstants::kNextOffset;
mov(esp, Operand(esp, kNextOffset));
jmp(&loop);
bind(&done);
// Set the top handler address to next handler past the current ENTRY handler.
pop(Operand::StaticVariable(handler_address));
// The exception is expected in eax.
if (type == OUT_OF_MEMORY) {
// Set external caught exception to false.
ExternalReference external_caught(
Isolate::kExternalCaughtExceptionAddress,
isolate());
mov(eax, false);
mov(Operand::StaticVariable(external_caught), eax);
ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
isolate());
mov(Operand::StaticVariable(external_caught), Immediate(false));
// Set pending exception and eax to out of memory exception.
ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
isolate());
mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
mov(Operand::StaticVariable(pending_exception), eax);
} else if (!value.is(eax)) {
mov(eax, value);
}
// Discard the context saved in the handler and clear the context pointer.
pop(edx);
Set(esi, Immediate(0));
// Drop the stack pointer to the top of the top stack handler.
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
mov(esp, Operand::StaticVariable(handler_address));
// Restore fp from handler and discard handler state.
// Unwind the handlers until the top ENTRY handler is found.
Label fetch_next, check_kind;
jmp(&check_kind, Label::kNear);
bind(&fetch_next);
mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
cmp(Operand(esp, StackHandlerConstants::kStateOffset),
Immediate(StackHandler::ENTRY));
j(not_equal, &fetch_next);
// Set the top handler address to next handler past the top ENTRY handler.
pop(Operand::StaticVariable(handler_address));
// Clear the context and frame pointer (0 was saved in the handler), and
// discard the state.
pop(esi);
pop(ebp);
pop(edx); // State.

View File

@ -2509,35 +2509,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
// Keep thrown value in rax.
if (!value.is(rax)) {
movq(rax, value);
}
// Fetch top stack handler.
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
Load(rsp, handler_address);
// Unwind the handlers until the ENTRY handler is found.
Label loop, done;
bind(&loop);
// Load the type of the current stack handler.
const int kStateOffset = StackHandlerConstants::kStateOffset;
cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
j(equal, &done, Label::kNear);
// Fetch the next handler in the list.
const int kNextOffset = StackHandlerConstants::kNextOffset;
movq(rsp, Operand(rsp, kNextOffset));
jmp(&loop);
bind(&done);
// Set the top handler address to next handler past the current ENTRY handler.
Operand handler_operand = ExternalOperand(handler_address);
pop(handler_operand);
// The exception is expected in rax.
if (type == OUT_OF_MEMORY) {
// Set external caught exception to false.
ExternalReference external_caught(
Isolate::kExternalCaughtExceptionAddress, isolate());
ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
isolate());
Set(rax, static_cast<int64_t>(false));
Store(external_caught, rax);
@ -2546,14 +2523,33 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
isolate());
movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
Store(pending_exception, rax);
} else if (!value.is(rax)) {
movq(rax, value);
}
// Discard the context saved in the handler and clear the context pointer.
pop(rdx);
Set(rsi, 0);
// Drop the stack pointer to the top of the top stack handler.
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
Load(rsp, handler_address);
pop(rbp); // Restore frame pointer.
pop(rdx); // Discard state.
// Unwind the handlers until the top ENTRY handler is found.
Label fetch_next, check_kind;
jmp(&check_kind, Label::kNear);
bind(&fetch_next);
movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
bind(&check_kind);
cmpq(Operand(rsp, StackHandlerConstants::kStateOffset),
Immediate(StackHandler::ENTRY));
j(not_equal, &fetch_next);
// Set the top handler address to next handler past the top ENTRY handler.
pop(ExternalOperand(handler_address));
// Clear the context and frame pointer (0 was saved in the handler), and
// discard the state.
pop(rsi);
pop(rbp);
pop(rdx); // State.
ret(0);
}