Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 56a2d6f935467c393a905bfec7edb139bf078dac..13de3e49bc85f0ac6fdc69423b0f32621518f860 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -1536,6 +1536,96 @@ 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); |
+ // Keep thrown value in rax. |
+ if (!value.is(rax)) { |
+ movq(rax, value); |
+ } |
+ |
+ ExternalReference handler_address(Top::k_handler_address); |
+ movq(kScratchRegister, handler_address); |
+ movq(rsp, Operand(kScratchRegister, 0)); |
+ // get next in chain |
+ pop(rcx); |
+ movq(Operand(kScratchRegister, 0), rcx); |
+ pop(rbp); // pop frame pointer |
+ pop(rdx); // remove 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 |
+ NearLabel skip; |
+ cmpq(rbp, Immediate(0)); |
+ j(equal, &skip); |
+ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
+ bind(&skip); |
+ ret(0); |
+} |
+ |
+ |
+void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
+ Register value) { |
+ // Keep thrown value in rax. |
+ if (!value.is(rax)) { |
+ movq(rax, value); |
+ } |
+ // Fetch top stack handler. |
+ ExternalReference handler_address(Top::k_handler_address); |
+ movq(kScratchRegister, handler_address); |
+ movq(rsp, Operand(kScratchRegister, 0)); |
+ |
+ // Unwind the handlers until the ENTRY handler is found. |
+ NearLabel 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); |
+ // 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. |
+ movq(kScratchRegister, handler_address); |
+ pop(Operand(kScratchRegister, 0)); |
+ |
+ if (type == OUT_OF_MEMORY) { |
+ // Set external caught exception to false. |
+ ExternalReference external_caught(Top::k_external_caught_exception_address); |
+ movq(rax, Immediate(false)); |
+ store_rax(external_caught); |
+ |
+ // Set pending exception and rax to out of memory exception. |
+ ExternalReference pending_exception(Top::k_pending_exception_address); |
+ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
+ store_rax(pending_exception); |
+ } |
+ |
+ // Clear the context pointer. |
+ 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 |
+ |
+ STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
+ StackHandlerConstants::kPCOffset); |
+ ret(0); |
+} |
+ |
+ |
void MacroAssembler::Ret() { |
ret(0); |
} |