| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |