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

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

Issue 8462010: Add a level of indirection to exception handler addresses. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Incorporate review changes. 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/objects.h » ('j') | 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 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698