From 06b8e73b99ad1390e9d47c6cb7261836a21fc5b5 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Tue, 16 Aug 2011 08:48:45 +0000 Subject: [PATCH] MIPS: port Simplify handling of exits from with and catch. Ported r8922 (5ea2fb5) Original commit message: Remove the try/finally used for with and catch. Instead of using try/finally to handle break and continue from with or catch, statically track nesting dept and clean up when compiling break or continue. And instead of using try/finally to handle throw to handler in a frame whose pc is inside a with or catch, store the context that the handler should run in in the handler itself. BUG= TEST= Review URL: http://codereview.chromium.org/7648026 Patch from Paul Lind . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8936 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/frames-mips.h | 9 ++-- src/mips/macro-assembler-mips.cc | 92 ++++++++++++++++---------------- 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/mips/frames-mips.h b/src/mips/frames-mips.h index 2e720fb17..8c605a39d 100644 --- a/src/mips/frames-mips.h +++ b/src/mips/frames-mips.h @@ -121,10 +121,11 @@ static const int kSafepointRegisterStackIndexMap[kNumRegs] = { class StackHandlerConstants : public AllStatic { public: - static const int kNextOffset = 0 * kPointerSize; - static const int kStateOffset = 1 * kPointerSize; - static const int kFPOffset = 2 * kPointerSize; - static const int kPCOffset = 3 * kPointerSize; + static const int kNextOffset = 0 * kPointerSize; + static const int kStateOffset = 1 * kPointerSize; + static const int kContextOffset = 2 * kPointerSize; + static const int kFPOffset = 3 * kPointerSize; + static const int kPCOffset = 4 * kPointerSize; static const int kSize = kPCOffset + kPointerSize; }; diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 5e8d676ac..76b713f51 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -2244,7 +2244,13 @@ void MacroAssembler::DebugBreak() { 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::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. if (try_location == IN_JAVASCRIPT) { if (type == TRY_CATCH_HANDLER) { @@ -2252,19 +2258,16 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, } else { li(t0, Operand(StackHandler::TRY_FINALLY)); } - ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize - && StackHandlerConstants::kFPOffset == 2 * kPointerSize - && StackHandlerConstants::kPCOffset == 3 * kPointerSize - && StackHandlerConstants::kNextOffset == 0 * kPointerSize); // Save the current handler as the next handler. li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); lw(t1, MemOperand(t2)); addiu(sp, sp, -StackHandlerConstants::kSize); - sw(ra, MemOperand(sp, 12)); - sw(fp, MemOperand(sp, 8)); - sw(t0, MemOperand(sp, 4)); - sw(t1, MemOperand(sp, 0)); + 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)); @@ -2272,11 +2275,6 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, } else { // Must preserve a0-a3, and s0 (argv). ASSERT(try_location == IN_JS_ENTRY); - ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize - && StackHandlerConstants::kFPOffset == 2 * kPointerSize - && StackHandlerConstants::kPCOffset == 3 * kPointerSize - && StackHandlerConstants::kNextOffset == 0 * kPointerSize); - // 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. @@ -2286,11 +2284,14 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, li(t2, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); lw(t1, MemOperand(t2)); + ASSERT(Smi::FromInt(0) == 0); // Used for no context. + addiu(sp, sp, -StackHandlerConstants::kSize); - sw(ra, MemOperand(sp, 12)); - sw(zero_reg, MemOperand(sp, 8)); - sw(t0, MemOperand(sp, 4)); - sw(t1, MemOperand(sp, 0)); + 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)); // Link this handler as the new current one. sw(sp, MemOperand(t2)); @@ -2299,7 +2300,7 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, void MacroAssembler::PopTryHandler() { - ASSERT_EQ(0, StackHandlerConstants::kNextOffset); + STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); pop(a1); Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); li(at, Operand(ExternalReference(Isolate::k_handler_address, isolate()))); @@ -2312,28 +2313,31 @@ void MacroAssembler::Throw(Register value) { Move(v0, value); // Adjust this code if not the case. - STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); + 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); // Drop the sp to the top of the handler. li(a3, Operand(ExternalReference(Isolate::k_handler_address, - isolate()))); + isolate()))); lw(sp, MemOperand(a3)); - // Restore the next handler and frame pointer, discard handler state. - STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); + // Restore the next handler. pop(a2); sw(a2, MemOperand(a3)); - STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); - MultiPop(a3.bit() | fp.bit()); - // 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 cp to NULL if fp is NULL. + // Restore context and frame pointer, discard state (a3). + MultiPop(a3.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. Label done; - Branch(USE_DELAY_SLOT, &done, eq, fp, Operand(zero_reg)); - mov(cp, zero_reg); // In branch delay slot. - lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + Branch(&done, eq, fp, Operand(zero_reg)); + sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); bind(&done); #ifdef DEBUG @@ -2355,7 +2359,6 @@ void MacroAssembler::Throw(Register value) { } #endif - STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); pop(t9); // 2 instructions: lw, add sp. Jump(t9); // 2 instructions: jr, nop (in delay slot). @@ -2370,7 +2373,12 @@ void MacroAssembler::Throw(Register value) { void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, Register value) { // Adjust this code if not the case. - STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); + 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); // v0 is expected to hold the exception. Move(v0, value); @@ -2393,7 +2401,6 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, bind(&done); // Set the top handler address to next handler past the current ENTRY handler. - STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); pop(a2); sw(a2, MemOperand(a3)); @@ -2415,20 +2422,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, // Stack layout at this point. See also StackHandlerConstants. // sp -> state (ENTRY) + // cp // fp // ra - // Discard handler state (a2 is not used) and restore frame pointer. - STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); - MultiPop(a2.bit() | fp.bit()); // a2: discarded 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. - Label cp_null; - Branch(USE_DELAY_SLOT, &cp_null, eq, fp, Operand(zero_reg)); - mov(cp, zero_reg); // In the branch delay slot. - lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - bind(&cp_null); + // Restore context and frame pointer, discard state (r2). + MultiPop(a2.bit() | cp.bit() | fp.bit()); #ifdef DEBUG // When emitting debug_code, set ra as return address for the jump. @@ -2448,7 +2447,6 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, addiu(ra, ra, kOffsetRaBytes); } #endif - STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); pop(t9); // 2 instructions: lw, add sp. Jump(t9); // 2 instructions: jr, nop (in delay slot). -- 2.34.1