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 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 __ push(edi); | 695 __ push(edi); |
696 __ CallRuntime(Runtime::kCompileBaseline); | 696 __ CallRuntime(Runtime::kCompileBaseline); |
697 | 697 |
698 // Restore return value. | 698 // Restore return value. |
699 __ pop(eax); | 699 __ pop(eax); |
700 } | 700 } |
701 __ ret(0); | 701 __ ret(0); |
702 } | 702 } |
703 | 703 |
704 static void Generate_InterpreterPushArgs(MacroAssembler* masm, | 704 static void Generate_InterpreterPushArgs(MacroAssembler* masm, |
705 Register array_limit) { | 705 Register array_limit, |
706 Register start_address) { | |
706 // ----------- S t a t e ------------- | 707 // ----------- S t a t e ------------- |
707 // -- ebx : Pointer to the last argument in the args array. | 708 // -- start_address : Pointer to the last argument in the args array. |
708 // -- array_limit : Pointer to one before the first argument in the | 709 // -- array_limit : Pointer to one before the first argument in the |
709 // args array. | 710 // args array. |
710 // ----------------------------------- | 711 // ----------------------------------- |
711 Label loop_header, loop_check; | 712 Label loop_header, loop_check; |
712 __ jmp(&loop_check); | 713 __ jmp(&loop_check); |
713 __ bind(&loop_header); | 714 __ bind(&loop_header); |
714 __ Push(Operand(ebx, 0)); | 715 __ Push(Operand(start_address, 0)); |
715 __ sub(ebx, Immediate(kPointerSize)); | 716 __ sub(start_address, Immediate(kPointerSize)); |
716 __ bind(&loop_check); | 717 __ bind(&loop_check); |
717 __ cmp(ebx, array_limit); | 718 __ cmp(start_address, array_limit); |
718 __ j(greater, &loop_header, Label::kNear); | 719 __ j(greater, &loop_header, Label::kNear); |
719 } | 720 } |
720 | 721 |
721 // static | 722 // static |
722 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 723 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
723 MacroAssembler* masm, TailCallMode tail_call_mode, | 724 MacroAssembler* masm, TailCallMode tail_call_mode, |
724 CallableType function_type) { | 725 CallableType function_type) { |
725 // ----------- S t a t e ------------- | 726 // ----------- S t a t e ------------- |
726 // -- eax : the number of arguments (not including the receiver) | 727 // -- eax : the number of arguments (not including the receiver) |
727 // -- ebx : the address of the first argument to be pushed. Subsequent | 728 // -- ebx : the address of the first argument to be pushed. Subsequent |
728 // arguments should be consecutive above this, in the same order as | 729 // arguments should be consecutive above this, in the same order as |
729 // they are to be pushed onto the stack. | 730 // they are to be pushed onto the stack. |
730 // -- edi : the target to call (can be any Object). | 731 // -- edi : the target to call (can be any Object). |
731 // ----------------------------------- | 732 // ----------------------------------- |
732 | 733 |
733 // Pop return address to allow tail-call after pushing arguments. | 734 // Pop return address to allow tail-call after pushing arguments. |
734 __ Pop(edx); | 735 __ Pop(edx); |
735 | 736 |
736 // Find the address of the last argument. | 737 // Find the address of the last argument. |
737 __ mov(ecx, eax); | 738 __ mov(ecx, eax); |
738 __ add(ecx, Immediate(1)); // Add one for receiver. | 739 __ add(ecx, Immediate(1)); // Add one for receiver. |
739 __ shl(ecx, kPointerSizeLog2); | 740 __ shl(ecx, kPointerSizeLog2); |
740 __ neg(ecx); | 741 __ neg(ecx); |
741 __ add(ecx, ebx); | 742 __ add(ecx, ebx); |
742 | 743 |
743 Generate_InterpreterPushArgs(masm, ecx); | 744 // TODO(mythria): Add a stack check before pushing the arguments. |
rmcilroy
2016/08/03 13:14:19
We should do this on all architectures (I'm sure y
mythria
2016/08/04 07:06:10
Yes, I was lazy to add TODO on all architectures.
| |
745 Generate_InterpreterPushArgs(masm, ecx, ebx); | |
744 | 746 |
745 // Call the target. | 747 // Call the target. |
746 __ Push(edx); // Re-push return address. | 748 __ Push(edx); // Re-push return address. |
747 | 749 |
748 if (function_type == CallableType::kJSFunction) { | 750 if (function_type == CallableType::kJSFunction) { |
749 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 751 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |
750 tail_call_mode), | 752 tail_call_mode), |
751 RelocInfo::CODE_TARGET); | 753 RelocInfo::CODE_TARGET); |
752 } else { | 754 } else { |
753 DCHECK_EQ(function_type, CallableType::kAny); | 755 DCHECK_EQ(function_type, CallableType::kAny); |
754 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 756 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
755 tail_call_mode), | 757 tail_call_mode), |
756 RelocInfo::CODE_TARGET); | 758 RelocInfo::CODE_TARGET); |
757 } | 759 } |
758 } | 760 } |
759 | 761 |
760 // static | 762 // static |
761 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 763 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( |
764 MacroAssembler* masm, CallableType construct_type) { | |
762 // ----------- S t a t e ------------- | 765 // ----------- S t a t e ------------- |
763 // -- eax : the number of arguments (not including the receiver) | 766 // -- eax : the number of arguments (not including the receiver) |
764 // -- edx : the new target | 767 // -- edx : the new target |
765 // -- edi : the constructor | 768 // -- edi : the constructor |
766 // -- ebx : the address of the first argument to be pushed. Subsequent | 769 // -- ebx : allocation site feedback (if available or undefined) |
770 // -- ecx : the address of the first argument to be pushed. Subsequent | |
767 // arguments should be consecutive above this, in the same order as | 771 // arguments should be consecutive above this, in the same order as |
768 // they are to be pushed onto the stack. | 772 // they are to be pushed onto the stack. |
769 // ----------------------------------- | 773 // ----------------------------------- |
770 | 774 |
771 // Pop return address to allow tail-call after pushing arguments. | 775 // Store edi, edx onto the stack. We need two extra registers |
772 __ Pop(ecx); | 776 // so store edi, edx temporarily on stack. |
777 __ Push(edi); | |
778 __ Push(edx); | |
773 | 779 |
774 // Push edi in the slot meant for receiver. We need an extra register | 780 // We have to pop return address and the two temporary registers before we |
775 // so store edi temporarily on stack. | 781 // can push arguments onto the stack. we do not have any free registers so |
776 __ Push(edi); | 782 // update the stack and copy them into the correct places on the stack. |
783 // current stack =====> required stack layout | |
784 // | | | edx | (2) <-- esp(1) | |
785 // | | | edi | (3) | |
786 // | | | return addr | (4) | |
787 // | | | arg N | (5) | |
788 // | edx | <-- esp | .... | | |
789 // | edi | | arg 0 | | |
790 // | return addr | | receiver slot | | |
777 | 791 |
778 // Find the address of the last argument. | 792 // First increment the stack pointer to the correct location. |
779 __ mov(edi, eax); | 793 // we need additional slots for arguments and the receiver. |
780 __ neg(edi); | 794 // Step 1 - compute the required increment to the stack. |
781 __ shl(edi, kPointerSizeLog2); | 795 __ mov(edx, eax); |
782 __ add(edi, ebx); | 796 __ shl(edx, kPointerSizeLog2); |
797 __ add(edx, Immediate(kPointerSize)); | |
783 | 798 |
784 Generate_InterpreterPushArgs(masm, edi); | 799 #ifdef _MSC_VER |
800 // TODO(mythria): Move it to macro assembler. | |
801 // In windows, we cannot increment the stack size by more than one page | |
802 // (mimimum page size is 4KB) without accessing atleast one byte on the | |
rmcilroy
2016/08/03 13:14:19
atleast/at least
mythria
2016/08/04 07:06:10
Done.
| |
803 // page. Check this: | |
804 // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. | |
805 const int page_size = 4 * 1024; | |
806 Label check_offset, update_stack_pointer; | |
807 __ bind(&check_offset); | |
808 __ cmp(edx, page_size); | |
809 __ j(less, &update_stack_pointer); | |
810 __ sub(esp, Immediate(page_size)); | |
811 // Just to touch the page, before we increment further. | |
812 __ mov(Operand(esp, 0), Immediate(0)); | |
813 __ sub(edx, Immediate(page_size)); | |
814 __ jmp(&check_offset); | |
815 __ bind(&update_stack_pointer); | |
816 #endif | |
785 | 817 |
786 // Restore the constructor from slot on stack. It was pushed at the slot | 818 // TODO(mythria): Add a stack check before updating the stack pointer. |
787 // meant for receiver. | 819 // Step 1 - Update the stack pointer. |
rmcilroy
2016/08/03 13:14:19
nit - newline above
| |
788 __ mov(edi, Operand(esp, eax, times_pointer_size, 0)); | 820 __ sub(esp, edx); |
789 | 821 |
790 // Re-push return address. | 822 // Step 2 move edx to the correct location. Move edx first otherwise |
791 __ Push(ecx); | 823 // we may overwrite when eax = 0 or 1, basically when the source and |
824 // destination overlap. We atleast need one extra slot for receiver, | |
rmcilroy
2016/08/03 13:14:19
/s/atleast/at least
mythria
2016/08/04 07:06:10
Done.
| |
825 // so no extra checks are required to avoid copy. | |
826 __ mov(edi, Operand(esp, eax, times_pointer_size, 1 * kPointerSize)); | |
827 __ mov(Operand(esp, 0), edi); | |
792 | 828 |
793 // Call the constructor with unmodified eax, edi, ebi values. | 829 // Step 3 move edi to the correct location |
794 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 830 __ mov(edi, Operand(esp, eax, times_pointer_size, 2 * kPointerSize)); |
831 __ mov(Operand(esp, 1 * kPointerSize), edi); | |
832 | |
833 // Step 4 move return address to the correct location | |
834 __ mov(edi, Operand(esp, eax, times_pointer_size, 3 * kPointerSize)); | |
835 __ mov(Operand(esp, 2 * kPointerSize), edi); | |
836 | |
837 // Step 5 copy arguments to correct locations. | |
838 __ mov(edx, eax); | |
839 | |
840 Label loop_header, loop_check; | |
841 __ jmp(&loop_check); | |
842 __ bind(&loop_header); | |
843 __ mov(edi, Operand(ecx, 0)); | |
844 __ mov(Operand(esp, edx, times_pointer_size, 2 * kPointerSize), edi); | |
845 __ sub(ecx, Immediate(kPointerSize)); | |
846 __ sub(edx, Immediate(1)); | |
847 __ bind(&loop_check); | |
848 __ cmp(edx, Immediate(0)); | |
849 __ j(greater, &loop_header, Label::kNear); | |
rmcilroy
2016/08/03 13:14:19
Can we do this with Generate_InterpreterPushArgs i
mythria
2016/08/04 07:06:10
InterpreterPushArgs pushes the arguments onto stac
| |
850 | |
851 // Restore edi and edx. | |
852 __ Pop(edx); | |
853 __ Pop(edi); | |
854 | |
855 __ AssertUndefinedOrAllocationSite(ebx); | |
856 if (construct_type == CallableType::kJSFunction) { | |
857 // Tail call to the function-specific construct stub (still in the caller | |
858 // context at this point). | |
859 __ AssertFunction(edi); | |
860 | |
861 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
862 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | |
863 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
864 __ jmp(ecx); | |
865 } else { | |
866 DCHECK_EQ(construct_type, CallableType::kAny); | |
867 | |
868 // Call the constructor with unmodified eax, edi, edx values. | |
869 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
870 } | |
795 } | 871 } |
796 | 872 |
797 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | 873 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
798 // Set the return address to the correct point in the interpreter entry | 874 // Set the return address to the correct point in the interpreter entry |
799 // trampoline. | 875 // trampoline. |
800 Smi* interpreter_entry_return_pc_offset( | 876 Smi* interpreter_entry_return_pc_offset( |
801 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); | 877 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); |
802 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); | 878 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); |
803 __ LoadHeapObject(ebx, | 879 __ LoadHeapObject(ebx, |
804 masm->isolate()->builtins()->InterpreterEntryTrampoline()); | 880 masm->isolate()->builtins()->InterpreterEntryTrampoline()); |
(...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3024 | 3100 |
3025 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { | 3101 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { |
3026 Generate_OnStackReplacementHelper(masm, true); | 3102 Generate_OnStackReplacementHelper(masm, true); |
3027 } | 3103 } |
3028 | 3104 |
3029 #undef __ | 3105 #undef __ |
3030 } // namespace internal | 3106 } // namespace internal |
3031 } // namespace v8 | 3107 } // namespace v8 |
3032 | 3108 |
3033 #endif // V8_TARGET_ARCH_IA32 | 3109 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |