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 |
772 void MacroAssembler::Throw(Register value) { | 777 void MacroAssembler::Throw(Register value) { |
773 // Adjust this code if not the case. | 778 // Adjust this code if not the case. |
774 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 779 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
775 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 780 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
776 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 781 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
777 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 782 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
778 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 783 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
779 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 784 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
780 // eax must hold the exception. | 785 |
786 // The exception is expected in eax. | |
781 if (!value.is(eax)) { | 787 if (!value.is(eax)) { |
782 mov(eax, value); | 788 mov(eax, value); |
783 } | 789 } |
790 // Drop the stack pointer to the top of the top handler. | |
791 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | |
792 mov(esp, Operand::StaticVariable(handler_address)); | |
793 // Restore the next handler. | |
794 pop(Operand::StaticVariable(handler_address)); | |
784 | 795 |
785 // Drop the sp to the top of the handler. | 796 // Remove the code object and state, compute the handler address in edi. |
786 ExternalReference handler_address(Isolate::kHandlerAddress, | 797 pop(edi); // Code object. |
787 isolate()); | 798 pop(edx); // Index and state. |
788 mov(esp, Operand::StaticVariable(handler_address)); | 799 // The handler table is a fixed array of (smi-tagged) code offsets. |
800 mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset)); | |
801 shr(edx, StackHandler::kKindWidth); | |
802 mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize)); | |
803 SmiUntag(edx); | |
804 lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize)); | |
789 | 805 |
790 // Restore next handler, context, and frame pointer; discard handler state. | 806 // Restore the context and frame pointer. |
791 pop(Operand::StaticVariable(handler_address)); | |
792 pop(esi); // Context. | 807 pop(esi); // Context. |
793 pop(ebp); // Frame pointer. | 808 pop(ebp); // Frame pointer. |
794 pop(edx); // State. | |
795 | 809 |
796 // If the handler is a JS frame, restore the context to the frame. | 810 // 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 | 811 // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either |
798 // of them. | 812 // ebp or esi. |
799 Label skip; | 813 Label skip; |
800 cmp(edx, Immediate(StackHandler::ENTRY)); | 814 test(esi, esi); |
801 j(equal, &skip, Label::kNear); | 815 j(zero, &skip, Label::kNear); |
802 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 816 mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); |
803 bind(&skip); | 817 bind(&skip); |
804 | 818 |
805 ret(0); | 819 // Jump to the handler code. |
820 jmp(edi); | |
806 } | 821 } |
807 | 822 |
808 | 823 |
809 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 824 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
810 Register value) { | 825 Register value) { |
811 // Adjust this code if not the case. | 826 // Adjust this code if not the case. |
812 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 827 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
813 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 828 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
814 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 829 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
815 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 830 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
816 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 831 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
817 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 832 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
818 | 833 |
819 // The exception is expected in eax. | 834 // The exception is expected in eax. |
820 if (type == OUT_OF_MEMORY) { | 835 if (type == OUT_OF_MEMORY) { |
821 // Set external caught exception to false. | 836 // Set external caught exception to false. |
822 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 837 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
823 isolate()); | 838 isolate()); |
824 mov(Operand::StaticVariable(external_caught), Immediate(false)); | 839 mov(Operand::StaticVariable(external_caught), Immediate(false)); |
825 | 840 |
826 // Set pending exception and eax to out of memory exception. | 841 // Set pending exception and eax to out of memory exception. |
827 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 842 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
828 isolate()); | 843 isolate()); |
829 mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | 844 mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); |
830 mov(Operand::StaticVariable(pending_exception), eax); | 845 mov(Operand::StaticVariable(pending_exception), eax); |
831 } else if (!value.is(eax)) { | 846 } else if (!value.is(eax)) { |
832 mov(eax, value); | 847 mov(eax, value); |
833 } | 848 } |
834 | 849 |
835 // Drop the stack pointer to the top of the top stack handler. | 850 // Drop the stack pointer to the top of the top stack handler. |
836 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 851 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
837 mov(esp, Operand::StaticVariable(handler_address)); | 852 mov(esp, Operand::StaticVariable(handler_address)); |
838 | 853 |
839 // Unwind the handlers until the top ENTRY handler is found. | 854 // Unwind the handlers until the top ENTRY handler is found. |
840 Label fetch_next, check_kind; | 855 Label fetch_next, check_kind; |
841 jmp(&check_kind, Label::kNear); | 856 jmp(&check_kind, Label::kNear); |
842 bind(&fetch_next); | 857 bind(&fetch_next); |
843 mov(esp, Operand(esp, StackHandlerConstants::kNextOffset)); | 858 mov(esp, Operand(esp, StackHandlerConstants::kNextOffset)); |
844 | 859 |
845 bind(&check_kind); | 860 bind(&check_kind); |
846 cmp(Operand(esp, StackHandlerConstants::kStateOffset), | 861 STATIC_ASSERT(StackHandler::ENTRY == 0); |
847 Immediate(StackHandler::ENTRY)); | 862 test(Operand(esp, StackHandlerConstants::kStateOffset), |
848 j(not_equal, &fetch_next); | 863 Immediate(StackHandler::KindField::kMask)); |
864 j(not_zero, &fetch_next); | |
849 | 865 |
850 // Set the top handler address to next handler past the top ENTRY handler. | 866 // Set the top handler address to next handler past the top ENTRY handler. |
851 pop(Operand::StaticVariable(handler_address)); | 867 pop(Operand::StaticVariable(handler_address)); |
852 | 868 |
853 // Clear the context and frame pointer (0 was saved in the handler), and | 869 // Remove the code object and state, compute the handler address in edi. |
854 // discard the state. | 870 pop(edi); // Code object. |
871 pop(edx); // Index and state. | |
872 // The handler table is a fixed array of (smi-tagged) code offsets. | |
873 mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset)); | |
874 shr(edx, StackHandler::kKindWidth); | |
875 mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize)); | |
876 SmiUntag(edx); | |
877 lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize)); | |
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 // Jump to the handler code. |
884 jmp(edi); | |
Vyacheslav Egorov (Chromium)
2011/11/10 19:01:04
Try to share code with Throw().
| |
860 } | 885 } |
861 | 886 |
862 | 887 |
863 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 888 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
864 Register scratch, | 889 Register scratch, |
865 Label* miss) { | 890 Label* miss) { |
866 Label same_contexts; | 891 Label same_contexts; |
867 | 892 |
868 ASSERT(!holder_reg.is(scratch)); | 893 ASSERT(!holder_reg.is(scratch)); |
869 | 894 |
(...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2638 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); | 2663 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); |
2639 Check(less_equal, "Live Bytes Count overflow chunk size"); | 2664 Check(less_equal, "Live Bytes Count overflow chunk size"); |
2640 } | 2665 } |
2641 | 2666 |
2642 bind(&done); | 2667 bind(&done); |
2643 } | 2668 } |
2644 | 2669 |
2645 } } // namespace v8::internal | 2670 } } // namespace v8::internal |
2646 | 2671 |
2647 #endif // V8_TARGET_ARCH_IA32 | 2672 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |