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

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

Issue 2335513004: [Interpreter] Adds stackcheck in InterpreterPushArgsAndCall/Construct builtins. (Closed)
Patch Set: fix for 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
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);
rmcilroy 2016/09/12 14:43:17 Not really keen on this pop. Could you not just us
mythria 2016/09/13 09:53:33 As discussed offline, we can't use esi, because it
796
797 __ TailCallRuntime(Runtime::kThrowStackOverflow);
798
799 __ int3();
800 }
762 } 801 }
763 802
764 namespace { 803 namespace {
765 804
766 // This function modified start_addr, and only reads the contents of num_args 805 // This function modified start_addr, and only reads the contents of num_args
767 // register. scratch1 and scratch2 are used as temporary registers. Their 806 // register. scratch1 and scratch2 are used as temporary registers. Their
768 // original values are restored after the use. 807 // original values are restored after the use.
769 void Generate_InterpreterPushArgsAndReturnAddress( 808 void Generate_InterpreterPushArgsAndReturnAddress(
770 MacroAssembler* masm, Register num_args, Register start_addr, 809 MacroAssembler* masm, Register num_args, Register start_addr,
771 Register scratch1, Register scratch2, bool receiver_in_args) { 810 Register scratch1, Register scratch2, bool receiver_in_args,
811 Label* stack_overflow) {
772 // Store scratch2, scratch1 onto the stack. We need to restore the original 812 // Store scratch2, scratch1 onto the stack. We need to restore the original
773 // values 813 // values so store scratch2, scratch1 temporarily on stack.
774 // so store scratch2, scratch1 temporarily on stack.
775 __ Push(scratch2); 814 __ Push(scratch2);
776 __ Push(scratch1); 815 __ Push(scratch1);
777 816
778 // We have to pop return address and the two temporary registers before we 817 // 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 818 // 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. 819 // update the stack and copy them into the correct places on the stack.
781 // current stack =====> required stack layout 820 // current stack =====> required stack layout
782 // | | | scratch1 | (2) <-- esp(1) 821 // | | | scratch1 | (2) <-- esp(1)
783 // | | | scratch2 | (3) 822 // | | | scratch2 | (3)
784 // | | | return addr | (4) 823 // | | | return addr | (4)
785 // | | | arg N | (5) 824 // | | | arg N | (5)
786 // | scratch1 | <-- esp | .... | 825 // | scratch1 | <-- esp | .... |
787 // | scratch2 | | arg 0 | 826 // | scratch2 | | arg 0 |
788 // | return addr | | receiver slot | 827 // | return addr | | receiver slot |
789 828
829 // Check for stack overflow before we push arguments.
830 // Check the stack for overflow. We are not trying to catch
831 // interruptions (e.g. debug break and preemption) here, so the "real stack
832 // limit" is checked.
833 ExternalReference real_stack_limit =
834 ExternalReference::address_of_real_stack_limit(masm->isolate());
835 __ mov(scratch1, Operand::StaticVariable(real_stack_limit));
836 // Make scratch2 the space we have left. The stack might already be overflowed
837 // here which will cause scratch2 to become negative.
838 __ mov(scratch2, esp);
839 __ sub(scratch2, scratch1);
840
841 // Compute expected number of arguments.
842 __ mov(scratch1, num_args);
843 __ add(scratch1, Immediate(1)); // Add one for receiver.
844 __ shl(scratch1, kPointerSizeLog2);
845
846 __ cmp(scratch2, scratch1);
847 __ j(less_equal, stack_overflow); // Signed comparison.
848
790 // First increment the stack pointer to the correct location. 849 // First increment the stack pointer to the correct location.
791 // we need additional slots for arguments and the receiver. 850 // we need additional slots for arguments and the receiver.
792 // Step 1 - compute the required increment to the stack. 851 // Step 1 - compute the required increment to the stack.
793 __ mov(scratch1, num_args);
794 __ shl(scratch1, kPointerSizeLog2);
795 __ add(scratch1, Immediate(kPointerSize));
796 852
797 #ifdef _MSC_VER 853 #ifdef _MSC_VER
798 // TODO(mythria): Move it to macro assembler. 854 // TODO(mythria): Move it to macro assembler.
799 // In windows, we cannot increment the stack size by more than one page 855 // 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 856 // (mimimum page size is 4KB) without accessing at least one byte on the
801 // page. Check this: 857 // page. Check this:
802 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 858 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
803 const int page_size = 4 * 1024; 859 const int page_size = 4 * 1024;
804 Label check_offset, update_stack_pointer; 860 Label check_offset, update_stack_pointer;
805 __ bind(&check_offset); 861 __ bind(&check_offset);
806 __ cmp(scratch1, page_size); 862 __ cmp(scratch1, page_size);
807 __ j(less, &update_stack_pointer); 863 __ j(less, &update_stack_pointer);
808 __ sub(esp, Immediate(page_size)); 864 __ sub(esp, Immediate(page_size));
809 // Just to touch the page, before we increment further. 865 // Just to touch the page, before we increment further.
810 __ mov(Operand(esp, 0), Immediate(0)); 866 __ mov(Operand(esp, 0), Immediate(0));
811 __ sub(scratch1, Immediate(page_size)); 867 __ sub(scratch1, Immediate(page_size));
812 __ jmp(&check_offset); 868 __ jmp(&check_offset);
813 __ bind(&update_stack_pointer); 869 __ bind(&update_stack_pointer);
814 #endif 870 #endif
815 871
816 // TODO(mythria): Add a stack check before updating the stack pointer.
817 872
818 // Step 1 - Update the stack pointer. 873 // Step 1 - Update the stack pointer.
819 __ sub(esp, scratch1); 874 __ sub(esp, scratch1);
820 875
821 // Step 2 move scratch1 to the correct location. Move scratch1 first otherwise 876 // Step 2 move scratch1 to the correct location. Move scratch1 first otherwise
822 // we may overwrite when num_args = 0 or 1, basically when the source and 877 // we may overwrite when num_args = 0 or 1, basically when the source and
823 // destination overlap. We at least need one extra slot for receiver, 878 // destination overlap. We at least need one extra slot for receiver,
824 // so no extra checks are required to avoid copy. 879 // so no extra checks are required to avoid copy.
825 __ mov(scratch1, 880 __ mov(scratch1,
826 Operand(esp, num_args, times_pointer_size, 1 * kPointerSize)); 881 Operand(esp, num_args, times_pointer_size, 1 * kPointerSize));
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 MacroAssembler* masm, CallableType construct_type) { 927 MacroAssembler* masm, CallableType construct_type) {
873 // ----------- S t a t e ------------- 928 // ----------- S t a t e -------------
874 // -- eax : the number of arguments (not including the receiver) 929 // -- eax : the number of arguments (not including the receiver)
875 // -- edx : the new target 930 // -- edx : the new target
876 // -- edi : the constructor 931 // -- edi : the constructor
877 // -- ebx : allocation site feedback (if available or undefined) 932 // -- ebx : allocation site feedback (if available or undefined)
878 // -- ecx : the address of the first argument to be pushed. Subsequent 933 // -- ecx : the address of the first argument to be pushed. Subsequent
879 // arguments should be consecutive above this, in the same order as 934 // arguments should be consecutive above this, in the same order as
880 // they are to be pushed onto the stack. 935 // they are to be pushed onto the stack.
881 // ----------------------------------- 936 // -----------------------------------
937 Label stack_overflow;
882 938
883 // Push arguments and move return address to the top of stack. 939 // 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 940 // 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. 941 // and edi registers will be modified but restored to their original values.
886 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false); 942 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false,
943 &stack_overflow);
887 944
888 __ AssertUndefinedOrAllocationSite(ebx); 945 __ AssertUndefinedOrAllocationSite(ebx);
889 if (construct_type == CallableType::kJSFunction) { 946 if (construct_type == CallableType::kJSFunction) {
890 // Tail call to the function-specific construct stub (still in the caller 947 // Tail call to the function-specific construct stub (still in the caller
891 // context at this point). 948 // context at this point).
892 __ AssertFunction(edi); 949 __ AssertFunction(edi);
893 950
894 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 951 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
895 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 952 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
896 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 953 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
897 __ jmp(ecx); 954 __ jmp(ecx);
898 } else { 955 } else {
899 DCHECK_EQ(construct_type, CallableType::kAny); 956 DCHECK_EQ(construct_type, CallableType::kAny);
900 957
901 // Call the constructor with unmodified eax, edi, edx values. 958 // Call the constructor with unmodified eax, edi, edx values.
902 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 959 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
903 } 960 }
961
962 __ bind(&stack_overflow);
963 {
964 // Pop the temporary registers, so that return address is on top of stack.
965 __ Pop(edx);
966 __ Pop(edi);
rmcilroy 2016/09/12 14:43:17 Really don't like this - it's impossible to see th
mythria 2016/09/13 09:53:33 I reworked the code. I don't think we can avoid us
967
968 __ TailCallRuntime(Runtime::kThrowStackOverflow);
969
970 __ int3();
971 }
904 } 972 }
905 973
906 // static 974 // static
907 void Builtins::Generate_InterpreterPushArgsAndConstructArray( 975 void Builtins::Generate_InterpreterPushArgsAndConstructArray(
908 MacroAssembler* masm) { 976 MacroAssembler* masm) {
909 // ----------- S t a t e ------------- 977 // ----------- S t a t e -------------
910 // -- eax : the number of arguments (not including the receiver) 978 // -- eax : the number of arguments (not including the receiver)
911 // -- edx : the target to call checked to be Array function. 979 // -- edx : the target to call checked to be Array function.
912 // -- ebx : the allocation site feedback 980 // -- ebx : the allocation site feedback
913 // -- ecx : the address of the first argument to be pushed. Subsequent 981 // -- ecx : the address of the first argument to be pushed. Subsequent
914 // arguments should be consecutive above this, in the same order as 982 // arguments should be consecutive above this, in the same order as
915 // they are to be pushed onto the stack. 983 // they are to be pushed onto the stack.
916 // ----------------------------------- 984 // -----------------------------------
985 Label stack_overflow;
917 986
918 // Push arguments and move return address to the top of stack. 987 // 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 988 // 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. 989 // and edi registers will be modified but restored to their original values.
921 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true); 990 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true,
991 &stack_overflow);
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 __ Pop(edi);
1004
1005 __ TailCallRuntime(Runtime::kThrowStackOverflow);
1006
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

Powered by Google App Engine
This is Rietveld 408576698