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

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

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