Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 2b15553f17ed35a5eeb560296e2e9b7d56ff324a..e4a76270a2189b5a99f3c43ea0b4b9dc01e96726 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -2387,18 +2387,15 @@ Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |
void MacroAssembler::PushTryHandler(CodeLocation try_location, |
HandlerType type) { |
// Adjust this code if not the case. |
- ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
// The pc (return address) is already on TOS. This code pushes state, |
- // frame pointer and current handler. Check that they are expected |
- // next on the stack, in that order. |
- ASSERT_EQ(StackHandlerConstants::kStateOffset, |
- StackHandlerConstants::kPCOffset - kPointerSize); |
- ASSERT_EQ(StackHandlerConstants::kFPOffset, |
- StackHandlerConstants::kStateOffset - kPointerSize); |
- ASSERT_EQ(StackHandlerConstants::kNextOffset, |
- StackHandlerConstants::kFPOffset - kPointerSize); |
- |
+ // frame pointer, context, and current handler. |
if (try_location == IN_JAVASCRIPT) { |
if (type == TRY_CATCH_HANDLER) { |
push(Immediate(StackHandler::TRY_CATCH)); |
@@ -2406,6 +2403,7 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, |
push(Immediate(StackHandler::TRY_FINALLY)); |
} |
push(rbp); |
+ push(rsi); |
} else { |
ASSERT(try_location == IN_JS_ENTRY); |
// The frame pointer does not point to a JS frame so we save NULL |
@@ -2413,6 +2411,7 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, |
// before dereferencing it to restore the context. |
push(Immediate(StackHandler::ENTRY)); |
push(Immediate(0)); // NULL frame pointer. |
+ Push(Smi::FromInt(0)); // No context. |
} |
// Save the current handler. |
Operand handler_operand = |
@@ -2435,12 +2434,13 @@ void MacroAssembler::PopTryHandler() { |
void MacroAssembler::Throw(Register value) { |
- // Check that stack should contain next handler, frame pointer, state and |
- // return address in that order. |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
- StackHandlerConstants::kStateOffset); |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
- StackHandlerConstants::kPCOffset); |
+ // Adjust this code if not the case. |
+ STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); |
+ 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); |
@@ -2451,23 +2451,32 @@ void MacroAssembler::Throw(Register value) { |
movq(rsp, handler_operand); |
// get next in chain |
pop(handler_operand); |
- pop(rbp); // pop frame pointer |
- pop(rdx); // remove state |
+ pop(rsi); // Context. |
+ pop(rbp); // Frame pointer. |
+ pop(rdx); // State. |
- // Before returning we restore the context from the frame pointer if not NULL. |
- // The frame pointer is NULL in the exception handler of a JS entry frame. |
- Set(rsi, 0); // Tentatively set context pointer to NULL |
+ // If the handler is a JS frame, restore the context to the frame. |
+ // (rdx == ENTRY) == (rbp == 0) == (rsi == 0), so we could test any |
+ // of them. |
Label skip; |
- cmpq(rbp, Immediate(0)); |
+ cmpq(rdx, Immediate(StackHandler::ENTRY)); |
j(equal, &skip, Label::kNear); |
- movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
+ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); |
bind(&skip); |
+ |
ret(0); |
} |
void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
Register value) { |
+ // Adjust this code if not the case. |
+ STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); |
+ 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); |
@@ -2507,19 +2516,13 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
Store(pending_exception, rax); |
} |
- // Clear the context pointer. |
+ // Discard the context saved in the handler and clear the context pointer. |
+ pop(rdx); |
Set(rsi, 0); |
- // Restore registers from handler. |
- STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == |
- StackHandlerConstants::kFPOffset); |
- pop(rbp); // FP |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
- StackHandlerConstants::kStateOffset); |
- pop(rdx); // State |
+ pop(rbp); // Restore frame pointer. |
+ pop(rdx); // Discard state. |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
- StackHandlerConstants::kPCOffset); |
ret(0); |
} |