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

Side by Side Diff: src/builtins/x64/builtins-x64.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/mips64/builtins-mips64.cc ('k') | test/mjsunit/stack-traces-overflow.js » ('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_X64 5 #if V8_TARGET_ARCH_X64
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 764 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 // Push function as argument and compile for baseline. 775 // Push function as argument and compile for baseline.
776 __ Push(rdi); 776 __ Push(rdi);
777 __ CallRuntime(Runtime::kCompileBaseline); 777 __ CallRuntime(Runtime::kCompileBaseline);
778 778
779 // Restore return value. 779 // Restore return value.
780 __ Pop(rax); 780 __ Pop(rax);
781 } 781 }
782 __ ret(0); 782 __ ret(0);
783 } 783 }
784 784
785 static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
786 Register scratch1, Register scratch2,
787 Label* stack_overflow) {
788 // Check the stack for overflow. We are not trying to catch
789 // interruptions (e.g. debug break and preemption) here, so the "real stack
790 // limit" is checked.
791 __ LoadRoot(scratch1, Heap::kRealStackLimitRootIndex);
792 __ movp(scratch2, rsp);
793 // Make scratch2 the space we have left. The stack might already be overflowed
794 // here which will cause scratch2 to become negative.
795 __ subp(scratch2, scratch1);
796 // Make scratch1 the space we need for the array when it is unrolled onto the
797 // stack.
798 __ movp(scratch1, num_args);
799 __ shlp(scratch1, Immediate(kPointerSizeLog2));
800 // Check if the arguments will overflow the stack.
801 __ cmpp(scratch2, scratch1);
802 __ j(less_equal, stack_overflow); // Signed comparison.
803 }
804
785 static void Generate_InterpreterPushArgs(MacroAssembler* masm, 805 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
786 Register num_args, 806 Register num_args,
787 Register start_address, 807 Register start_address,
788 Register scratch) { 808 Register scratch) {
789 // Find the address of the last argument. 809 // Find the address of the last argument.
790 __ Move(scratch, num_args); 810 __ Move(scratch, num_args);
791 __ shlp(scratch, Immediate(kPointerSizeLog2)); 811 __ shlp(scratch, Immediate(kPointerSizeLog2));
792 __ negp(scratch); 812 __ negp(scratch);
793 __ addp(scratch, start_address); 813 __ addp(scratch, start_address);
794 814
795 // TODO(mythria): Add a stack check before pushing arguments.
796 // Push the arguments. 815 // Push the arguments.
797 Label loop_header, loop_check; 816 Label loop_header, loop_check;
798 __ j(always, &loop_check); 817 __ j(always, &loop_check);
799 __ bind(&loop_header); 818 __ bind(&loop_header);
800 __ Push(Operand(start_address, 0)); 819 __ Push(Operand(start_address, 0));
801 __ subp(start_address, Immediate(kPointerSize)); 820 __ subp(start_address, Immediate(kPointerSize));
802 __ bind(&loop_check); 821 __ bind(&loop_check);
803 __ cmpp(start_address, scratch); 822 __ cmpp(start_address, scratch);
804 __ j(greater, &loop_header, Label::kNear); 823 __ j(greater, &loop_header, Label::kNear);
805 } 824 }
806 825
807 // static 826 // static
808 void Builtins::Generate_InterpreterPushArgsAndCallImpl( 827 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
809 MacroAssembler* masm, TailCallMode tail_call_mode, 828 MacroAssembler* masm, TailCallMode tail_call_mode,
810 CallableType function_type) { 829 CallableType function_type) {
811 // ----------- S t a t e ------------- 830 // ----------- S t a t e -------------
812 // -- rax : the number of arguments (not including the receiver) 831 // -- rax : the number of arguments (not including the receiver)
813 // -- rbx : the address of the first argument to be pushed. Subsequent 832 // -- rbx : the address of the first argument to be pushed. Subsequent
814 // arguments should be consecutive above this, in the same order as 833 // arguments should be consecutive above this, in the same order as
815 // they are to be pushed onto the stack. 834 // they are to be pushed onto the stack.
816 // -- rdi : the target to call (can be any Object). 835 // -- rdi : the target to call (can be any Object).
817 // ----------------------------------- 836 // -----------------------------------
818 837 Label stack_overflow;
819 // Pop return address to allow tail-call after pushing arguments.
820 __ PopReturnAddressTo(kScratchRegister);
821 838
822 // Number of values to be pushed. 839 // Number of values to be pushed.
823 __ Move(rcx, rax); 840 __ Move(rcx, rax);
824 __ addp(rcx, Immediate(1)); // Add one for receiver. 841 __ addp(rcx, Immediate(1)); // Add one for receiver.
825 842
843 // Add a stack check before pushing arguments.
844 Generate_StackOverflowCheck(masm, rcx, rdx, r8, &stack_overflow);
845
846 // Pop return address to allow tail-call after pushing arguments.
847 __ PopReturnAddressTo(kScratchRegister);
848
826 // rbx and rdx will be modified. 849 // rbx and rdx will be modified.
827 Generate_InterpreterPushArgs(masm, rcx, rbx, rdx); 850 Generate_InterpreterPushArgs(masm, rcx, rbx, rdx);
828 851
829 // Call the target. 852 // Call the target.
830 __ PushReturnAddressFrom(kScratchRegister); // Re-push return address. 853 __ PushReturnAddressFrom(kScratchRegister); // Re-push return address.
831 854
832 if (function_type == CallableType::kJSFunction) { 855 if (function_type == CallableType::kJSFunction) {
833 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, 856 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny,
834 tail_call_mode), 857 tail_call_mode),
835 RelocInfo::CODE_TARGET); 858 RelocInfo::CODE_TARGET);
836 } else { 859 } else {
837 DCHECK_EQ(function_type, CallableType::kAny); 860 DCHECK_EQ(function_type, CallableType::kAny);
838 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 861 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
839 tail_call_mode), 862 tail_call_mode),
840 RelocInfo::CODE_TARGET); 863 RelocInfo::CODE_TARGET);
841 } 864 }
865
866 // Throw stack overflow exception.
867 __ bind(&stack_overflow);
868 {
869 __ TailCallRuntime(Runtime::kThrowStackOverflow);
870 // This should be unreachable.
871 __ int3();
872 }
842 } 873 }
843 874
844 // static 875 // static
845 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( 876 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
846 MacroAssembler* masm, CallableType construct_type) { 877 MacroAssembler* masm, CallableType construct_type) {
847 // ----------- S t a t e ------------- 878 // ----------- S t a t e -------------
848 // -- rax : the number of arguments (not including the receiver) 879 // -- rax : the number of arguments (not including the receiver)
849 // -- rdx : the new target (either the same as the constructor or 880 // -- rdx : the new target (either the same as the constructor or
850 // the JSFunction on which new was invoked initially) 881 // the JSFunction on which new was invoked initially)
851 // -- rdi : the constructor to call (can be any Object) 882 // -- rdi : the constructor to call (can be any Object)
852 // -- rbx : the allocation site feedback if available, undefined otherwise 883 // -- rbx : the allocation site feedback if available, undefined otherwise
853 // -- rcx : the address of the first argument to be pushed. Subsequent 884 // -- rcx : the address of the first argument to be pushed. Subsequent
854 // arguments should be consecutive above this, in the same order as 885 // arguments should be consecutive above this, in the same order as
855 // they are to be pushed onto the stack. 886 // they are to be pushed onto the stack.
856 // ----------------------------------- 887 // -----------------------------------
888 Label stack_overflow;
889
890 // Add a stack check before pushing arguments.
891 Generate_StackOverflowCheck(masm, rax, r8, r9, &stack_overflow);
857 892
858 // Pop return address to allow tail-call after pushing arguments. 893 // Pop return address to allow tail-call after pushing arguments.
859 __ PopReturnAddressTo(kScratchRegister); 894 __ PopReturnAddressTo(kScratchRegister);
860 895
861 // Push slot for the receiver to be constructed. 896 // Push slot for the receiver to be constructed.
862 __ Push(Immediate(0)); 897 __ Push(Immediate(0));
863 898
864 // rcx and r8 will be modified. 899 // rcx and r8 will be modified.
865 Generate_InterpreterPushArgs(masm, rax, rcx, r8); 900 Generate_InterpreterPushArgs(masm, rax, rcx, r8);
866 901
867 // Push return address in preparation for the tail-call. 902 // Push return address in preparation for the tail-call.
868 __ PushReturnAddressFrom(kScratchRegister); 903 __ PushReturnAddressFrom(kScratchRegister);
869 904
870 __ AssertUndefinedOrAllocationSite(rbx); 905 __ AssertUndefinedOrAllocationSite(rbx);
871 if (construct_type == CallableType::kJSFunction) { 906 if (construct_type == CallableType::kJSFunction) {
872 // Tail call to the function-specific construct stub (still in the caller 907 // Tail call to the function-specific construct stub (still in the caller
873 // context at this point). 908 // context at this point).
874 __ AssertFunction(rdi); 909 __ AssertFunction(rdi);
875 910
876 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 911 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
877 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); 912 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset));
878 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); 913 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize));
879 // Jump to the constructor function (rax, rbx, rdx passed on). 914 // Jump to the constructor function (rax, rbx, rdx passed on).
880 __ jmp(rcx); 915 __ jmp(rcx);
881 } else { 916 } else {
882 DCHECK_EQ(construct_type, CallableType::kAny); 917 DCHECK_EQ(construct_type, CallableType::kAny);
883 // Call the constructor (rax, rdx, rdi passed on). 918 // Call the constructor (rax, rdx, rdi passed on).
884 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 919 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
885 } 920 }
921
922 // Throw stack overflow exception.
923 __ bind(&stack_overflow);
924 {
925 __ TailCallRuntime(Runtime::kThrowStackOverflow);
926 // This should be unreachable.
927 __ int3();
928 }
886 } 929 }
887 930
888 // static 931 // static
889 void Builtins::Generate_InterpreterPushArgsAndConstructArray( 932 void Builtins::Generate_InterpreterPushArgsAndConstructArray(
890 MacroAssembler* masm) { 933 MacroAssembler* masm) {
891 // ----------- S t a t e ------------- 934 // ----------- S t a t e -------------
892 // -- rax : the number of arguments (not including the receiver) 935 // -- rax : the number of arguments (not including the receiver)
893 // -- rdx : the target to call checked to be Array function. 936 // -- rdx : the target to call checked to be Array function.
894 // -- rbx : the allocation site feedback 937 // -- rbx : the allocation site feedback
895 // -- rcx : the address of the first argument to be pushed. Subsequent 938 // -- rcx : the address of the first argument to be pushed. Subsequent
896 // arguments should be consecutive above this, in the same order as 939 // arguments should be consecutive above this, in the same order as
897 // they are to be pushed onto the stack. 940 // they are to be pushed onto the stack.
898 // ----------------------------------- 941 // -----------------------------------
899 942 Label stack_overflow;
900 // Pop return address to allow tail-call after pushing arguments.
901 __ PopReturnAddressTo(kScratchRegister);
902 943
903 // Number of values to be pushed. 944 // Number of values to be pushed.
904 __ Move(r8, rax); 945 __ Move(r8, rax);
905 __ addp(r8, Immediate(1)); // Add one for receiver. 946 __ addp(r8, Immediate(1)); // Add one for receiver.
906 947
948 // Add a stack check before pushing arguments.
949 Generate_StackOverflowCheck(masm, r8, rdi, r9, &stack_overflow);
950
951 // Pop return address to allow tail-call after pushing arguments.
952 __ PopReturnAddressTo(kScratchRegister);
953
907 // rcx and rdi will be modified. 954 // rcx and rdi will be modified.
908 Generate_InterpreterPushArgs(masm, r8, rcx, rdi); 955 Generate_InterpreterPushArgs(masm, r8, rcx, rdi);
909 956
910 // Push return address in preparation for the tail-call. 957 // Push return address in preparation for the tail-call.
911 __ PushReturnAddressFrom(kScratchRegister); 958 __ PushReturnAddressFrom(kScratchRegister);
912 959
913 // Array constructor expects constructor in rdi. It is same as rdx here. 960 // Array constructor expects constructor in rdi. It is same as rdx here.
914 __ Move(rdi, rdx); 961 __ Move(rdi, rdx);
915 962
916 ArrayConstructorStub stub(masm->isolate()); 963 ArrayConstructorStub stub(masm->isolate());
917 __ TailCallStub(&stub); 964 __ TailCallStub(&stub);
965
966 // Throw stack overflow exception.
967 __ bind(&stack_overflow);
968 {
969 __ TailCallRuntime(Runtime::kThrowStackOverflow);
970 // This should be unreachable.
971 __ int3();
972 }
918 } 973 }
919 974
920 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 975 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
921 // Set the return address to the correct point in the interpreter entry 976 // Set the return address to the correct point in the interpreter entry
922 // trampoline. 977 // trampoline.
923 Smi* interpreter_entry_return_pc_offset( 978 Smi* interpreter_entry_return_pc_offset(
924 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 979 masm->isolate()->heap()->interpreter_entry_return_pc_offset());
925 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); 980 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
926 __ Move(rbx, masm->isolate()->builtins()->InterpreterEntryTrampoline()); 981 __ Move(rbx, masm->isolate()->builtins()->InterpreterEntryTrampoline());
927 __ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() + 982 __ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() +
(...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2110 { 2165 {
2111 // Drop all arguments including the receiver. 2166 // Drop all arguments including the receiver.
2112 __ PopReturnAddressTo(rcx); 2167 __ PopReturnAddressTo(rcx);
2113 __ SmiToInteger32(r8, r8); 2168 __ SmiToInteger32(r8, r8);
2114 __ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize)); 2169 __ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize));
2115 __ PushReturnAddressFrom(rcx); 2170 __ PushReturnAddressFrom(rcx);
2116 __ Ret(); 2171 __ Ret();
2117 } 2172 }
2118 } 2173 }
2119 2174
2120 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
2121 Label* stack_overflow) {
2122 // ----------- S t a t e -------------
2123 // -- rax : actual number of arguments
2124 // -- rbx : expected number of arguments
2125 // -- rdx : new target (passed through to callee)
2126 // -- rdi : function (passed through to callee)
2127 // -----------------------------------
2128 // Check the stack for overflow. We are not trying to catch
2129 // interruptions (e.g. debug break and preemption) here, so the "real stack
2130 // limit" is checked.
2131 Label okay;
2132 __ LoadRoot(r8, Heap::kRealStackLimitRootIndex);
2133 __ movp(rcx, rsp);
2134 // Make rcx the space we have left. The stack might already be overflowed
2135 // here which will cause rcx to become negative.
2136 __ subp(rcx, r8);
2137 // Make r8 the space we need for the array when it is unrolled onto the
2138 // stack.
2139 __ movp(r8, rbx);
2140 __ shlp(r8, Immediate(kPointerSizeLog2));
2141 // Check if the arguments will overflow the stack.
2142 __ cmpp(rcx, r8);
2143 __ j(less_equal, stack_overflow); // Signed comparison.
2144 }
2145
2146 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 2175 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
2147 __ pushq(rbp); 2176 __ pushq(rbp);
2148 __ movp(rbp, rsp); 2177 __ movp(rbp, rsp);
2149 2178
2150 // Store the arguments adaptor context sentinel. 2179 // Store the arguments adaptor context sentinel.
2151 __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2180 __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2152 2181
2153 // Push the function on the stack. 2182 // Push the function on the stack.
2154 __ Push(rdi); 2183 __ Push(rdi);
2155 2184
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 2279
2251 Label enough, too_few; 2280 Label enough, too_few;
2252 __ cmpp(rax, rbx); 2281 __ cmpp(rax, rbx);
2253 __ j(less, &too_few); 2282 __ j(less, &too_few);
2254 __ cmpp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 2283 __ cmpp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
2255 __ j(equal, &dont_adapt_arguments); 2284 __ j(equal, &dont_adapt_arguments);
2256 2285
2257 { // Enough parameters: Actual >= expected. 2286 { // Enough parameters: Actual >= expected.
2258 __ bind(&enough); 2287 __ bind(&enough);
2259 EnterArgumentsAdaptorFrame(masm); 2288 EnterArgumentsAdaptorFrame(masm);
2260 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2289 // The registers rcx and r8 will be modified. The register rbx is only read.
2290 Generate_StackOverflowCheck(masm, rbx, rcx, r8, &stack_overflow);
2261 2291
2262 // Copy receiver and all expected arguments. 2292 // Copy receiver and all expected arguments.
2263 const int offset = StandardFrameConstants::kCallerSPOffset; 2293 const int offset = StandardFrameConstants::kCallerSPOffset;
2264 __ leap(rax, Operand(rbp, rax, times_pointer_size, offset)); 2294 __ leap(rax, Operand(rbp, rax, times_pointer_size, offset));
2265 __ Set(r8, -1); // account for receiver 2295 __ Set(r8, -1); // account for receiver
2266 2296
2267 Label copy; 2297 Label copy;
2268 __ bind(&copy); 2298 __ bind(&copy);
2269 __ incp(r8); 2299 __ incp(r8);
2270 __ Push(Operand(rax, 0)); 2300 __ Push(Operand(rax, 0));
2271 __ subp(rax, Immediate(kPointerSize)); 2301 __ subp(rax, Immediate(kPointerSize));
2272 __ cmpp(r8, rbx); 2302 __ cmpp(r8, rbx);
2273 __ j(less, &copy); 2303 __ j(less, &copy);
2274 __ jmp(&invoke); 2304 __ jmp(&invoke);
2275 } 2305 }
2276 2306
2277 { // Too few parameters: Actual < expected. 2307 { // Too few parameters: Actual < expected.
2278 __ bind(&too_few); 2308 __ bind(&too_few);
2279 2309
2280 EnterArgumentsAdaptorFrame(masm); 2310 EnterArgumentsAdaptorFrame(masm);
2281 ArgumentsAdaptorStackCheck(masm, &stack_overflow); 2311 // The registers rcx and r8 will be modified. The register rbx is only read.
2312 Generate_StackOverflowCheck(masm, rbx, rcx, r8, &stack_overflow);
2282 2313
2283 // Copy receiver and all actual arguments. 2314 // Copy receiver and all actual arguments.
2284 const int offset = StandardFrameConstants::kCallerSPOffset; 2315 const int offset = StandardFrameConstants::kCallerSPOffset;
2285 __ leap(rdi, Operand(rbp, rax, times_pointer_size, offset)); 2316 __ leap(rdi, Operand(rbp, rax, times_pointer_size, offset));
2286 __ Set(r8, -1); // account for receiver 2317 __ Set(r8, -1); // account for receiver
2287 2318
2288 Label copy; 2319 Label copy;
2289 __ bind(&copy); 2320 __ bind(&copy);
2290 __ incp(r8); 2321 __ incp(r8);
2291 __ Push(Operand(rdi, 0)); 2322 __ Push(Operand(rdi, 0));
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
3134 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3165 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
3135 Generate_OnStackReplacementHelper(masm, true); 3166 Generate_OnStackReplacementHelper(masm, true);
3136 } 3167 }
3137 3168
3138 #undef __ 3169 #undef __
3139 3170
3140 } // namespace internal 3171 } // namespace internal
3141 } // namespace v8 3172 } // namespace v8
3142 3173
3143 #endif // V8_TARGET_ARCH_X64 3174 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/builtins/mips64/builtins-mips64.cc ('k') | test/mjsunit/stack-traces-overflow.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698