Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: src/mips/macro-assembler-mips.cc

Issue 8557003: MIPS: Add a level of indirection to exception handler addresses. (Closed)
Patch Set: Rebased on r10024 Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips/macro-assembler-mips.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2526 matching lines...) Expand 10 before | Expand all | Expand 10 after
2537 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 2537 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
2538 } 2538 }
2539 2539
2540 #endif // ENABLE_DEBUGGER_SUPPORT 2540 #endif // ENABLE_DEBUGGER_SUPPORT
2541 2541
2542 2542
2543 // --------------------------------------------------------------------------- 2543 // ---------------------------------------------------------------------------
2544 // Exception handling. 2544 // Exception handling.
2545 2545
2546 void MacroAssembler::PushTryHandler(CodeLocation try_location, 2546 void MacroAssembler::PushTryHandler(CodeLocation try_location,
2547 HandlerType type) { 2547 HandlerType type,
2548 int handler_index) {
2548 // Adjust this code if not the case. 2549 // Adjust this code if not the case.
2549 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 2550 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2550 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 2551 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2551 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); 2552 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
2552 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); 2553 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
2553 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); 2554 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
2554 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); 2555 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
2555 2556
2556 // The return address is passed in register ra. 2557 // For the JSEntry handler, we must preserve a0-a3 and s0.
2558 // t1-t3 are available. We will build up the handler from the bottom by
2559 // pushing on the stack. First compute the state.
2560 unsigned state = StackHandler::OffsetField::encode(handler_index);
2557 if (try_location == IN_JAVASCRIPT) { 2561 if (try_location == IN_JAVASCRIPT) {
2558 if (type == TRY_CATCH_HANDLER) { 2562 state |= (type == TRY_CATCH_HANDLER)
2559 li(t0, Operand(StackHandler::TRY_CATCH)); 2563 ? StackHandler::KindField::encode(StackHandler::TRY_CATCH)
2560 } else { 2564 : StackHandler::KindField::encode(StackHandler::TRY_FINALLY);
2561 li(t0, Operand(StackHandler::TRY_FINALLY)); 2565 } else {
2562 } 2566 ASSERT(try_location == IN_JS_ENTRY);
2563 // Save the current handler as the next handler. 2567 state |= StackHandler::KindField::encode(StackHandler::ENTRY);
2564 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 2568 }
2565 lw(t1, MemOperand(t2));
2566 2569
2567 addiu(sp, sp, -StackHandlerConstants::kSize); 2570 // Set up the code object (t1) and the state (t2) for pushing.
2568 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset)); 2571 li(t1, Operand(CodeObject()));
2569 sw(fp, MemOperand(sp, StackHandlerConstants::kFPOffset)); 2572 li(t2, Operand(state));
2570 sw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
2571 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset));
2572 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
2573 2573
2574 // Link this handler as the new current one. 2574 // Push the frame pointer, context, state, and code object.
2575 sw(sp, MemOperand(t2)); 2575 if (try_location == IN_JAVASCRIPT) {
2576 MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit());
2577 } else {
2578 ASSERT_EQ(Smi::FromInt(0), 0);
2579 // The second zero_reg indicates no context.
2580 // The first zero_reg is the NULL frame pointer.
2581 // The operands are reversed to match the order of MultiPush/Pop.
2582 Push(zero_reg, zero_reg, t2, t1);
2583 }
2576 2584
2577 } else { 2585 // Link the current handler as the next handler.
2578 // Must preserve a0-a3, and s0 (argv). 2586 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
2579 ASSERT(try_location == IN_JS_ENTRY); 2587 lw(t1, MemOperand(t2));
2580 // The frame pointer does not point to a JS frame so we save NULL 2588 push(t1);
2581 // for fp. We expect the code throwing an exception to check fp 2589 // Set this new handler as the current one.
2582 // before dereferencing it to restore the context. 2590 sw(sp, MemOperand(t2));
2583 li(t0, Operand(StackHandler::ENTRY));
2584
2585 // Save the current handler as the next handler.
2586 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
2587 lw(t1, MemOperand(t2));
2588
2589 ASSERT(Smi::FromInt(0) == 0); // Used for no context.
2590
2591 addiu(sp, sp, -StackHandlerConstants::kSize);
2592 sw(ra, MemOperand(sp, StackHandlerConstants::kPCOffset));
2593 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kFPOffset));
2594 sw(zero_reg, MemOperand(sp, StackHandlerConstants::kContextOffset));
2595 sw(t0, MemOperand(sp, StackHandlerConstants::kStateOffset));
2596 sw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset));
2597
2598 // Link this handler as the new current one.
2599 sw(sp, MemOperand(t2));
2600 }
2601 } 2591 }
2602 2592
2603 2593
2604 void MacroAssembler::PopTryHandler() { 2594 void MacroAssembler::PopTryHandler() {
2605 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 2595 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
2606 pop(a1); 2596 pop(a1);
2607 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); 2597 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
2608 li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 2598 li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
2609 sw(a1, MemOperand(at)); 2599 sw(a1, MemOperand(at));
2610 } 2600 }
2611 2601
2612 2602
2603 void MacroAssembler::JumpToHandlerEntry() {
2604 // Compute the handler entry address and jump to it. The handler table is
2605 // a fixed array of (smi-tagged) code offsets.
2606 // v0 = exception, a1 = code object, a2 = state.
2607 lw(a3, FieldMemOperand(a1, Code::kHandlerTableOffset)); // Handler table.
2608 Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2609 srl(a2, a2, StackHandler::kKindWidth); // Handler index.
2610 sll(a2, a2, kPointerSizeLog2);
2611 Addu(a2, a3, a2);
2612 lw(a2, MemOperand(a2)); // Smi-tagged offset.
2613 Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start.
2614 sra(t9, a2, kSmiTagSize);
2615 Addu(t9, t9, a1);
2616 Jump(t9); // Jump.
2617 }
2618
2619
2613 void MacroAssembler::Throw(Register value) { 2620 void MacroAssembler::Throw(Register value) {
2614 // v0 is expected to hold the exception. 2621 // Adjust this code if not the case.
2622 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2623 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
2624 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
2625 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
2626 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
2627 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
2628
2629 // The exception is expected in v0.
2615 Move(v0, value); 2630 Move(v0, value);
2616 2631
2617 // Adjust this code if not the case. 2632 // Drop the stack pointer to the top of the top handler.
2618 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2619 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2620 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
2621 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
2622 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
2623 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
2624
2625 // Drop the sp to the top of the handler.
2626 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, 2633 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress,
2627 isolate()))); 2634 isolate())));
2628 lw(sp, MemOperand(a3)); 2635 lw(sp, MemOperand(a3));
2629 2636
2630 // Restore the next handler. 2637 // Restore the next handler.
2631 pop(a2); 2638 pop(a2);
2632 sw(a2, MemOperand(a3)); 2639 sw(a2, MemOperand(a3));
2633 2640
2634 // Restore context and frame pointer, discard state (a3). 2641 // Get the code object (a1) and state (a2). Restore the context and frame
2635 MultiPop(a3.bit() | cp.bit() | fp.bit()); 2642 // pointer.
2643 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
2636 2644
2637 // If the handler is a JS frame, restore the context to the frame. 2645 // If the handler is a JS frame, restore the context to the frame.
2638 // (a3 == ENTRY) == (fp == 0) == (cp == 0), so we could test any 2646 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
2639 // of them. 2647 // or cp.
2640 Label done; 2648 Label done;
2641 Branch(&done, eq, fp, Operand(zero_reg)); 2649 Branch(&done, eq, cp, Operand(zero_reg));
2642 sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2650 sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2643 bind(&done); 2651 bind(&done);
2644 2652
2645 #ifdef DEBUG 2653 JumpToHandlerEntry();
2646 // When emitting debug_code, set ra as return address for the jump.
2647 // 5 instructions: add: 1, pop: 2, jump: 2.
2648 const int kOffsetRaInstructions = 5;
2649 Label find_ra;
2650
2651 if (emit_debug_code()) {
2652 // Compute ra for the Jump(t9).
2653 const int kOffsetRaBytes = kOffsetRaInstructions * Assembler::kInstrSize;
2654
2655 // This branch-and-link sequence is needed to get the current PC on mips,
2656 // saved to the ra register. Then adjusted for instruction count.
2657 bal(&find_ra); // bal exposes branch-delay.
2658 nop(); // Branch delay slot nop.
2659 bind(&find_ra);
2660 addiu(ra, ra, kOffsetRaBytes);
2661 }
2662 #endif
2663
2664 pop(t9); // 2 instructions: lw, add sp.
2665 Jump(t9); // 2 instructions: jr, nop (in delay slot).
2666
2667 if (emit_debug_code()) {
2668 // Make sure that the expected number of instructions were generated.
2669 ASSERT_EQ(kOffsetRaInstructions,
2670 InstructionsGeneratedSince(&find_ra));
2671 }
2672 } 2654 }
2673 2655
2674 2656
2675 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, 2657 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
2676 Register value) { 2658 Register value) {
2677 // Adjust this code if not the case. 2659 // Adjust this code if not the case.
2678 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); 2660 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
2679 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 2661 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
2680 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize); 2662 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
2681 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize); 2663 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
2682 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize); 2664 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
2683 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); 2665 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
2684 2666
2685 // The exception is expected in v0. 2667 // The exception is expected in v0.
2686 if (type == OUT_OF_MEMORY) { 2668 if (type == OUT_OF_MEMORY) {
2687 // Set external caught exception to false. 2669 // Set external caught exception to false.
2688 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, 2670 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
2689 isolate()); 2671 isolate());
2690 li(a0, Operand(false, RelocInfo::NONE)); 2672 li(a0, Operand(false, RelocInfo::NONE));
2691 li(a2, Operand(external_caught)); 2673 li(a2, Operand(external_caught));
2692 sw(a0, MemOperand(a2)); 2674 sw(a0, MemOperand(a2));
2693 2675
2694 // Set pending exception and v0 to out of memory exception. 2676 // Set pending exception and v0 to out of memory exception.
2695 Failure* out_of_memory = Failure::OutOfMemoryException(); 2677 Failure* out_of_memory = Failure::OutOfMemoryException();
2696 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); 2678 li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
2697 li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 2679 li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
2698 isolate()))); 2680 isolate())));
2699 sw(v0, MemOperand(a2)); 2681 sw(v0, MemOperand(a2));
2700 } else if (!value.is(v0)) { 2682 } else if (!value.is(v0)) {
2701 mov(v0, value); 2683 mov(v0, value);
2702 } 2684 }
2703 2685
2704 // Drop the stack pointer to the top of the top stack handler. 2686 // Drop the stack pointer to the top of the top stack handler.
2705 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); 2687 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
2706 lw(sp, MemOperand(a3)); 2688 lw(sp, MemOperand(a3));
2707 2689
2708 // Unwind the handlers until the top ENTRY handler is found. 2690 // Unwind the handlers until the ENTRY handler is found.
2709 Label fetch_next, check_kind; 2691 Label fetch_next, check_kind;
2710 jmp(&check_kind); 2692 jmp(&check_kind);
2711 bind(&fetch_next); 2693 bind(&fetch_next);
2712 lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); 2694 lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
2713 2695
2714 bind(&check_kind); 2696 bind(&check_kind);
2697 STATIC_ASSERT(StackHandler::ENTRY == 0);
2715 lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset)); 2698 lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset));
2716 Branch(&fetch_next, ne, a2, Operand(StackHandler::ENTRY)); 2699 And(a2, a2, Operand(StackHandler::KindField::kMask));
2700 Branch(&fetch_next, ne, a2, Operand(zero_reg));
2717 2701
2718 // Set the top handler address to next handler past the top ENTRY handler. 2702 // Set the top handler address to next handler past the top ENTRY handler.
2719 pop(a2); 2703 pop(a2);
2720 sw(a2, MemOperand(a3)); 2704 sw(a2, MemOperand(a3));
2721 2705
2722 // Clear the context and frame pointer (0 was saved in the handler), and 2706 // Get the code object (a1) and state (a2). Clear the context and frame
2723 // discard the state (a2). 2707 // pointer (0 was saved in the handler).
2724 MultiPop(a2.bit() | cp.bit() | fp.bit()); 2708 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit());
2725 2709
2726 pop(t9); // 2 instructions: lw, add sp. 2710 JumpToHandlerEntry();
2727 Jump(t9); // 2 instructions: jr, nop (in delay slot).
2728 } 2711 }
2729 2712
2730 2713
2731 void MacroAssembler::AllocateInNewSpace(int object_size, 2714 void MacroAssembler::AllocateInNewSpace(int object_size,
2732 Register result, 2715 Register result,
2733 Register scratch1, 2716 Register scratch1,
2734 Register scratch2, 2717 Register scratch2,
2735 Label* gc_required, 2718 Label* gc_required,
2736 AllocationFlags flags) { 2719 AllocationFlags flags) {
2737 if (!FLAG_inline_new) { 2720 if (!FLAG_inline_new) {
(...skipping 2293 matching lines...) Expand 10 before | Expand all | Expand 10 after
5031 opcode == BGTZL); 5014 opcode == BGTZL);
5032 opcode = (cond == eq) ? BEQ : BNE; 5015 opcode = (cond == eq) ? BEQ : BNE;
5033 instr = (instr & ~kOpcodeMask) | opcode; 5016 instr = (instr & ~kOpcodeMask) | opcode;
5034 masm_.emit(instr); 5017 masm_.emit(instr);
5035 } 5018 }
5036 5019
5037 5020
5038 } } // namespace v8::internal 5021 } } // namespace v8::internal
5039 5022
5040 #endif // V8_TARGET_ARCH_MIPS 5023 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/macro-assembler-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698