| 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 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 | 718 |
| 719 void MacroAssembler::LeaveApiExitFrame() { | 719 void MacroAssembler::LeaveApiExitFrame() { |
| 720 mov(esp, ebp); | 720 mov(esp, ebp); |
| 721 pop(ebp); | 721 pop(ebp); |
| 722 | 722 |
| 723 LeaveExitFrameEpilogue(); | 723 LeaveExitFrameEpilogue(); |
| 724 } | 724 } |
| 725 | 725 |
| 726 | 726 |
| 727 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 727 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| 728 HandlerType type) { | 728 HandlerType type, |
| 729 int handler_index) { |
| 729 // Adjust this code if not the case. | 730 // Adjust this code if not the case. |
| 730 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 731 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 731 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 732 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 732 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 733 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 733 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 734 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 734 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 735 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 735 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 736 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 736 // The pc (return address) is already on TOS. | 737 |
| 738 // We will build up the handler from the bottom by pushing on the stack. |
| 739 // First compute the state and push the frame pointer and context. |
| 740 unsigned state = StackHandler::OffsetField::encode(handler_index); |
| 737 if (try_location == IN_JAVASCRIPT) { | 741 if (try_location == IN_JAVASCRIPT) { |
| 738 if (type == TRY_CATCH_HANDLER) { | |
| 739 push(Immediate(StackHandler::TRY_CATCH)); | |
| 740 } else { | |
| 741 push(Immediate(StackHandler::TRY_FINALLY)); | |
| 742 } | |
| 743 push(ebp); | 742 push(ebp); |
| 744 push(esi); | 743 push(esi); |
| 744 state |= (type == TRY_CATCH_HANDLER) |
| 745 ? StackHandler::KindField::encode(StackHandler::TRY_CATCH) |
| 746 : StackHandler::KindField::encode(StackHandler::TRY_FINALLY); |
| 745 } else { | 747 } else { |
| 746 ASSERT(try_location == IN_JS_ENTRY); | 748 ASSERT(try_location == IN_JS_ENTRY); |
| 747 // The frame pointer does not point to a JS frame so we save NULL | 749 // The frame pointer does not point to a JS frame so we save NULL for |
| 748 // for ebp. We expect the code throwing an exception to check ebp | 750 // ebp. We expect the code throwing an exception to check ebp before |
| 749 // before dereferencing it to restore the context. | 751 // dereferencing it to restore the context. |
| 750 push(Immediate(StackHandler::ENTRY)); | |
| 751 push(Immediate(0)); // NULL frame pointer. | 752 push(Immediate(0)); // NULL frame pointer. |
| 752 push(Immediate(Smi::FromInt(0))); // No context. | 753 push(Immediate(Smi::FromInt(0))); // No context. |
| 754 state |= StackHandler::KindField::encode(StackHandler::ENTRY); |
| 753 } | 755 } |
| 754 // Save the current handler as the next handler. | 756 |
| 755 push(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress, | 757 // Push the state and the code object. |
| 756 isolate()))); | 758 push(Immediate(state)); |
| 757 // Link this handler as the new current one. | 759 push(CodeObject()); |
| 758 mov(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress, | 760 |
| 759 isolate())), | 761 // Link the current handler as the next handler. |
| 760 esp); | 762 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 763 push(Operand::StaticVariable(handler_address)); |
| 764 // Set this new handler as the current one. |
| 765 mov(Operand::StaticVariable(handler_address), esp); |
| 761 } | 766 } |
| 762 | 767 |
| 763 | 768 |
| 764 void MacroAssembler::PopTryHandler() { | 769 void MacroAssembler::PopTryHandler() { |
| 765 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 770 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 766 pop(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress, | 771 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 767 isolate()))); | 772 pop(Operand::StaticVariable(handler_address)); |
| 768 add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 773 add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| 769 } | 774 } |
| 770 | 775 |
| 771 | 776 |
| 777 void MacroAssembler::JumpToHandlerEntry() { |
| 778 // Compute the handler entry address and jump to it. The handler table is |
| 779 // a fixed array of (smi-tagged) code offsets. |
| 780 // eax = exception, edi = code object, edx = state. |
| 781 mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset)); |
| 782 shr(edx, StackHandler::kKindWidth); |
| 783 mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize)); |
| 784 SmiUntag(edx); |
| 785 lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize)); |
| 786 jmp(edi); |
| 787 } |
| 788 |
| 789 |
| 772 void MacroAssembler::Throw(Register value) { | 790 void MacroAssembler::Throw(Register value) { |
| 773 // Adjust this code if not the case. | 791 // Adjust this code if not the case. |
| 774 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 792 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 775 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 793 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 776 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 794 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 777 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 795 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 778 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 796 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 779 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 797 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 780 // eax must hold the exception. | 798 |
| 799 // The exception is expected in eax. |
| 781 if (!value.is(eax)) { | 800 if (!value.is(eax)) { |
| 782 mov(eax, value); | 801 mov(eax, value); |
| 783 } | 802 } |
| 803 // Drop the stack pointer to the top of the top handler. |
| 804 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 805 mov(esp, Operand::StaticVariable(handler_address)); |
| 806 // Restore the next handler. |
| 807 pop(Operand::StaticVariable(handler_address)); |
| 784 | 808 |
| 785 // Drop the sp to the top of the handler. | 809 // Remove the code object and state, compute the handler address in edi. |
| 786 ExternalReference handler_address(Isolate::kHandlerAddress, | 810 pop(edi); // Code object. |
| 787 isolate()); | 811 pop(edx); // Index and state. |
| 788 mov(esp, Operand::StaticVariable(handler_address)); | |
| 789 | 812 |
| 790 // Restore next handler, context, and frame pointer; discard handler state. | 813 // Restore the context and frame pointer. |
| 791 pop(Operand::StaticVariable(handler_address)); | |
| 792 pop(esi); // Context. | 814 pop(esi); // Context. |
| 793 pop(ebp); // Frame pointer. | 815 pop(ebp); // Frame pointer. |
| 794 pop(edx); // State. | |
| 795 | 816 |
| 796 // If the handler is a JS frame, restore the context to the frame. | 817 // If the handler is a JS frame, restore the context to the frame. |
| 797 // (edx == ENTRY) == (ebp == 0) == (esi == 0), so we could test any | 818 // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either |
| 798 // of them. | 819 // ebp or esi. |
| 799 Label skip; | 820 Label skip; |
| 800 cmp(edx, Immediate(StackHandler::ENTRY)); | 821 test(esi, esi); |
| 801 j(equal, &skip, Label::kNear); | 822 j(zero, &skip, Label::kNear); |
| 802 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 823 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); |
| 803 bind(&skip); | 824 bind(&skip); |
| 804 | 825 |
| 805 ret(0); | 826 JumpToHandlerEntry(); |
| 806 } | 827 } |
| 807 | 828 |
| 808 | 829 |
| 809 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 830 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 810 Register value) { | 831 Register value) { |
| 811 // Adjust this code if not the case. | 832 // Adjust this code if not the case. |
| 812 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 833 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 813 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 834 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 814 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 835 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 815 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 836 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 816 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 837 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 817 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 838 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 818 | 839 |
| 819 // The exception is expected in eax. | 840 // The exception is expected in eax. |
| 820 if (type == OUT_OF_MEMORY) { | 841 if (type == OUT_OF_MEMORY) { |
| 821 // Set external caught exception to false. | 842 // Set external caught exception to false. |
| 822 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 843 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
| 823 isolate()); | 844 isolate()); |
| 824 mov(Operand::StaticVariable(external_caught), Immediate(false)); | 845 mov(Operand::StaticVariable(external_caught), Immediate(false)); |
| 825 | 846 |
| 826 // Set pending exception and eax to out of memory exception. | 847 // Set pending exception and eax to out of memory exception. |
| 827 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 848 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
| 828 isolate()); | 849 isolate()); |
| 829 mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | 850 mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); |
| 830 mov(Operand::StaticVariable(pending_exception), eax); | 851 mov(Operand::StaticVariable(pending_exception), eax); |
| 831 } else if (!value.is(eax)) { | 852 } else if (!value.is(eax)) { |
| 832 mov(eax, value); | 853 mov(eax, value); |
| 833 } | 854 } |
| 834 | 855 |
| 835 // Drop the stack pointer to the top of the top stack handler. | 856 // Drop the stack pointer to the top of the top stack handler. |
| 836 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 857 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 837 mov(esp, Operand::StaticVariable(handler_address)); | 858 mov(esp, Operand::StaticVariable(handler_address)); |
| 838 | 859 |
| 839 // Unwind the handlers until the top ENTRY handler is found. | 860 // Unwind the handlers until the top ENTRY handler is found. |
| 840 Label fetch_next, check_kind; | 861 Label fetch_next, check_kind; |
| 841 jmp(&check_kind, Label::kNear); | 862 jmp(&check_kind, Label::kNear); |
| 842 bind(&fetch_next); | 863 bind(&fetch_next); |
| 843 mov(esp, Operand(esp, StackHandlerConstants::kNextOffset)); | 864 mov(esp, Operand(esp, StackHandlerConstants::kNextOffset)); |
| 844 | 865 |
| 845 bind(&check_kind); | 866 bind(&check_kind); |
| 846 cmp(Operand(esp, StackHandlerConstants::kStateOffset), | 867 STATIC_ASSERT(StackHandler::ENTRY == 0); |
| 847 Immediate(StackHandler::ENTRY)); | 868 test(Operand(esp, StackHandlerConstants::kStateOffset), |
| 848 j(not_equal, &fetch_next); | 869 Immediate(StackHandler::KindField::kMask)); |
| 870 j(not_zero, &fetch_next); |
| 849 | 871 |
| 850 // Set the top handler address to next handler past the top ENTRY handler. | 872 // Set the top handler address to next handler past the top ENTRY handler. |
| 851 pop(Operand::StaticVariable(handler_address)); | 873 pop(Operand::StaticVariable(handler_address)); |
| 852 | 874 |
| 853 // Clear the context and frame pointer (0 was saved in the handler), and | 875 // Remove the code object and state, compute the handler address in edi. |
| 854 // discard the state. | 876 pop(edi); // Code object. |
| 877 pop(edx); // Index and state. |
| 878 |
| 879 // Clear the context pointer and frame pointer (0 was saved in the handler). |
| 855 pop(esi); | 880 pop(esi); |
| 856 pop(ebp); | 881 pop(ebp); |
| 857 pop(edx); // State. | |
| 858 | 882 |
| 859 ret(0); | 883 JumpToHandlerEntry(); |
| 860 } | 884 } |
| 861 | 885 |
| 862 | 886 |
| 863 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 887 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 864 Register scratch, | 888 Register scratch, |
| 865 Label* miss) { | 889 Label* miss) { |
| 866 Label same_contexts; | 890 Label same_contexts; |
| 867 | 891 |
| 868 ASSERT(!holder_reg.is(scratch)); | 892 ASSERT(!holder_reg.is(scratch)); |
| 869 | 893 |
| (...skipping 1766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2636 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); | 2660 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); |
| 2637 Check(less_equal, "Live Bytes Count overflow chunk size"); | 2661 Check(less_equal, "Live Bytes Count overflow chunk size"); |
| 2638 } | 2662 } |
| 2639 | 2663 |
| 2640 bind(&done); | 2664 bind(&done); |
| 2641 } | 2665 } |
| 2642 | 2666 |
| 2643 } } // namespace v8::internal | 2667 } } // namespace v8::internal |
| 2644 | 2668 |
| 2645 #endif // V8_TARGET_ARCH_IA32 | 2669 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |