OLD | NEW |
---|---|
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 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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_InterpreterPushArgs(MacroAssembler* masm, | 706 static void Generate_InterpreterPushArgs(MacroAssembler* masm, |
707 Register array_limit) { | 707 Register array_limit, |
708 Register start_address) { | |
708 // ----------- S t a t e ------------- | 709 // ----------- S t a t e ------------- |
709 // -- ebx : Pointer to the last argument in the args array. | 710 // -- start_address : Pointer to the last argument in the args array. |
710 // -- array_limit : Pointer to one before the first argument in the | 711 // -- array_limit : Pointer to one before the first argument in the |
711 // args array. | 712 // args array. |
712 // ----------------------------------- | 713 // ----------------------------------- |
713 Label loop_header, loop_check; | 714 Label loop_header, loop_check; |
714 __ jmp(&loop_check); | 715 __ jmp(&loop_check); |
715 __ bind(&loop_header); | 716 __ bind(&loop_header); |
716 __ Push(Operand(ebx, 0)); | 717 __ Push(Operand(start_address, 0)); |
717 __ sub(ebx, Immediate(kPointerSize)); | 718 __ sub(start_address, Immediate(kPointerSize)); |
718 __ bind(&loop_check); | 719 __ bind(&loop_check); |
719 __ cmp(ebx, array_limit); | 720 __ cmp(start_address, array_limit); |
720 __ j(greater, &loop_header, Label::kNear); | 721 __ j(greater, &loop_header, Label::kNear); |
721 } | 722 } |
722 | 723 |
723 // static | 724 // static |
724 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 725 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
725 MacroAssembler* masm, TailCallMode tail_call_mode, | 726 MacroAssembler* masm, TailCallMode tail_call_mode, |
726 CallableType function_type) { | 727 CallableType function_type) { |
727 // ----------- S t a t e ------------- | 728 // ----------- S t a t e ------------- |
728 // -- eax : the number of arguments (not including the receiver) | 729 // -- eax : the number of arguments (not including the receiver) |
729 // -- ebx : the address of the first argument to be pushed. Subsequent | 730 // -- ebx : the address of the first argument to be pushed. Subsequent |
730 // arguments should be consecutive above this, in the same order as | 731 // arguments should be consecutive above this, in the same order as |
731 // they are to be pushed onto the stack. | 732 // they are to be pushed onto the stack. |
732 // -- edi : the target to call (can be any Object). | 733 // -- edi : the target to call (can be any Object). |
733 // ----------------------------------- | 734 // ----------------------------------- |
734 | 735 |
735 // Pop return address to allow tail-call after pushing arguments. | 736 // Pop return address to allow tail-call after pushing arguments. |
736 __ Pop(edx); | 737 __ Pop(edx); |
737 | 738 |
738 // Find the address of the last argument. | 739 // Find the address of the last argument. |
739 __ mov(ecx, eax); | 740 __ mov(ecx, eax); |
740 __ add(ecx, Immediate(1)); // Add one for receiver. | 741 __ add(ecx, Immediate(1)); // Add one for receiver. |
741 __ shl(ecx, kPointerSizeLog2); | 742 __ shl(ecx, kPointerSizeLog2); |
742 __ neg(ecx); | 743 __ neg(ecx); |
743 __ add(ecx, ebx); | 744 __ add(ecx, ebx); |
744 | 745 |
745 Generate_InterpreterPushArgs(masm, ecx); | 746 // TODO(mythria): Add a stack check before pushing the arguments. |
747 Generate_InterpreterPushArgs(masm, ecx, ebx); | |
746 | 748 |
747 // Call the target. | 749 // Call the target. |
748 __ Push(edx); // Re-push return address. | 750 __ Push(edx); // Re-push return address. |
749 | 751 |
750 if (function_type == CallableType::kJSFunction) { | 752 if (function_type == CallableType::kJSFunction) { |
751 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 753 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |
752 tail_call_mode), | 754 tail_call_mode), |
753 RelocInfo::CODE_TARGET); | 755 RelocInfo::CODE_TARGET); |
754 } else { | 756 } else { |
755 DCHECK_EQ(function_type, CallableType::kAny); | 757 DCHECK_EQ(function_type, CallableType::kAny); |
756 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 758 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
757 tail_call_mode), | 759 tail_call_mode), |
758 RelocInfo::CODE_TARGET); | 760 RelocInfo::CODE_TARGET); |
759 } | 761 } |
760 } | 762 } |
761 | 763 |
762 // static | 764 // static |
763 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 765 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( |
766 MacroAssembler* masm, CallableType construct_type) { | |
764 // ----------- S t a t e ------------- | 767 // ----------- S t a t e ------------- |
765 // -- eax : the number of arguments (not including the receiver) | 768 // -- eax : the number of arguments (not including the receiver) |
766 // -- edx : the new target | 769 // -- edx : the new target |
767 // -- edi : the constructor | 770 // -- edi : the constructor |
768 // -- ebx : the address of the first argument to be pushed. Subsequent | 771 // -- ebx : allocation site feedback (if available or undefined) |
772 // -- ecx : the address of the first argument to be pushed. Subsequent | |
769 // arguments should be consecutive above this, in the same order as | 773 // arguments should be consecutive above this, in the same order as |
770 // they are to be pushed onto the stack. | 774 // they are to be pushed onto the stack. |
771 // ----------------------------------- | 775 // ----------------------------------- |
772 | 776 |
773 // Pop return address to allow tail-call after pushing arguments. | 777 // Store edi, edx onto the stack. We need two extra registers |
774 __ Pop(ecx); | 778 // so store edi, edx temporarily on stack. |
779 __ Push(edi); | |
780 __ Push(edx); | |
775 | 781 |
776 // Push edi in the slot meant for receiver. We need an extra register | 782 // We have to pop return address and the two temporary registers before we |
777 // so store edi temporarily on stack. | 783 // can push arguments onto the stack. we do not have any free registers so |
778 __ Push(edi); | 784 // update the stack and copy them into the correct places on the stack. |
785 // current stack =====> required stack layout | |
786 // | | | edx | (2) <-- esp(1) | |
787 // | | | edi | (3) | |
788 // | | | return addr | (4) | |
789 // | | | arg N | (5) | |
790 // | edx | <-- esp | .... | | |
791 // | edi | | arg 0 | | |
792 // | return addr | | receiver slot | | |
779 | 793 |
780 // Find the address of the last argument. | 794 // First increment the stack pointer to the correct location. |
781 __ mov(edi, eax); | 795 // we need additional slots for arguments and the receiver. |
782 __ neg(edi); | 796 // Step 1 - compute the required increment to the stack. |
783 __ shl(edi, kPointerSizeLog2); | 797 __ mov(edx, eax); |
784 __ add(edi, ebx); | 798 __ shl(edx, kPointerSizeLog2); |
799 __ add(edx, Immediate(kPointerSize)); | |
785 | 800 |
786 Generate_InterpreterPushArgs(masm, edi); | 801 #ifdef _MSC_VER |
802 // TODO(mythria): Move it to macro assembler. | |
803 // 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 | |
805 // page. Check this: | |
806 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. | |
807 const int page_size = 4 * 1024; | |
808 Label check_offset, update_stack_pointer; | |
809 __ bind(&check_offset); | |
810 __ cmp(edx, page_size); | |
811 __ j(less, &update_stack_pointer); | |
812 __ sub(esp, Immediate(page_size)); | |
813 // Just to touch the page, before we increment further. | |
814 __ mov(Operand(esp, 0), Immediate(0)); | |
815 __ sub(edx, Immediate(page_size)); | |
816 __ jmp(&check_offset); | |
817 __ bind(&update_stack_pointer); | |
818 #endif | |
787 | 819 |
788 // Restore the constructor from slot on stack. It was pushed at the slot | 820 // TODO(mythria): Add a stack check before updating the stack pointer. |
789 // meant for receiver. | |
790 __ mov(edi, Operand(esp, eax, times_pointer_size, 0)); | |
791 | 821 |
792 // Re-push return address. | 822 // Step 1 - Update the stack pointer. |
793 __ Push(ecx); | 823 __ sub(esp, edx); |
794 | 824 |
795 // Call the constructor with unmodified eax, edi, ebi values. | 825 // Step 2 move edx to the correct location. Move edx first otherwise |
796 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 826 // we may overwrite when eax = 0 or 1, basically when the source and |
827 // destination overlap. We at least need one extra slot for receiver, | |
828 // so no extra checks are required to avoid copy. | |
829 __ mov(edi, Operand(esp, eax, times_pointer_size, 1 * kPointerSize)); | |
830 __ mov(Operand(esp, 0), edi); | |
831 | |
832 // Step 3 move edi to the correct location | |
833 __ mov(edi, Operand(esp, eax, times_pointer_size, 2 * kPointerSize)); | |
834 __ mov(Operand(esp, 1 * kPointerSize), edi); | |
835 | |
836 // Step 4 move return address to the correct location | |
837 __ mov(edi, Operand(esp, eax, times_pointer_size, 3 * kPointerSize)); | |
838 __ mov(Operand(esp, 2 * kPointerSize), edi); | |
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)); | |
mythria
2016/09/01 08:42:24
This is the only change on the top of the earlier
| |
843 | |
844 // Step 5 copy arguments to correct locations. | |
845 __ mov(edx, eax); | |
846 | |
847 Label loop_header, loop_check; | |
848 __ jmp(&loop_check); | |
849 __ bind(&loop_header); | |
850 __ mov(edi, Operand(ecx, 0)); | |
851 __ mov(Operand(esp, edx, times_pointer_size, 2 * kPointerSize), edi); | |
852 __ sub(ecx, Immediate(kPointerSize)); | |
853 __ sub(edx, Immediate(1)); | |
854 __ bind(&loop_check); | |
855 __ cmp(edx, Immediate(0)); | |
856 __ j(greater, &loop_header, Label::kNear); | |
857 | |
858 // Restore edi and edx. | |
859 __ Pop(edx); | |
860 __ Pop(edi); | |
861 | |
862 __ AssertUndefinedOrAllocationSite(ebx); | |
863 if (construct_type == CallableType::kJSFunction) { | |
864 // Tail call to the function-specific construct stub (still in the caller | |
865 // context at this point). | |
866 __ AssertFunction(edi); | |
867 | |
868 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
869 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | |
870 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
871 __ jmp(ecx); | |
872 } else { | |
873 DCHECK_EQ(construct_type, CallableType::kAny); | |
874 | |
875 // Call the constructor with unmodified eax, edi, edx values. | |
876 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
877 } | |
797 } | 878 } |
798 | 879 |
799 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | 880 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
800 // Set the return address to the correct point in the interpreter entry | 881 // Set the return address to the correct point in the interpreter entry |
801 // trampoline. | 882 // trampoline. |
802 Smi* interpreter_entry_return_pc_offset( | 883 Smi* interpreter_entry_return_pc_offset( |
803 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); | 884 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); |
804 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); | 885 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); |
805 __ LoadHeapObject(ebx, | 886 __ LoadHeapObject(ebx, |
806 masm->isolate()->builtins()->InterpreterEntryTrampoline()); | 887 masm->isolate()->builtins()->InterpreterEntryTrampoline()); |
(...skipping 2233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3040 | 3121 |
3041 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { | 3122 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { |
3042 Generate_OnStackReplacementHelper(masm, true); | 3123 Generate_OnStackReplacementHelper(masm, true); |
3043 } | 3124 } |
3044 | 3125 |
3045 #undef __ | 3126 #undef __ |
3046 } // namespace internal | 3127 } // namespace internal |
3047 } // namespace v8 | 3128 } // namespace v8 |
3048 | 3129 |
3049 #endif // V8_TARGET_ARCH_IA32 | 3130 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |