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

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

Issue 2335513004: [Interpreter] Adds stackcheck in InterpreterPushArgsAndCall/Construct builtins. (Closed)
Patch Set: Addressed comments from Ross. 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 | « src/builtins/arm64/builtins-arm64.cc ('k') | src/builtins/mips/builtins-mips.cc » ('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 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_IA32 5 #if V8_TARGET_ARCH_IA32
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 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 // Push function as argument and compile for baseline. 696 // Push function as argument and compile for baseline.
697 __ push(edi); 697 __ push(edi);
698 __ CallRuntime(Runtime::kCompileBaseline); 698 __ CallRuntime(Runtime::kCompileBaseline);
699 699
700 // Restore return value. 700 // Restore return value.
701 __ pop(eax); 701 __ pop(eax);
702 } 702 }
703 __ ret(0); 703 __ ret(0);
704 } 704 }
705 705
706 static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
707 Register scratch1, Register scratch2,
708 Label* stack_overflow,
709 bool include_receiver = false) {
710 // Check the stack for overflow. We are not trying to catch
711 // interruptions (e.g. debug break and preemption) here, so the "real stack
712 // limit" is checked.
713 ExternalReference real_stack_limit =
714 ExternalReference::address_of_real_stack_limit(masm->isolate());
715 __ mov(scratch1, Operand::StaticVariable(real_stack_limit));
716 // Make scratch2 the space we have left. The stack might already be overflowed
717 // here which will cause scratch2 to become negative.
718 __ mov(scratch2, esp);
719 __ sub(scratch2, scratch1);
720 // Make scratch1 the space we need for the array when it is unrolled onto the
721 // stack.
722 __ mov(scratch1, num_args);
723 if (include_receiver) {
724 __ add(scratch1, Immediate(1));
725 }
726 __ shl(scratch1, kPointerSizeLog2);
727 // Check if the arguments will overflow the stack.
728 __ cmp(scratch2, scratch1);
729 __ j(less_equal, stack_overflow); // Signed comparison.
730 }
731
706 static void Generate_InterpreterPushArgs(MacroAssembler* masm, 732 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
707 Register array_limit, 733 Register array_limit,
708 Register start_address) { 734 Register start_address) {
709 // ----------- S t a t e ------------- 735 // ----------- S t a t e -------------
710 // -- start_address : Pointer to the last argument in the args array. 736 // -- start_address : Pointer to the last argument in the args array.
711 // -- array_limit : Pointer to one before the first argument in the 737 // -- array_limit : Pointer to one before the first argument in the
712 // args array. 738 // args array.
713 // ----------------------------------- 739 // -----------------------------------
714 Label loop_header, loop_check; 740 Label loop_header, loop_check;
715 __ jmp(&loop_check); 741 __ jmp(&loop_check);
716 __ bind(&loop_header); 742 __ bind(&loop_header);
717 __ Push(Operand(start_address, 0)); 743 __ Push(Operand(start_address, 0));
718 __ sub(start_address, Immediate(kPointerSize)); 744 __ sub(start_address, Immediate(kPointerSize));
719 __ bind(&loop_check); 745 __ bind(&loop_check);
720 __ cmp(start_address, array_limit); 746 __ cmp(start_address, array_limit);
721 __ j(greater, &loop_header, Label::kNear); 747 __ j(greater, &loop_header, Label::kNear);
722 } 748 }
723 749
724 // static 750 // static
725 void Builtins::Generate_InterpreterPushArgsAndCallImpl( 751 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
726 MacroAssembler* masm, TailCallMode tail_call_mode, 752 MacroAssembler* masm, TailCallMode tail_call_mode,
727 CallableType function_type) { 753 CallableType function_type) {
728 // ----------- S t a t e ------------- 754 // ----------- S t a t e -------------
729 // -- eax : the number of arguments (not including the receiver) 755 // -- eax : the number of arguments (not including the receiver)
730 // -- ebx : the address of the first argument to be pushed. Subsequent 756 // -- ebx : the address of the first argument to be pushed. Subsequent
731 // arguments should be consecutive above this, in the same order as 757 // arguments should be consecutive above this, in the same order as
732 // they are to be pushed onto the stack. 758 // they are to be pushed onto the stack.
733 // -- edi : the target to call (can be any Object). 759 // -- edi : the target to call (can be any Object).
734 // ----------------------------------- 760 // -----------------------------------
761 Label stack_overflow;
762 // Compute the expected number of arguments.
763 __ mov(ecx, eax);
764 __ add(ecx, Immediate(1)); // Add one for receiver.
765
766 // Add a stack check before pushing the arguments. We need an extra register
767 // to perform a stack check. So push it onto the stack temporarily. This
768 // might cause stack overflow, but it will be detected by the check.
769 __ Push(edi);
770 Generate_StackOverflowCheck(masm, ecx, edx, edi, &stack_overflow);
771 __ Pop(edi);
735 772
736 // Pop return address to allow tail-call after pushing arguments. 773 // Pop return address to allow tail-call after pushing arguments.
737 __ Pop(edx); 774 __ Pop(edx);
738 775
739 // Find the address of the last argument. 776 // Find the address of the last argument.
740 __ mov(ecx, eax);
741 __ add(ecx, Immediate(1)); // Add one for receiver.
742 __ shl(ecx, kPointerSizeLog2); 777 __ shl(ecx, kPointerSizeLog2);
743 __ neg(ecx); 778 __ neg(ecx);
744 __ add(ecx, ebx); 779 __ add(ecx, ebx);
745
746 // TODO(mythria): Add a stack check before pushing the arguments.
747 Generate_InterpreterPushArgs(masm, ecx, ebx); 780 Generate_InterpreterPushArgs(masm, ecx, ebx);
748 781
749 // Call the target. 782 // Call the target.
750 __ Push(edx); // Re-push return address. 783 __ Push(edx); // Re-push return address.
751 784
752 if (function_type == CallableType::kJSFunction) { 785 if (function_type == CallableType::kJSFunction) {
753 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, 786 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny,
754 tail_call_mode), 787 tail_call_mode),
755 RelocInfo::CODE_TARGET); 788 RelocInfo::CODE_TARGET);
756 } else { 789 } else {
757 DCHECK_EQ(function_type, CallableType::kAny); 790 DCHECK_EQ(function_type, CallableType::kAny);
758 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 791 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
759 tail_call_mode), 792 tail_call_mode),
760 RelocInfo::CODE_TARGET); 793 RelocInfo::CODE_TARGET);
761 } 794 }
795
796 __ bind(&stack_overflow);
797 {
798 // Pop the temporary registers, so that return address is on top of stack.
799 __ Pop(edi);
800
801 __ TailCallRuntime(Runtime::kThrowStackOverflow);
802
803 // This should be unreachable.
804 __ int3();
805 }
762 } 806 }
763 807
764 namespace { 808 namespace {
765 809
766 // This function modified start_addr, and only reads the contents of num_args 810 // This function modified start_addr, and only reads the contents of num_args
767 // register. scratch1 and scratch2 are used as temporary registers. Their 811 // register. scratch1 and scratch2 are used as temporary registers. Their
768 // original values are restored after the use. 812 // original values are restored after the use.
769 void Generate_InterpreterPushArgsAndReturnAddress( 813 void Generate_InterpreterPushArgsAndReturnAddress(
770 MacroAssembler* masm, Register num_args, Register start_addr, 814 MacroAssembler* masm, Register num_args, Register start_addr,
771 Register scratch1, Register scratch2, bool receiver_in_args) { 815 Register scratch1, Register scratch2, bool receiver_in_args,
772 // Store scratch2, scratch1 onto the stack. We need to restore the original 816 int num_slots_above_ret_addr, Label* stack_overflow) {
773 // values 817 // We have to move return address and the temporary registers above it
774 // so store scratch2, scratch1 temporarily on stack. 818 // before we can copy arguments onto the stack. To achieve this:
775 __ Push(scratch2); 819 // Step 1: Increment the stack pointer by num_args + 1 (for receiver).
776 __ Push(scratch1); 820 // Step 2: Move the return address and values above it to the top of stack.
777 821 // Step 3: Copy the arguments into the correct locations.
778 // We have to pop return address and the two temporary registers before we
779 // can push arguments onto the stack. we do not have any free registers so
780 // update the stack and copy them into the correct places on the stack.
781 // current stack =====> required stack layout 822 // current stack =====> required stack layout
782 // | | | scratch1 | (2) <-- esp(1) 823 // | | | scratch1 | (2) <-- esp(1)
783 // | | | scratch2 | (3) 824 // | | | .... | (2)
784 // | | | return addr | (4) 825 // | | | scratch-n | (2)
785 // | | | arg N | (5) 826 // | | | return addr | (2)
827 // | | | arg N | (3)
786 // | scratch1 | <-- esp | .... | 828 // | scratch1 | <-- esp | .... |
787 // | scratch2 | | arg 0 | 829 // | .... | | arg 0 |
830 // | scratch-n | | arg 0 |
788 // | return addr | | receiver slot | 831 // | return addr | | receiver slot |
789 832
790 // First increment the stack pointer to the correct location. 833 // Check for stack overflow before we increment the stack pointer.
791 // we need additional slots for arguments and the receiver. 834 Generate_StackOverflowCheck(masm, num_args, scratch1, scratch2,
792 // Step 1 - compute the required increment to the stack. 835 stack_overflow, true);
793 __ mov(scratch1, num_args); 836
794 __ shl(scratch1, kPointerSizeLog2); 837 // Step 1 - Update the stack pointer. scratch1 already contains the required
795 __ add(scratch1, Immediate(kPointerSize)); 838 // increment to the stack. i.e. num_args + 1 stack slots. This is computed in
839 // the Generate_StackOverflowCheck.
796 840
797 #ifdef _MSC_VER 841 #ifdef _MSC_VER
798 // TODO(mythria): Move it to macro assembler. 842 // TODO(mythria): Move it to macro assembler.
799 // In windows, we cannot increment the stack size by more than one page 843 // In windows, we cannot increment the stack size by more than one page
800 // (mimimum page size is 4KB) without accessing at least one byte on the 844 // (mimimum page size is 4KB) without accessing at least one byte on the
801 // page. Check this: 845 // page. Check this:
802 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 846 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
803 const int page_size = 4 * 1024; 847 const int page_size = 4 * 1024;
804 Label check_offset, update_stack_pointer; 848 Label check_offset, update_stack_pointer;
805 __ bind(&check_offset); 849 __ bind(&check_offset);
806 __ cmp(scratch1, page_size); 850 __ cmp(scratch1, page_size);
807 __ j(less, &update_stack_pointer); 851 __ j(less, &update_stack_pointer);
808 __ sub(esp, Immediate(page_size)); 852 __ sub(esp, Immediate(page_size));
809 // Just to touch the page, before we increment further. 853 // Just to touch the page, before we increment further.
810 __ mov(Operand(esp, 0), Immediate(0)); 854 __ mov(Operand(esp, 0), Immediate(0));
811 __ sub(scratch1, Immediate(page_size)); 855 __ sub(scratch1, Immediate(page_size));
812 __ jmp(&check_offset); 856 __ jmp(&check_offset);
813 __ bind(&update_stack_pointer); 857 __ bind(&update_stack_pointer);
814 #endif 858 #endif
815 859
816 // TODO(mythria): Add a stack check before updating the stack pointer.
817
818 // Step 1 - Update the stack pointer.
819 __ sub(esp, scratch1); 860 __ sub(esp, scratch1);
820 861
821 // Step 2 move scratch1 to the correct location. Move scratch1 first otherwise 862 // Step 2 move return_address and slots above it to the correct locations.
822 // we may overwrite when num_args = 0 or 1, basically when the source and 863 // Move from top to bottom, otherwise we may overwrite when num_args = 0 or 1,
823 // destination overlap. We at least need one extra slot for receiver, 864 // basically when the source and destination overlap. We at least need one
824 // so no extra checks are required to avoid copy. 865 // extra slot for receiver, so no extra checks are required to avoid copy.
825 __ mov(scratch1, 866 for (int i = 0; i < num_slots_above_ret_addr + 1; i++) {
826 Operand(esp, num_args, times_pointer_size, 1 * kPointerSize)); 867 __ mov(scratch1,
827 __ mov(Operand(esp, 0), scratch1); 868 Operand(esp, num_args, times_pointer_size, (i + 1) * kPointerSize));
869 __ mov(Operand(esp, i * kPointerSize), scratch1);
870 }
828 871
829 // Step 3 move scratch2 to the correct location 872 // Step 3 copy arguments to correct locations.
830 __ mov(scratch1,
831 Operand(esp, num_args, times_pointer_size, 2 * kPointerSize));
832 __ mov(Operand(esp, 1 * kPointerSize), scratch1);
833
834 // Step 4 move return address to the correct location
835 __ mov(scratch1,
836 Operand(esp, num_args, times_pointer_size, 3 * kPointerSize));
837 __ mov(Operand(esp, 2 * kPointerSize), scratch1);
838
839 // Step 5 copy arguments to correct locations.
840 if (receiver_in_args) { 873 if (receiver_in_args) {
841 __ mov(scratch1, num_args); 874 __ mov(scratch1, num_args);
842 __ add(scratch1, Immediate(1)); 875 __ add(scratch1, Immediate(1));
843 } else { 876 } else {
844 // Slot meant for receiver contains return address. Reset it so that 877 // Slot meant for receiver contains return address. Reset it so that
845 // we will not incorrectly interpret return address as an object. 878 // we will not incorrectly interpret return address as an object.
846 __ mov(Operand(esp, num_args, times_pointer_size, 3 * kPointerSize), 879 __ mov(Operand(esp, num_args, times_pointer_size,
880 (num_slots_above_ret_addr + 1) * kPointerSize),
847 Immediate(0)); 881 Immediate(0));
848 __ mov(scratch1, num_args); 882 __ mov(scratch1, num_args);
849 } 883 }
850 884
851 Label loop_header, loop_check; 885 Label loop_header, loop_check;
852 __ jmp(&loop_check); 886 __ jmp(&loop_check);
853 __ bind(&loop_header); 887 __ bind(&loop_header);
854 __ mov(scratch2, Operand(start_addr, 0)); 888 __ mov(scratch2, Operand(start_addr, 0));
855 __ mov(Operand(esp, scratch1, times_pointer_size, 2 * kPointerSize), 889 __ mov(Operand(esp, scratch1, times_pointer_size,
890 num_slots_above_ret_addr * kPointerSize),
856 scratch2); 891 scratch2);
857 __ sub(start_addr, Immediate(kPointerSize)); 892 __ sub(start_addr, Immediate(kPointerSize));
858 __ sub(scratch1, Immediate(1)); 893 __ sub(scratch1, Immediate(1));
859 __ bind(&loop_check); 894 __ bind(&loop_check);
860 __ cmp(scratch1, Immediate(0)); 895 __ cmp(scratch1, Immediate(0));
861 __ j(greater, &loop_header, Label::kNear); 896 __ j(greater, &loop_header, Label::kNear);
862
863 // Restore scratch1 and scratch2.
864 __ Pop(scratch1);
865 __ Pop(scratch2);
866 } 897 }
867 898
868 } // end anonymous namespace 899 } // end anonymous namespace
869 900
870 // static 901 // static
871 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( 902 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
872 MacroAssembler* masm, CallableType construct_type) { 903 MacroAssembler* masm, CallableType construct_type) {
873 // ----------- S t a t e ------------- 904 // ----------- S t a t e -------------
874 // -- eax : the number of arguments (not including the receiver) 905 // -- eax : the number of arguments (not including the receiver)
875 // -- edx : the new target 906 // -- edx : the new target
876 // -- edi : the constructor 907 // -- edi : the constructor
877 // -- ebx : allocation site feedback (if available or undefined) 908 // -- ebx : allocation site feedback (if available or undefined)
878 // -- ecx : the address of the first argument to be pushed. Subsequent 909 // -- ecx : the address of the first argument to be pushed. Subsequent
879 // arguments should be consecutive above this, in the same order as 910 // arguments should be consecutive above this, in the same order as
880 // they are to be pushed onto the stack. 911 // they are to be pushed onto the stack.
881 // ----------------------------------- 912 // -----------------------------------
913 Label stack_overflow;
914 // We need two scratch registers. Push edi and edx onto stack.
915 __ Push(edi);
916 __ Push(edx);
882 917
883 // Push arguments and move return address to the top of stack. 918 // Push arguments and move return address to the top of stack.
884 // The eax register is readonly. The ecx register will be modified. The edx 919 // The eax register is readonly. The ecx register will be modified. The edx
885 // and edi registers will be modified but restored to their original values. 920 // and edi registers will be modified but restored to their original values.
886 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false); 921 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false,
922 2, &stack_overflow);
923
924 // Restore edi and edx
925 __ Pop(edx);
926 __ Pop(edi);
887 927
888 __ AssertUndefinedOrAllocationSite(ebx); 928 __ AssertUndefinedOrAllocationSite(ebx);
889 if (construct_type == CallableType::kJSFunction) { 929 if (construct_type == CallableType::kJSFunction) {
890 // Tail call to the function-specific construct stub (still in the caller 930 // Tail call to the function-specific construct stub (still in the caller
891 // context at this point). 931 // context at this point).
892 __ AssertFunction(edi); 932 __ AssertFunction(edi);
893 933
894 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 934 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
895 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 935 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
896 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 936 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
897 __ jmp(ecx); 937 __ jmp(ecx);
898 } else { 938 } else {
899 DCHECK_EQ(construct_type, CallableType::kAny); 939 DCHECK_EQ(construct_type, CallableType::kAny);
900 940
901 // Call the constructor with unmodified eax, edi, edx values. 941 // Call the constructor with unmodified eax, edi, edx values.
902 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 942 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
903 } 943 }
944
945 __ bind(&stack_overflow);
946 {
947 // Pop the temporary registers, so that return address is on top of stack.
948 __ Pop(edx);
949 __ Pop(edi);
950
951 __ TailCallRuntime(Runtime::kThrowStackOverflow);
952
953 // This should be unreachable.
954 __ int3();
955 }
904 } 956 }
905 957
906 // static 958 // static
907 void Builtins::Generate_InterpreterPushArgsAndConstructArray( 959 void Builtins::Generate_InterpreterPushArgsAndConstructArray(
908 MacroAssembler* masm) { 960 MacroAssembler* masm) {
909 // ----------- S t a t e ------------- 961 // ----------- S t a t e -------------
910 // -- eax : the number of arguments (not including the receiver) 962 // -- eax : the number of arguments (not including the receiver)
911 // -- edx : the target to call checked to be Array function. 963 // -- edx : the target to call checked to be Array function.
912 // -- ebx : the allocation site feedback 964 // -- ebx : the allocation site feedback
913 // -- ecx : the address of the first argument to be pushed. Subsequent 965 // -- ecx : the address of the first argument to be pushed. Subsequent
914 // arguments should be consecutive above this, in the same order as 966 // arguments should be consecutive above this, in the same order as
915 // they are to be pushed onto the stack. 967 // they are to be pushed onto the stack.
916 // ----------------------------------- 968 // -----------------------------------
969 Label stack_overflow;
970 // We need two scratch registers. Register edi is available, push edx onto
971 // stack.
972 __ Push(edx);
917 973
918 // Push arguments and move return address to the top of stack. 974 // Push arguments and move return address to the top of stack.
919 // The eax register is readonly. The ecx register will be modified. The edx 975 // The eax register is readonly. The ecx register will be modified. The edx
920 // and edi registers will be modified but restored to their original values. 976 // and edi registers will be modified but restored to their original values.
921 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true); 977 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true,
978 1, &stack_overflow);
979
980 // Restore edx.
981 __ Pop(edx);
922 982
923 // Array constructor expects constructor in edi. It is same as edx here. 983 // Array constructor expects constructor in edi. It is same as edx here.
924 __ Move(edi, edx); 984 __ Move(edi, edx);
925 985
926 ArrayConstructorStub stub(masm->isolate()); 986 ArrayConstructorStub stub(masm->isolate());
927 __ TailCallStub(&stub); 987 __ TailCallStub(&stub);
988
989 __ bind(&stack_overflow);
990 {
991 // Pop the temporary registers, so that return address is on top of stack.
992 __ Pop(edx);
993
994 __ TailCallRuntime(Runtime::kThrowStackOverflow);
995
996 // This should be unreachable.
997 __ int3();
998 }
928 } 999 }
929 1000
930 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 1001 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
931 // Set the return address to the correct point in the interpreter entry 1002 // Set the return address to the correct point in the interpreter entry
932 // trampoline. 1003 // trampoline.
933 Smi* interpreter_entry_return_pc_offset( 1004 Smi* interpreter_entry_return_pc_offset(
934 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 1005 masm->isolate()->heap()->interpreter_entry_return_pc_offset());
935 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); 1006 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
936 __ LoadHeapObject(ebx, 1007 __ LoadHeapObject(ebx,
937 masm->isolate()->builtins()->InterpreterEntryTrampoline()); 1008 masm->isolate()->builtins()->InterpreterEntryTrampoline());
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 __ bind(&drop_frame_and_ret); 2214 __ bind(&drop_frame_and_ret);
2144 { 2215 {
2145 // Drop all arguments including the receiver. 2216 // Drop all arguments including the receiver.
2146 __ PopReturnAddressTo(ecx); 2217 __ PopReturnAddressTo(ecx);
2147 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2218 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize));
2148 __ PushReturnAddressFrom(ecx); 2219 __ PushReturnAddressFrom(ecx);
2149 __ Ret(); 2220 __ Ret();
2150 } 2221 }
2151 } 2222 }
2152 2223
2153 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
2154 Label* stack_overflow) {
2155 // ----------- S t a t e -------------
2156 // -- eax : actual number of arguments
2157 // -- ebx : expected number of arguments
2158 // -- edx : new target (passed through to callee)
2159 // -----------------------------------
2160 // Check the stack for overflow. We are not trying to catch
2161 // interruptions (e.g. debug break and preemption) here, so the "real stack
2162 // limit" is checked.
2163 ExternalReference real_stack_limit =
2164 ExternalReference::address_of_real_stack_limit(masm->isolate());
2165 __ mov(edi, Operand::StaticVariable(real_stack_limit));
2166 // Make ecx the space we have left. The stack might already be overflowed
2167 // here which will cause ecx to become negative.
2168 __ mov(ecx, esp);
2169 __ sub(ecx, edi);
2170 // Make edi the space we need for the array when it is unrolled onto the
2171 // stack.
2172 __ mov(edi, ebx);
2173 __ shl(edi, kPointerSizeLog2);
2174 // Check if the arguments will overflow the stack.
2175 __ cmp(ecx, edi);
2176 __ j(less_equal, stack_overflow); // Signed comparison.
2177 }
2178
2179 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 2224 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
2180 __ push(ebp); 2225 __ push(ebp);
2181 __ mov(ebp, esp); 2226 __ mov(ebp, esp);
2182 2227
2183 // Store the arguments adaptor context sentinel. 2228 // Store the arguments adaptor context sentinel.
2184 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2229 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2185 2230
2186 // Push the function on the stack. 2231 // Push the function on the stack.
2187 __ push(edi); 2232 __ push(edi);
2188 2233
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after
2915 2960
2916 Label enough, too_few; 2961 Label enough, too_few;
2917 __ cmp(eax, ebx); 2962 __ cmp(eax, ebx);
2918 __ j(less, &too_few); 2963 __ j(less, &too_few);
2919 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 2964 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
2920 __ j(equal, &dont_adapt_arguments); 2965 __ j(equal, &dont_adapt_arguments);
2921 2966
2922 { // Enough parameters: Actual >= expected. 2967 { // Enough parameters: Actual >= expected.
2923 __ bind(&enough); 2968 __ bind(&enough);
2924 EnterArgumentsAdaptorFrame(masm); 2969 EnterArgumentsAdaptorFrame(masm);
2925 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2970 // edi is used as a scratch register. It should be restored from the frame
2971 // when needed.
2972 Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow);
2926 2973
2927 // Copy receiver and all expected arguments. 2974 // Copy receiver and all expected arguments.
2928 const int offset = StandardFrameConstants::kCallerSPOffset; 2975 const int offset = StandardFrameConstants::kCallerSPOffset;
2929 __ lea(edi, Operand(ebp, eax, times_4, offset)); 2976 __ lea(edi, Operand(ebp, eax, times_4, offset));
2930 __ mov(eax, -1); // account for receiver 2977 __ mov(eax, -1); // account for receiver
2931 2978
2932 Label copy; 2979 Label copy;
2933 __ bind(&copy); 2980 __ bind(&copy);
2934 __ inc(eax); 2981 __ inc(eax);
2935 __ push(Operand(edi, 0)); 2982 __ push(Operand(edi, 0));
2936 __ sub(edi, Immediate(kPointerSize)); 2983 __ sub(edi, Immediate(kPointerSize));
2937 __ cmp(eax, ebx); 2984 __ cmp(eax, ebx);
2938 __ j(less, &copy); 2985 __ j(less, &copy);
2939 // eax now contains the expected number of arguments. 2986 // eax now contains the expected number of arguments.
2940 __ jmp(&invoke); 2987 __ jmp(&invoke);
2941 } 2988 }
2942 2989
2943 { // Too few parameters: Actual < expected. 2990 { // Too few parameters: Actual < expected.
2944 __ bind(&too_few); 2991 __ bind(&too_few);
2945 EnterArgumentsAdaptorFrame(masm); 2992 EnterArgumentsAdaptorFrame(masm);
2946 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2993 // edi is used as a scratch register. It should be restored from the frame
2994 // when needed.
2995 Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow);
2947 2996
2948 // Remember expected arguments in ecx. 2997 // Remember expected arguments in ecx.
2949 __ mov(ecx, ebx); 2998 __ mov(ecx, ebx);
2950 2999
2951 // Copy receiver and all actual arguments. 3000 // Copy receiver and all actual arguments.
2952 const int offset = StandardFrameConstants::kCallerSPOffset; 3001 const int offset = StandardFrameConstants::kCallerSPOffset;
2953 __ lea(edi, Operand(ebp, eax, times_4, offset)); 3002 __ lea(edi, Operand(ebp, eax, times_4, offset));
2954 // ebx = expected - actual. 3003 // ebx = expected - actual.
2955 __ sub(ebx, eax); 3004 __ sub(ebx, eax);
2956 // eax = -actual - 1 3005 // eax = -actual - 1
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
3171 3220
3172 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3221 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
3173 Generate_OnStackReplacementHelper(masm, true); 3222 Generate_OnStackReplacementHelper(masm, true);
3174 } 3223 }
3175 3224
3176 #undef __ 3225 #undef __
3177 } // namespace internal 3226 } // namespace internal
3178 } // namespace v8 3227 } // namespace v8
3179 3228
3180 #endif // V8_TARGET_ARCH_IA32 3229 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/builtins/arm64/builtins-arm64.cc ('k') | src/builtins/mips/builtins-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698