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

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

Issue 2307903002: [Interpreter] Collect allocation site feedback in call bytecode handler. (Closed)
Patch Set: corrected few comments. 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 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 tail_call_mode), 754 tail_call_mode),
755 RelocInfo::CODE_TARGET); 755 RelocInfo::CODE_TARGET);
756 } else { 756 } else {
757 DCHECK_EQ(function_type, CallableType::kAny); 757 DCHECK_EQ(function_type, CallableType::kAny);
758 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 758 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
759 tail_call_mode), 759 tail_call_mode),
760 RelocInfo::CODE_TARGET); 760 RelocInfo::CODE_TARGET);
761 } 761 }
762 } 762 }
763 763
764 // static 764 namespace {
765 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
766 MacroAssembler* masm, CallableType construct_type) {
767 // ----------- S t a t e -------------
768 // -- eax : the number of arguments (not including the receiver)
769 // -- edx : the new target
770 // -- edi : the constructor
771 // -- ebx : allocation site feedback (if available or undefined)
772 // -- ecx : the address of the first argument to be pushed. Subsequent
773 // arguments should be consecutive above this, in the same order as
774 // they are to be pushed onto the stack.
775 // -----------------------------------
776 765
777 // Store edi, edx onto the stack. We need two extra registers 766 // This function modified start_addr, and only reads the contents of num_args
778 // so store edi, edx temporarily on stack. 767 // register. reg1 and reg2 are used as temporary registers. Their original
779 __ Push(edi); 768 // values are restored after the use. reg1 and reg2 will be pushed onto the
780 __ Push(edx); 769 // stack, so they should either have an Smi or a tagged pointer.
rmcilroy 2016/09/07 10:57:39 Do reg1/reg2 need to be tagged? They are pushed, b
mythria 2016/09/07 13:11:15 As mentioned offline, I was thinking about interru
770 void Generate_InterpreterPushArgsAndReturnAddress(MacroAssembler* masm,
771 Register num_args,
772 Register start_addr,
773 Register reg1, Register reg2,
rmcilroy 2016/09/07 10:57:39 nit - reg1 / reg2 -> scratch1 / scratch2 (also upd
mythria 2016/09/07 13:11:16 Done.
774 bool receiver_in_args) {
775 // Store reg2, reg1 onto the stack. We need to restore the original values
776 // so store reg2, reg1 temporarily on stack.
777 __ Push(reg2);
778 __ Push(reg1);
781 779
782 // We have to pop return address and the two temporary registers before we 780 // We have to pop return address and the two temporary registers before we
783 // can push arguments onto the stack. we do not have any free registers so 781 // can push arguments onto the stack. we do not have any free registers so
784 // update the stack and copy them into the correct places on the stack. 782 // update the stack and copy them into the correct places on the stack.
785 // current stack =====> required stack layout 783 // current stack =====> required stack layout
786 // | | | edx | (2) <-- esp(1) 784 // | | | reg1 | (2) <-- esp(1)
787 // | | | edi | (3) 785 // | | | reg2 | (3)
788 // | | | return addr | (4) 786 // | | | return addr | (4)
789 // | | | arg N | (5) 787 // | | | arg N | (5)
790 // | edx | <-- esp | .... | 788 // | reg1 | <-- esp | .... |
791 // | edi | | arg 0 | 789 // | reg2 | | arg 0 |
792 // | return addr | | receiver slot | 790 // | return addr | | receiver slot |
793 791
794 // First increment the stack pointer to the correct location. 792 // First increment the stack pointer to the correct location.
795 // we need additional slots for arguments and the receiver. 793 // we need additional slots for arguments and the receiver.
796 // Step 1 - compute the required increment to the stack. 794 // Step 1 - compute the required increment to the stack.
797 __ mov(edx, eax); 795 __ mov(reg1, num_args);
798 __ shl(edx, kPointerSizeLog2); 796 __ shl(reg1, kPointerSizeLog2);
799 __ add(edx, Immediate(kPointerSize)); 797 __ add(reg1, Immediate(kPointerSize));
800 798
801 #ifdef _MSC_VER 799 #ifdef _MSC_VER
802 // TODO(mythria): Move it to macro assembler. 800 // TODO(mythria): Move it to macro assembler.
803 // In windows, we cannot increment the stack size by more than one page 801 // In windows, we cannot increment the stack size by more than one page
804 // (mimimum page size is 4KB) without accessing at least one byte on the 802 // (mimimum page size is 4KB) without accessing at least one byte on the
805 // page. Check this: 803 // page. Check this:
806 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 804 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
807 const int page_size = 4 * 1024; 805 const int page_size = 4 * 1024;
808 Label check_offset, update_stack_pointer; 806 Label check_offset, update_stack_pointer;
809 __ bind(&check_offset); 807 __ bind(&check_offset);
810 __ cmp(edx, page_size); 808 __ cmp(reg1, page_size);
811 __ j(less, &update_stack_pointer); 809 __ j(less, &update_stack_pointer);
812 __ sub(esp, Immediate(page_size)); 810 __ sub(esp, Immediate(page_size));
813 // Just to touch the page, before we increment further. 811 // Just to touch the page, before we increment further.
814 __ mov(Operand(esp, 0), Immediate(0)); 812 __ mov(Operand(esp, 0), Immediate(0));
815 __ sub(edx, Immediate(page_size)); 813 __ sub(reg1, Immediate(page_size));
816 __ jmp(&check_offset); 814 __ jmp(&check_offset);
817 __ bind(&update_stack_pointer); 815 __ bind(&update_stack_pointer);
818 #endif 816 #endif
819 817
820 // TODO(mythria): Add a stack check before updating the stack pointer. 818 // TODO(mythria): Add a stack check before updating the stack pointer.
821 819
822 // Step 1 - Update the stack pointer. 820 // Step 1 - Update the stack pointer.
823 __ sub(esp, edx); 821 __ sub(esp, reg1);
824 822
825 // Step 2 move edx to the correct location. Move edx first otherwise 823 // Step 2 move reg1 to the correct location. Move reg1 first otherwise
826 // we may overwrite when eax = 0 or 1, basically when the source and 824 // we may overwrite when num_args = 0 or 1, basically when the source and
827 // destination overlap. We at least need one extra slot for receiver, 825 // destination overlap. We at least need one extra slot for receiver,
828 // so no extra checks are required to avoid copy. 826 // so no extra checks are required to avoid copy.
829 __ mov(edi, Operand(esp, eax, times_pointer_size, 1 * kPointerSize)); 827 __ mov(reg1, Operand(esp, num_args, times_pointer_size, 1 * kPointerSize));
830 __ mov(Operand(esp, 0), edi); 828 __ mov(Operand(esp, 0), reg1);
831 829
832 // Step 3 move edi to the correct location 830 // Step 3 move reg2 to the correct location
833 __ mov(edi, Operand(esp, eax, times_pointer_size, 2 * kPointerSize)); 831 __ mov(reg1, Operand(esp, num_args, times_pointer_size, 2 * kPointerSize));
834 __ mov(Operand(esp, 1 * kPointerSize), edi); 832 __ mov(Operand(esp, 1 * kPointerSize), reg1);
835 833
836 // Step 4 move return address to the correct location 834 // Step 4 move return address to the correct location
837 __ mov(edi, Operand(esp, eax, times_pointer_size, 3 * kPointerSize)); 835 __ mov(reg1, Operand(esp, num_args, times_pointer_size, 3 * kPointerSize));
838 __ mov(Operand(esp, 2 * kPointerSize), edi); 836 __ mov(Operand(esp, 2 * kPointerSize), reg1);
839
840 // Slot meant for receiver contains return address. Reset it so that
841 // we will not incorrectly interpret return address as an object.
842 __ mov(Operand(esp, eax, times_pointer_size, 3 * kPointerSize), Immediate(0));
843 837
844 // Step 5 copy arguments to correct locations. 838 // Step 5 copy arguments to correct locations.
845 __ mov(edx, eax); 839 if (receiver_in_args) {
840 __ mov(reg1, num_args);
841 __ add(reg1, Immediate(1));
842 } else {
843 // Slot meant for receiver contains return address. Reset it so that
844 // we will not incorrectly interpret return address as an object.
845 __ mov(Operand(esp, num_args, times_pointer_size, 3 * kPointerSize),
846 Immediate(0));
847 __ mov(reg1, num_args);
848 }
846 849
847 Label loop_header, loop_check; 850 Label loop_header, loop_check;
848 __ jmp(&loop_check); 851 __ jmp(&loop_check);
849 __ bind(&loop_header); 852 __ bind(&loop_header);
850 __ mov(edi, Operand(ecx, 0)); 853 __ mov(reg2, Operand(start_addr, 0));
851 __ mov(Operand(esp, edx, times_pointer_size, 2 * kPointerSize), edi); 854 __ mov(Operand(esp, reg1, times_pointer_size, 2 * kPointerSize), reg2);
852 __ sub(ecx, Immediate(kPointerSize)); 855 __ sub(start_addr, Immediate(kPointerSize));
853 __ sub(edx, Immediate(1)); 856 __ sub(reg1, Immediate(1));
854 __ bind(&loop_check); 857 __ bind(&loop_check);
855 __ cmp(edx, Immediate(0)); 858 __ cmp(reg1, Immediate(0));
856 __ j(greater, &loop_header, Label::kNear); 859 __ j(greater, &loop_header, Label::kNear);
857 860
858 // Restore edi and edx. 861 // Restore reg1 and reg2.
859 __ Pop(edx); 862 __ Pop(reg1);
860 __ Pop(edi); 863 __ Pop(reg2);
864 }
865
866 } // end anonymous namespace
867
868 // static
869 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
870 MacroAssembler* masm, CallableType construct_type) {
871 // ----------- S t a t e -------------
872 // -- eax : the number of arguments (not including the receiver)
873 // -- edx : the new target
874 // -- edi : the constructor
875 // -- ebx : allocation site feedback (if available or undefined)
876 // -- ecx : the address of the first argument to be pushed. Subsequent
877 // arguments should be consecutive above this, in the same order as
878 // they are to be pushed onto the stack.
879 // -----------------------------------
880
881 // Push arguments and move return address to the top of stack.
882 // eax is readonly. ecx will be modified. edx and edi will be modified but
rmcilroy 2016/09/07 10:57:39 Capitalize start of sentences (e.g., do "The eax r
mythria 2016/09/07 13:11:15 Done.
883 // restored to their original values. edx and edi will be pushed onto the
884 // stack, so ensure they have an Smi or tagged pointer.
885 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false);
861 886
862 __ AssertUndefinedOrAllocationSite(ebx); 887 __ AssertUndefinedOrAllocationSite(ebx);
863 if (construct_type == CallableType::kJSFunction) { 888 if (construct_type == CallableType::kJSFunction) {
864 // Tail call to the function-specific construct stub (still in the caller 889 // Tail call to the function-specific construct stub (still in the caller
865 // context at this point). 890 // context at this point).
866 __ AssertFunction(edi); 891 __ AssertFunction(edi);
867 892
868 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 893 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
869 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 894 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
870 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 895 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
871 __ jmp(ecx); 896 __ jmp(ecx);
872 } else { 897 } else {
873 DCHECK_EQ(construct_type, CallableType::kAny); 898 DCHECK_EQ(construct_type, CallableType::kAny);
874 899
875 // Call the constructor with unmodified eax, edi, edx values. 900 // Call the constructor with unmodified eax, edi, edx values.
876 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 901 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
877 } 902 }
878 } 903 }
879 904
905 // static
906 void Builtins::Generate_InterpreterPushArgsAndConstructArray(
907 MacroAssembler* masm) {
908 // ----------- S t a t e -------------
909 // -- eax : the number of arguments (not including the receiver)
910 // -- edx : the target to call checked to be Array function.
911 // -- ebx : the allocation site feedback
912 // -- ecx : the address of the first argument to be pushed. Subsequent
913 // arguments should be consecutive above this, in the same order as
914 // they are to be pushed onto the stack.
915 // -----------------------------------
916
917 // Push arguments and move return address to the top of stack.
918 // eax is readonly. ecx will be modified. edx and ebx will be modified but
919 // restored to their original values. edx and ebx will be pushed onto the
920 // stack, so ensure they have an Smi or tagged pointer.
921 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, ebx, true);
922
923 // Array constructor expects constructor in edi. It is same as edx here.
924 __ Move(edi, edx);
925
926 ArrayConstructorStub stub(masm->isolate());
927 __ TailCallStub(&stub);
928 }
929
880 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 930 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
881 // Set the return address to the correct point in the interpreter entry 931 // Set the return address to the correct point in the interpreter entry
882 // trampoline. 932 // trampoline.
883 Smi* interpreter_entry_return_pc_offset( 933 Smi* interpreter_entry_return_pc_offset(
884 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 934 masm->isolate()->heap()->interpreter_entry_return_pc_offset());
885 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); 935 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
886 __ LoadHeapObject(ebx, 936 __ LoadHeapObject(ebx,
887 masm->isolate()->builtins()->InterpreterEntryTrampoline()); 937 masm->isolate()->builtins()->InterpreterEntryTrampoline());
888 __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() + 938 __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() +
889 Code::kHeaderSize - kHeapObjectTag)); 939 Code::kHeaderSize - kHeapObjectTag));
(...skipping 2231 matching lines...) Expand 10 before | Expand all | Expand 10 after
3121 3171
3122 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3172 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
3123 Generate_OnStackReplacementHelper(masm, true); 3173 Generate_OnStackReplacementHelper(masm, true);
3124 } 3174 }
3125 3175
3126 #undef __ 3176 #undef __
3127 } // namespace internal 3177 } // namespace internal
3128 } // namespace v8 3178 } // namespace v8
3129 3179
3130 #endif // V8_TARGET_ARCH_IA32 3180 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698