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

Side by Side Diff: src/builtins/x87/builtins-x87.cc

Issue 2351543002: X87: [Interpreter] Adds stackcheck in InterpreterPushArgsAndCall/Construct builtins. (Closed)
Patch Set: Created 4 years, 3 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X87 5 #if V8_TARGET_ARCH_X87
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/codegen.h" 8 #include "src/codegen.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 // Push function as argument and compile for baseline. 704 // Push function as argument and compile for baseline.
705 __ push(edi); 705 __ push(edi);
706 __ CallRuntime(Runtime::kCompileBaseline); 706 __ CallRuntime(Runtime::kCompileBaseline);
707 707
708 // Restore return value. 708 // Restore return value.
709 __ pop(eax); 709 __ pop(eax);
710 } 710 }
711 __ ret(0); 711 __ ret(0);
712 } 712 }
713 713
714 static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
715 Register scratch1, Register scratch2,
716 Label* stack_overflow,
717 bool include_receiver = false) {
718 // Check the stack for overflow. We are not trying to catch
719 // interruptions (e.g. debug break and preemption) here, so the "real stack
720 // limit" is checked.
721 ExternalReference real_stack_limit =
722 ExternalReference::address_of_real_stack_limit(masm->isolate());
723 __ mov(scratch1, Operand::StaticVariable(real_stack_limit));
724 // Make scratch2 the space we have left. The stack might already be overflowed
725 // here which will cause scratch2 to become negative.
726 __ mov(scratch2, esp);
727 __ sub(scratch2, scratch1);
728 // Make scratch1 the space we need for the array when it is unrolled onto the
729 // stack.
730 __ mov(scratch1, num_args);
731 if (include_receiver) {
732 __ add(scratch1, Immediate(1));
733 }
734 __ shl(scratch1, kPointerSizeLog2);
735 // Check if the arguments will overflow the stack.
736 __ cmp(scratch2, scratch1);
737 __ j(less_equal, stack_overflow); // Signed comparison.
738 }
739
714 static void Generate_InterpreterPushArgs(MacroAssembler* masm, 740 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
715 Register array_limit, 741 Register array_limit,
716 Register start_address) { 742 Register start_address) {
717 // ----------- S t a t e ------------- 743 // ----------- S t a t e -------------
718 // -- start_address : Pointer to the last argument in the args array. 744 // -- start_address : Pointer to the last argument in the args array.
719 // -- array_limit : Pointer to one before the first argument in the 745 // -- array_limit : Pointer to one before the first argument in the
720 // args array. 746 // args array.
721 // ----------------------------------- 747 // -----------------------------------
722 Label loop_header, loop_check; 748 Label loop_header, loop_check;
723 __ jmp(&loop_check); 749 __ jmp(&loop_check);
724 __ bind(&loop_header); 750 __ bind(&loop_header);
725 __ Push(Operand(start_address, 0)); 751 __ Push(Operand(start_address, 0));
726 __ sub(start_address, Immediate(kPointerSize)); 752 __ sub(start_address, Immediate(kPointerSize));
727 __ bind(&loop_check); 753 __ bind(&loop_check);
728 __ cmp(start_address, array_limit); 754 __ cmp(start_address, array_limit);
729 __ j(greater, &loop_header, Label::kNear); 755 __ j(greater, &loop_header, Label::kNear);
730 } 756 }
731 757
732 // static 758 // static
733 void Builtins::Generate_InterpreterPushArgsAndCallImpl( 759 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
734 MacroAssembler* masm, TailCallMode tail_call_mode, 760 MacroAssembler* masm, TailCallMode tail_call_mode,
735 CallableType function_type) { 761 CallableType function_type) {
736 // ----------- S t a t e ------------- 762 // ----------- S t a t e -------------
737 // -- eax : the number of arguments (not including the receiver) 763 // -- eax : the number of arguments (not including the receiver)
738 // -- ebx : the address of the first argument to be pushed. Subsequent 764 // -- ebx : the address of the first argument to be pushed. Subsequent
739 // arguments should be consecutive above this, in the same order as 765 // arguments should be consecutive above this, in the same order as
740 // they are to be pushed onto the stack. 766 // they are to be pushed onto the stack.
741 // -- edi : the target to call (can be any Object). 767 // -- edi : the target to call (can be any Object).
742 // ----------------------------------- 768 // -----------------------------------
769 Label stack_overflow;
770 // Compute the expected number of arguments.
771 __ mov(ecx, eax);
772 __ add(ecx, Immediate(1)); // Add one for receiver.
773
774 // Add a stack check before pushing the arguments. We need an extra register
775 // to perform a stack check. So push it onto the stack temporarily. This
776 // might cause stack overflow, but it will be detected by the check.
777 __ Push(edi);
778 Generate_StackOverflowCheck(masm, ecx, edx, edi, &stack_overflow);
779 __ Pop(edi);
743 780
744 // Pop return address to allow tail-call after pushing arguments. 781 // Pop return address to allow tail-call after pushing arguments.
745 __ Pop(edx); 782 __ Pop(edx);
746 783
747 // Find the address of the last argument. 784 // Find the address of the last argument.
748 __ mov(ecx, eax);
749 __ add(ecx, Immediate(1)); // Add one for receiver.
750 __ shl(ecx, kPointerSizeLog2); 785 __ shl(ecx, kPointerSizeLog2);
751 __ neg(ecx); 786 __ neg(ecx);
752 __ add(ecx, ebx); 787 __ add(ecx, ebx);
753
754 // TODO(mythria): Add a stack check before pushing the arguments.
755 Generate_InterpreterPushArgs(masm, ecx, ebx); 788 Generate_InterpreterPushArgs(masm, ecx, ebx);
756 789
757 // Call the target. 790 // Call the target.
758 __ Push(edx); // Re-push return address. 791 __ Push(edx); // Re-push return address.
759 792
760 if (function_type == CallableType::kJSFunction) { 793 if (function_type == CallableType::kJSFunction) {
761 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, 794 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny,
762 tail_call_mode), 795 tail_call_mode),
763 RelocInfo::CODE_TARGET); 796 RelocInfo::CODE_TARGET);
764 } else { 797 } else {
765 DCHECK_EQ(function_type, CallableType::kAny); 798 DCHECK_EQ(function_type, CallableType::kAny);
766 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 799 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
767 tail_call_mode), 800 tail_call_mode),
768 RelocInfo::CODE_TARGET); 801 RelocInfo::CODE_TARGET);
769 } 802 }
803
804 __ bind(&stack_overflow);
805 {
806 // Pop the temporary registers, so that return address is on top of stack.
807 __ Pop(edi);
808
809 __ TailCallRuntime(Runtime::kThrowStackOverflow);
810
811 // This should be unreachable.
812 __ int3();
813 }
770 } 814 }
771 815
772 namespace { 816 namespace {
773 817
774 // This function modified start_addr, and only reads the contents of num_args 818 // This function modified start_addr, and only reads the contents of num_args
775 // register. scratch1 and scratch2 are used as temporary registers. Their 819 // register. scratch1 and scratch2 are used as temporary registers. Their
776 // original values are restored after the use. 820 // original values are restored after the use.
777 void Generate_InterpreterPushArgsAndReturnAddress( 821 void Generate_InterpreterPushArgsAndReturnAddress(
778 MacroAssembler* masm, Register num_args, Register start_addr, 822 MacroAssembler* masm, Register num_args, Register start_addr,
779 Register scratch1, Register scratch2, bool receiver_in_args) { 823 Register scratch1, Register scratch2, bool receiver_in_args,
780 // Store scratch2, scratch1 onto the stack. We need to restore the original 824 int num_slots_above_ret_addr, Label* stack_overflow) {
781 // values 825 // We have to move return address and the temporary registers above it
782 // so store scratch2, scratch1 temporarily on stack. 826 // before we can copy arguments onto the stack. To achieve this:
783 __ Push(scratch2); 827 // Step 1: Increment the stack pointer by num_args + 1 (for receiver).
784 __ Push(scratch1); 828 // Step 2: Move the return address and values above it to the top of stack.
785 829 // Step 3: Copy the arguments into the correct locations.
786 // We have to pop return address and the two temporary registers before we
787 // can push arguments onto the stack. we do not have any free registers so
788 // update the stack and copy them into the correct places on the stack.
789 // current stack =====> required stack layout 830 // current stack =====> required stack layout
790 // | | | scratch1 | (2) <-- esp(1) 831 // | | | scratch1 | (2) <-- esp(1)
791 // | | | scratch2 | (3) 832 // | | | .... | (2)
792 // | | | return addr | (4) 833 // | | | scratch-n | (2)
793 // | | | arg N | (5) 834 // | | | return addr | (2)
835 // | | | arg N | (3)
794 // | scratch1 | <-- esp | .... | 836 // | scratch1 | <-- esp | .... |
795 // | scratch2 | | arg 0 | 837 // | .... | | arg 0 |
838 // | scratch-n | | arg 0 |
796 // | return addr | | receiver slot | 839 // | return addr | | receiver slot |
797 840
798 // First increment the stack pointer to the correct location. 841 // Check for stack overflow before we increment the stack pointer.
799 // we need additional slots for arguments and the receiver. 842 Generate_StackOverflowCheck(masm, num_args, scratch1, scratch2,
800 // Step 1 - compute the required increment to the stack. 843 stack_overflow, true);
801 __ mov(scratch1, num_args); 844
802 __ shl(scratch1, kPointerSizeLog2); 845 // Step 1 - Update the stack pointer. scratch1 already contains the required
803 __ add(scratch1, Immediate(kPointerSize)); 846 // increment to the stack. i.e. num_args + 1 stack slots. This is computed in
847 // the Generate_StackOverflowCheck.
804 848
805 #ifdef _MSC_VER 849 #ifdef _MSC_VER
806 // TODO(mythria): Move it to macro assembler. 850 // TODO(mythria): Move it to macro assembler.
807 // In windows, we cannot increment the stack size by more than one page 851 // In windows, we cannot increment the stack size by more than one page
808 // (mimimum page size is 4KB) without accessing at least one byte on the 852 // (mimimum page size is 4KB) without accessing at least one byte on the
809 // page. Check this: 853 // page. Check this:
810 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 854 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
811 const int page_size = 4 * 1024; 855 const int page_size = 4 * 1024;
812 Label check_offset, update_stack_pointer; 856 Label check_offset, update_stack_pointer;
813 __ bind(&check_offset); 857 __ bind(&check_offset);
814 __ cmp(scratch1, page_size); 858 __ cmp(scratch1, page_size);
815 __ j(less, &update_stack_pointer); 859 __ j(less, &update_stack_pointer);
816 __ sub(esp, Immediate(page_size)); 860 __ sub(esp, Immediate(page_size));
817 // Just to touch the page, before we increment further. 861 // Just to touch the page, before we increment further.
818 __ mov(Operand(esp, 0), Immediate(0)); 862 __ mov(Operand(esp, 0), Immediate(0));
819 __ sub(scratch1, Immediate(page_size)); 863 __ sub(scratch1, Immediate(page_size));
820 __ jmp(&check_offset); 864 __ jmp(&check_offset);
821 __ bind(&update_stack_pointer); 865 __ bind(&update_stack_pointer);
822 #endif 866 #endif
823 867
824 // TODO(mythria): Add a stack check before updating the stack pointer.
825
826 // Step 1 - Update the stack pointer.
827 __ sub(esp, scratch1); 868 __ sub(esp, scratch1);
828 869
829 // Step 2 move scratch1 to the correct location. Move scratch1 first otherwise 870 // Step 2 move return_address and slots above it to the correct locations.
830 // we may overwrite when num_args = 0 or 1, basically when the source and 871 // Move from top to bottom, otherwise we may overwrite when num_args = 0 or 1,
831 // destination overlap. We at least need one extra slot for receiver, 872 // basically when the source and destination overlap. We at least need one
832 // so no extra checks are required to avoid copy. 873 // extra slot for receiver, so no extra checks are required to avoid copy.
833 __ mov(scratch1, 874 for (int i = 0; i < num_slots_above_ret_addr + 1; i++) {
834 Operand(esp, num_args, times_pointer_size, 1 * kPointerSize)); 875 __ mov(scratch1,
835 __ mov(Operand(esp, 0), scratch1); 876 Operand(esp, num_args, times_pointer_size, (i + 1) * kPointerSize));
877 __ mov(Operand(esp, i * kPointerSize), scratch1);
878 }
836 879
837 // Step 3 move scratch2 to the correct location 880 // Step 3 copy arguments to correct locations.
838 __ mov(scratch1,
839 Operand(esp, num_args, times_pointer_size, 2 * kPointerSize));
840 __ mov(Operand(esp, 1 * kPointerSize), scratch1);
841
842 // Step 4 move return address to the correct location
843 __ mov(scratch1,
844 Operand(esp, num_args, times_pointer_size, 3 * kPointerSize));
845 __ mov(Operand(esp, 2 * kPointerSize), scratch1);
846
847 // Step 5 copy arguments to correct locations.
848 if (receiver_in_args) { 881 if (receiver_in_args) {
849 __ mov(scratch1, num_args); 882 __ mov(scratch1, num_args);
850 __ add(scratch1, Immediate(1)); 883 __ add(scratch1, Immediate(1));
851 } else { 884 } else {
852 // Slot meant for receiver contains return address. Reset it so that 885 // Slot meant for receiver contains return address. Reset it so that
853 // we will not incorrectly interpret return address as an object. 886 // we will not incorrectly interpret return address as an object.
854 __ mov(Operand(esp, num_args, times_pointer_size, 3 * kPointerSize), 887 __ mov(Operand(esp, num_args, times_pointer_size,
888 (num_slots_above_ret_addr + 1) * kPointerSize),
855 Immediate(0)); 889 Immediate(0));
856 __ mov(scratch1, num_args); 890 __ mov(scratch1, num_args);
857 } 891 }
858 892
859 Label loop_header, loop_check; 893 Label loop_header, loop_check;
860 __ jmp(&loop_check); 894 __ jmp(&loop_check);
861 __ bind(&loop_header); 895 __ bind(&loop_header);
862 __ mov(scratch2, Operand(start_addr, 0)); 896 __ mov(scratch2, Operand(start_addr, 0));
863 __ mov(Operand(esp, scratch1, times_pointer_size, 2 * kPointerSize), 897 __ mov(Operand(esp, scratch1, times_pointer_size,
898 num_slots_above_ret_addr * kPointerSize),
864 scratch2); 899 scratch2);
865 __ sub(start_addr, Immediate(kPointerSize)); 900 __ sub(start_addr, Immediate(kPointerSize));
866 __ sub(scratch1, Immediate(1)); 901 __ sub(scratch1, Immediate(1));
867 __ bind(&loop_check); 902 __ bind(&loop_check);
868 __ cmp(scratch1, Immediate(0)); 903 __ cmp(scratch1, Immediate(0));
869 __ j(greater, &loop_header, Label::kNear); 904 __ j(greater, &loop_header, Label::kNear);
870
871 // Restore scratch1 and scratch2.
872 __ Pop(scratch1);
873 __ Pop(scratch2);
874 } 905 }
875 906
876 } // end anonymous namespace 907 } // end anonymous namespace
877 908
878 // static 909 // static
879 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( 910 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
880 MacroAssembler* masm, CallableType construct_type) { 911 MacroAssembler* masm, CallableType construct_type) {
881 // ----------- S t a t e ------------- 912 // ----------- S t a t e -------------
882 // -- eax : the number of arguments (not including the receiver) 913 // -- eax : the number of arguments (not including the receiver)
883 // -- edx : the new target 914 // -- edx : the new target
884 // -- edi : the constructor 915 // -- edi : the constructor
885 // -- ebx : allocation site feedback (if available or undefined) 916 // -- ebx : allocation site feedback (if available or undefined)
886 // -- ecx : the address of the first argument to be pushed. Subsequent 917 // -- ecx : the address of the first argument to be pushed. Subsequent
887 // arguments should be consecutive above this, in the same order as 918 // arguments should be consecutive above this, in the same order as
888 // they are to be pushed onto the stack. 919 // they are to be pushed onto the stack.
889 // ----------------------------------- 920 // -----------------------------------
921 Label stack_overflow;
922 // We need two scratch registers. Push edi and edx onto stack.
923 __ Push(edi);
924 __ Push(edx);
890 925
891 // Push arguments and move return address to the top of stack. 926 // Push arguments and move return address to the top of stack.
892 // The eax register is readonly. The ecx register will be modified. The edx 927 // The eax register is readonly. The ecx register will be modified. The edx
893 // and edi registers will be modified but restored to their original values. 928 // and edi registers will be modified but restored to their original values.
894 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false); 929 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false,
930 2, &stack_overflow);
931
932 // Restore edi and edx
933 __ Pop(edx);
934 __ Pop(edi);
895 935
896 __ AssertUndefinedOrAllocationSite(ebx); 936 __ AssertUndefinedOrAllocationSite(ebx);
897 if (construct_type == CallableType::kJSFunction) { 937 if (construct_type == CallableType::kJSFunction) {
898 // Tail call to the function-specific construct stub (still in the caller 938 // Tail call to the function-specific construct stub (still in the caller
899 // context at this point). 939 // context at this point).
900 __ AssertFunction(edi); 940 __ AssertFunction(edi);
901 941
902 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 942 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
903 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 943 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
904 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 944 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
905 __ jmp(ecx); 945 __ jmp(ecx);
906 } else { 946 } else {
907 DCHECK_EQ(construct_type, CallableType::kAny); 947 DCHECK_EQ(construct_type, CallableType::kAny);
908 948
909 // Call the constructor with unmodified eax, edi, edx values. 949 // Call the constructor with unmodified eax, edi, edx values.
910 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 950 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
911 } 951 }
952
953 __ bind(&stack_overflow);
954 {
955 // Pop the temporary registers, so that return address is on top of stack.
956 __ Pop(edx);
957 __ Pop(edi);
958
959 __ TailCallRuntime(Runtime::kThrowStackOverflow);
960
961 // This should be unreachable.
962 __ int3();
963 }
912 } 964 }
913 965
914 // static 966 // static
915 void Builtins::Generate_InterpreterPushArgsAndConstructArray( 967 void Builtins::Generate_InterpreterPushArgsAndConstructArray(
916 MacroAssembler* masm) { 968 MacroAssembler* masm) {
917 // ----------- S t a t e ------------- 969 // ----------- S t a t e -------------
918 // -- eax : the number of arguments (not including the receiver) 970 // -- eax : the number of arguments (not including the receiver)
919 // -- edx : the target to call checked to be Array function. 971 // -- edx : the target to call checked to be Array function.
920 // -- ebx : the allocation site feedback 972 // -- ebx : the allocation site feedback
921 // -- ecx : the address of the first argument to be pushed. Subsequent 973 // -- ecx : the address of the first argument to be pushed. Subsequent
922 // arguments should be consecutive above this, in the same order as 974 // arguments should be consecutive above this, in the same order as
923 // they are to be pushed onto the stack. 975 // they are to be pushed onto the stack.
924 // ----------------------------------- 976 // -----------------------------------
977 Label stack_overflow;
978 // We need two scratch registers. Register edi is available, push edx onto
979 // stack.
980 __ Push(edx);
925 981
926 // Push arguments and move return address to the top of stack. 982 // Push arguments and move return address to the top of stack.
927 // The eax register is readonly. The ecx register will be modified. The edx 983 // The eax register is readonly. The ecx register will be modified. The edx
928 // and edi registers will be modified but restored to their original values. 984 // and edi registers will be modified but restored to their original values.
929 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true); 985 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true,
986 1, &stack_overflow);
987
988 // Restore edx.
989 __ Pop(edx);
930 990
931 // Array constructor expects constructor in edi. It is same as edx here. 991 // Array constructor expects constructor in edi. It is same as edx here.
932 __ Move(edi, edx); 992 __ Move(edi, edx);
933 993
934 ArrayConstructorStub stub(masm->isolate()); 994 ArrayConstructorStub stub(masm->isolate());
935 __ TailCallStub(&stub); 995 __ TailCallStub(&stub);
996
997 __ bind(&stack_overflow);
998 {
999 // Pop the temporary registers, so that return address is on top of stack.
1000 __ Pop(edx);
1001
1002 __ TailCallRuntime(Runtime::kThrowStackOverflow);
1003
1004 // This should be unreachable.
1005 __ int3();
1006 }
936 } 1007 }
937 1008
938 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 1009 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
939 // Set the return address to the correct point in the interpreter entry 1010 // Set the return address to the correct point in the interpreter entry
940 // trampoline. 1011 // trampoline.
941 Smi* interpreter_entry_return_pc_offset( 1012 Smi* interpreter_entry_return_pc_offset(
942 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 1013 masm->isolate()->heap()->interpreter_entry_return_pc_offset());
943 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); 1014 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
944 __ LoadHeapObject(ebx, 1015 __ LoadHeapObject(ebx,
945 masm->isolate()->builtins()->InterpreterEntryTrampoline()); 1016 masm->isolate()->builtins()->InterpreterEntryTrampoline());
(...skipping 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2102 __ bind(&drop_frame_and_ret); 2173 __ bind(&drop_frame_and_ret);
2103 { 2174 {
2104 // Drop all arguments including the receiver. 2175 // Drop all arguments including the receiver.
2105 __ PopReturnAddressTo(ecx); 2176 __ PopReturnAddressTo(ecx);
2106 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2177 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
2107 __ PushReturnAddressFrom(ecx); 2178 __ PushReturnAddressFrom(ecx);
2108 __ Ret(); 2179 __ Ret();
2109 } 2180 }
2110 } 2181 }
2111 2182
2112 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
2113 Label* stack_overflow) {
2114 // ----------- S t a t e -------------
2115 // -- eax : actual number of arguments
2116 // -- ebx : expected number of arguments
2117 // -- edx : new target (passed through to callee)
2118 // -----------------------------------
2119 // Check the stack for overflow. We are not trying to catch
2120 // interruptions (e.g. debug break and preemption) here, so the "real stack
2121 // limit" is checked.
2122 ExternalReference real_stack_limit =
2123 ExternalReference::address_of_real_stack_limit(masm->isolate());
2124 __ mov(edi, Operand::StaticVariable(real_stack_limit));
2125 // Make ecx the space we have left. The stack might already be overflowed
2126 // here which will cause ecx to become negative.
2127 __ mov(ecx, esp);
2128 __ sub(ecx, edi);
2129 // Make edi the space we need for the array when it is unrolled onto the
2130 // stack.
2131 __ mov(edi, ebx);
2132 __ shl(edi, kPointerSizeLog2);
2133 // Check if the arguments will overflow the stack.
2134 __ cmp(ecx, edi);
2135 __ j(less_equal, stack_overflow); // Signed comparison.
2136 }
2137
2138 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 2183 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
2139 __ push(ebp); 2184 __ push(ebp);
2140 __ mov(ebp, esp); 2185 __ mov(ebp, esp);
2141 2186
2142 // Store the arguments adaptor context sentinel. 2187 // Store the arguments adaptor context sentinel.
2143 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2188 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2144 2189
2145 // Push the function on the stack. 2190 // Push the function on the stack.
2146 __ push(edi); 2191 __ push(edi);
2147 2192
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
2863 2908
2864 Label enough, too_few; 2909 Label enough, too_few;
2865 __ cmp(eax, ebx); 2910 __ cmp(eax, ebx);
2866 __ j(less, &too_few); 2911 __ j(less, &too_few);
2867 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 2912 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
2868 __ j(equal, &dont_adapt_arguments); 2913 __ j(equal, &dont_adapt_arguments);
2869 2914
2870 { // Enough parameters: Actual >= expected. 2915 { // Enough parameters: Actual >= expected.
2871 __ bind(&enough); 2916 __ bind(&enough);
2872 EnterArgumentsAdaptorFrame(masm); 2917 EnterArgumentsAdaptorFrame(masm);
2873 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2918 // edi is used as a scratch register. It should be restored from the frame
2919 // when needed.
2920 Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow);
2874 2921
2875 // Copy receiver and all expected arguments. 2922 // Copy receiver and all expected arguments.
2876 const int offset = StandardFrameConstants::kCallerSPOffset; 2923 const int offset = StandardFrameConstants::kCallerSPOffset;
2877 __ lea(edi, Operand(ebp, eax, times_4, offset)); 2924 __ lea(edi, Operand(ebp, eax, times_4, offset));
2878 __ mov(eax, -1); // account for receiver 2925 __ mov(eax, -1); // account for receiver
2879 2926
2880 Label copy; 2927 Label copy;
2881 __ bind(&copy); 2928 __ bind(&copy);
2882 __ inc(eax); 2929 __ inc(eax);
2883 __ push(Operand(edi, 0)); 2930 __ push(Operand(edi, 0));
2884 __ sub(edi, Immediate(kPointerSize)); 2931 __ sub(edi, Immediate(kPointerSize));
2885 __ cmp(eax, ebx); 2932 __ cmp(eax, ebx);
2886 __ j(less, &copy); 2933 __ j(less, &copy);
2887 // eax now contains the expected number of arguments. 2934 // eax now contains the expected number of arguments.
2888 __ jmp(&invoke); 2935 __ jmp(&invoke);
2889 } 2936 }
2890 2937
2891 { // Too few parameters: Actual < expected. 2938 { // Too few parameters: Actual < expected.
2892 __ bind(&too_few); 2939 __ bind(&too_few);
2893
2894 EnterArgumentsAdaptorFrame(masm); 2940 EnterArgumentsAdaptorFrame(masm);
2895 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2941 // edi is used as a scratch register. It should be restored from the frame
2942 // when needed.
2943 Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow);
2896 2944
2897 // Remember expected arguments in ecx. 2945 // Remember expected arguments in ecx.
2898 __ mov(ecx, ebx); 2946 __ mov(ecx, ebx);
2899 2947
2900 // Copy receiver and all actual arguments. 2948 // Copy receiver and all actual arguments.
2901 const int offset = StandardFrameConstants::kCallerSPOffset; 2949 const int offset = StandardFrameConstants::kCallerSPOffset;
2902 __ lea(edi, Operand(ebp, eax, times_4, offset)); 2950 __ lea(edi, Operand(ebp, eax, times_4, offset));
2903 // ebx = expected - actual. 2951 // ebx = expected - actual.
2904 __ sub(ebx, eax); 2952 __ sub(ebx, eax);
2905 // eax = -actual - 1 2953 // eax = -actual - 1
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 3168
3121 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3169 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
3122 Generate_OnStackReplacementHelper(masm, true); 3170 Generate_OnStackReplacementHelper(masm, true);
3123 } 3171 }
3124 3172
3125 #undef __ 3173 #undef __
3126 } // namespace internal 3174 } // namespace internal
3127 } // namespace v8 3175 } // namespace v8
3128 3176
3129 #endif // V8_TARGET_ARCH_X87 3177 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698