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