Index: src/mips/macro-assembler-mips.cc |
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc |
index fb93208bf53f28fd38ee5caf567e59bafc062dc7..c1161d73dd5ec411e79c767cff5b95717553ef77 100644 |
--- a/src/mips/macro-assembler-mips.cc |
+++ b/src/mips/macro-assembler-mips.cc |
@@ -2544,60 +2544,50 @@ void MacroAssembler::DebugBreak() { |
// Exception handling. |
void MacroAssembler::PushTryHandler(CodeLocation try_location, |
- HandlerType type) { |
+ HandlerType type, |
+ int handler_index) { |
// Adjust this code if not the case. |
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
- |
- // The return address is passed in register ra. |
+ STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
+ |
+ // For the JSEntry handler, we must preserve a0-a3 and s0. |
+ // t1-t3 are available. We will build up the handler from the bottom by |
+ // pushing on the stack. First compute the state. |
+ unsigned state = StackHandler::OffsetField::encode(handler_index); |
if (try_location == IN_JAVASCRIPT) { |
- if (type == TRY_CATCH_HANDLER) { |
- li(t0, Operand(StackHandler::TRY_CATCH)); |
- } else { |
- li(t0, Operand(StackHandler::TRY_FINALLY)); |
- } |
- // Save the current handler as the next handler. |
- li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
- lw(t1, MemOperand(t2)); |
- |
- addiu(sp, sp, -StackHandlerConstants::kSize); |
- sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset)); |
- sw(fp, MemOperand(sp, StackHandlerConstants::kFPOffset)); |
- sw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); |
- sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
- sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
- |
- // Link this handler as the new current one. |
- sw(sp, MemOperand(t2)); |
- |
+ state |= (type == TRY_CATCH_HANDLER) |
+ ? StackHandler::KindField::encode(StackHandler::TRY_CATCH) |
+ : StackHandler::KindField::encode(StackHandler::TRY_FINALLY); |
} else { |
- // Must preserve a0-a3, and s0 (argv). |
ASSERT(try_location == IN_JS_ENTRY); |
- // The frame pointer does not point to a JS frame so we save NULL |
- // for fp. We expect the code throwing an exception to check fp |
- // before dereferencing it to restore the context. |
- li(t0, Operand(StackHandler::ENTRY)); |
- |
- // Save the current handler as the next handler. |
- li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
- lw(t1, MemOperand(t2)); |
- |
- ASSERT(Smi::FromInt(0) == 0); // Used for no context. |
+ state |= StackHandler::KindField::encode(StackHandler::ENTRY); |
+ } |
- addiu(sp, sp, -StackHandlerConstants::kSize); |
- sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset)); |
- sw(zero_reg, MemOperand(sp, StackHandlerConstants::kFPOffset)); |
- sw(zero_reg, MemOperand(sp, StackHandlerConstants::kContextOffset)); |
- sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
- sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
+ // Set up the code object (t1) and the state (t2) for pushing. |
+ li(t1, Operand(CodeObject())); |
+ li(t2, Operand(state)); |
- // Link this handler as the new current one. |
- sw(sp, MemOperand(t2)); |
+ // Push the frame pointer, context, state, and code object. |
+ if (try_location == IN_JAVASCRIPT) { |
+ MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit()); |
+ } else { |
+ ASSERT_EQ(Smi::FromInt(0), 0); |
+ // The second zero_reg indicates no context. |
+ // The first zero_reg is the NULL frame pointer. |
+ // The operands are reversed to match the order of MultiPush/Pop. |
+ Push(zero_reg, zero_reg, t2, t1); |
} |
+ |
+ // Link the current handler as the next handler. |
+ li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
+ lw(t1, MemOperand(t2)); |
+ push(t1); |
+ // Set this new handler as the current one. |
+ sw(sp, MemOperand(t2)); |
} |
@@ -2610,19 +2600,36 @@ void MacroAssembler::PopTryHandler() { |
} |
-void MacroAssembler::Throw(Register value) { |
- // v0 is expected to hold the exception. |
- Move(v0, value); |
+void MacroAssembler::JumpToHandlerEntry() { |
+ // Compute the handler entry address and jump to it. The handler table is |
+ // a fixed array of (smi-tagged) code offsets. |
+ // v0 = exception, a1 = code object, a2 = state. |
+ lw(a3, FieldMemOperand(a1, Code::kHandlerTableOffset)); // Handler table. |
+ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ srl(a2, a2, StackHandler::kKindWidth); // Handler index. |
+ sll(a2, a2, kPointerSizeLog2); |
+ Addu(a2, a3, a2); |
+ lw(a2, MemOperand(a2)); // Smi-tagged offset. |
+ Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. |
+ sra(t9, a2, kSmiTagSize); |
+ Addu(t9, t9, a1); |
+ Jump(t9); // Jump. |
+} |
+ |
+void MacroAssembler::Throw(Register value) { |
// Adjust this code if not the case. |
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
+ STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
+ |
+ // The exception is expected in v0. |
+ Move(v0, value); |
- // Drop the sp to the top of the handler. |
+ // Drop the stack pointer to the top of the top handler. |
li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, |
isolate()))); |
lw(sp, MemOperand(a3)); |
@@ -2631,44 +2638,19 @@ void MacroAssembler::Throw(Register value) { |
pop(a2); |
sw(a2, MemOperand(a3)); |
- // Restore context and frame pointer, discard state (a3). |
- MultiPop(a3.bit() | cp.bit() | fp.bit()); |
+ // Get the code object (a1) and state (a2). Restore the context and frame |
+ // pointer. |
+ MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); |
// If the handler is a JS frame, restore the context to the frame. |
- // (a3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any |
- // of them. |
+ // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp |
+ // or cp. |
Label done; |
- Branch(&done, eq, fp, Operand(zero_reg)); |
+ Branch(&done, eq, cp, Operand(zero_reg)); |
sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
bind(&done); |
-#ifdef DEBUG |
- // When emitting debug_code, set ra as return address for the jump. |
- // 5 instructions: add: 1, pop: 2, jump: 2. |
- const int kOffsetRaInstructions = 5; |
- Label find_ra; |
- |
- if (emit_debug_code()) { |
- // Compute ra for the Jump(t9). |
- const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize; |
- |
- // This branch-and-link sequence is needed to get the current PC on mips, |
- // saved to the ra register. Then adjusted for instruction count. |
- bal(&find_ra); // bal exposes branch-delay. |
- nop(); // Branch delay slot nop. |
- bind(&find_ra); |
- addiu(ra, ra, kOffsetRaBytes); |
- } |
-#endif |
- |
- pop(t9); // 2 instructions: lw, add sp. |
- Jump(t9); // 2 instructions: jr, nop (in delay slot). |
- |
- if (emit_debug_code()) { |
- // Make sure that the expected number of instructions were generated. |
- ASSERT_EQ(kOffsetRaInstructions, |
- InstructionsGeneratedSince(&find_ra)); |
- } |
+ JumpToHandlerEntry(); |
} |
@@ -2677,10 +2659,10 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
// Adjust this code if not the case. |
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); |
- STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
+ STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
// The exception is expected in v0. |
if (type == OUT_OF_MEMORY) { |
@@ -2705,26 +2687,27 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
lw(sp, MemOperand(a3)); |
- // Unwind the handlers until the top ENTRY handler is found. |
+ // Unwind the handlers until the ENTRY handler is found. |
Label fetch_next, check_kind; |
jmp(&check_kind); |
bind(&fetch_next); |
lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
bind(&check_kind); |
+ STATIC_ASSERT(StackHandler::ENTRY == 0); |
lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
- Branch(&fetch_next, ne, a2, Operand(StackHandler::ENTRY)); |
+ And(a2, a2, Operand(StackHandler::KindField::kMask)); |
+ Branch(&fetch_next, ne, a2, Operand(zero_reg)); |
// Set the top handler address to next handler past the top ENTRY handler. |
pop(a2); |
sw(a2, MemOperand(a3)); |
- // Clear the context and frame pointer (0 was saved in the handler), and |
- // discard the state (a2). |
- MultiPop(a2.bit() | cp.bit() | fp.bit()); |
+ // Get the code object (a1) and state (a2). Clear the context and frame |
+ // pointer (0 was saved in the handler). |
+ MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); |
- pop(t9); // 2 instructions: lw, add sp. |
- Jump(t9); // 2 instructions: jr, nop (in delay slot). |
+ JumpToHandlerEntry(); |
} |