| 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_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 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 __ Move( | 692 __ Move( |
| 693 kInterpreterDispatchTableRegister, | 693 kInterpreterDispatchTableRegister, |
| 694 ExternalReference::interpreter_dispatch_table_address(masm->isolate())); | 694 ExternalReference::interpreter_dispatch_table_address(masm->isolate())); |
| 695 | 695 |
| 696 // Dispatch to the first bytecode handler for the function. | 696 // Dispatch to the first bytecode handler for the function. |
| 697 __ movzxbp(rbx, Operand(kInterpreterBytecodeArrayRegister, | 697 __ movzxbp(rbx, Operand(kInterpreterBytecodeArrayRegister, |
| 698 kInterpreterBytecodeOffsetRegister, times_1, 0)); | 698 kInterpreterBytecodeOffsetRegister, times_1, 0)); |
| 699 __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx, | 699 __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx, |
| 700 times_pointer_size, 0)); | 700 times_pointer_size, 0)); |
| 701 __ call(rbx); | 701 __ call(rbx); |
| 702 masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); |
| 702 | 703 |
| 703 // Even though the first bytecode handler was called, we will never return. | 704 // The return value is in rax. |
| 704 __ Abort(kUnexpectedReturnFromBytecodeHandler); | 705 |
| 706 // Get the arguments + reciever count. |
| 707 __ movp(rbx, Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 708 __ movl(rbx, FieldOperand(rbx, BytecodeArray::kParameterSizeOffset)); |
| 709 |
| 710 // Leave the frame (also dropping the register file). |
| 711 __ leave(); |
| 712 |
| 713 // Drop receiver + arguments and return. |
| 714 __ PopReturnAddressTo(rcx); |
| 715 __ addp(rsp, rbx); |
| 716 __ PushReturnAddressFrom(rcx); |
| 717 __ ret(0); |
| 705 | 718 |
| 706 // Load debug copy of the bytecode array. | 719 // Load debug copy of the bytecode array. |
| 707 __ bind(&load_debug_bytecode_array); | 720 __ bind(&load_debug_bytecode_array); |
| 708 Register debug_info = kInterpreterBytecodeArrayRegister; | 721 Register debug_info = kInterpreterBytecodeArrayRegister; |
| 709 __ movp(debug_info, FieldOperand(rax, SharedFunctionInfo::kDebugInfoOffset)); | 722 __ movp(debug_info, FieldOperand(rax, SharedFunctionInfo::kDebugInfoOffset)); |
| 710 __ movp(kInterpreterBytecodeArrayRegister, | 723 __ movp(kInterpreterBytecodeArrayRegister, |
| 711 FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex)); | 724 FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex)); |
| 712 __ jmp(&bytecode_array_loaded); | 725 __ jmp(&bytecode_array_loaded); |
| 713 | 726 |
| 714 // If the bytecode array is no longer present, then the underlying function | 727 // If the bytecode array is no longer present, then the underlying function |
| 715 // has been switched to a different kind of code and we heal the closure by | 728 // has been switched to a different kind of code and we heal the closure by |
| 716 // switching the code entry field over to the new code object as well. | 729 // switching the code entry field over to the new code object as well. |
| 717 __ bind(&bytecode_array_not_present); | 730 __ bind(&bytecode_array_not_present); |
| 718 __ leave(); // Leave the frame so we can tail call. | 731 __ leave(); // Leave the frame so we can tail call. |
| 719 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 732 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 720 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset)); | 733 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset)); |
| 721 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | 734 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
| 722 __ movp(FieldOperand(rdi, JSFunction::kCodeEntryOffset), rcx); | 735 __ movp(FieldOperand(rdi, JSFunction::kCodeEntryOffset), rcx); |
| 723 __ RecordWriteCodeEntryField(rdi, rcx, r15); | 736 __ RecordWriteCodeEntryField(rdi, rcx, r15); |
| 724 __ jmp(rcx); | 737 __ jmp(rcx); |
| 725 } | 738 } |
| 726 | 739 |
| 727 | |
| 728 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { | |
| 729 // The return value is in accumulator, which is already in rax. | |
| 730 | |
| 731 // Leave the frame (also dropping the register file). | |
| 732 __ leave(); | |
| 733 | |
| 734 // Drop receiver + arguments and return. | |
| 735 __ movl(rbx, FieldOperand(kInterpreterBytecodeArrayRegister, | |
| 736 BytecodeArray::kParameterSizeOffset)); | |
| 737 __ PopReturnAddressTo(rcx); | |
| 738 __ addp(rsp, rbx); | |
| 739 __ PushReturnAddressFrom(rcx); | |
| 740 __ ret(0); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 static void Generate_InterpreterPushArgs(MacroAssembler* masm, | 740 static void Generate_InterpreterPushArgs(MacroAssembler* masm, |
| 745 bool push_receiver) { | 741 bool push_receiver) { |
| 746 // ----------- S t a t e ------------- | 742 // ----------- S t a t e ------------- |
| 747 // -- rax : the number of arguments (not including the receiver) | 743 // -- rax : the number of arguments (not including the receiver) |
| 748 // -- rbx : the address of the first argument to be pushed. Subsequent | 744 // -- rbx : the address of the first argument to be pushed. Subsequent |
| 749 // arguments should be consecutive above this, in the same order as | 745 // arguments should be consecutive above this, in the same order as |
| 750 // they are to be pushed onto the stack. | 746 // they are to be pushed onto the stack. |
| 751 // ----------------------------------- | 747 // ----------------------------------- |
| 752 | 748 |
| 753 // Find the address of the last argument. | 749 // Find the address of the last argument. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 764 Label loop_header, loop_check; | 760 Label loop_header, loop_check; |
| 765 __ j(always, &loop_check); | 761 __ j(always, &loop_check); |
| 766 __ bind(&loop_header); | 762 __ bind(&loop_header); |
| 767 __ Push(Operand(rbx, 0)); | 763 __ Push(Operand(rbx, 0)); |
| 768 __ subp(rbx, Immediate(kPointerSize)); | 764 __ subp(rbx, Immediate(kPointerSize)); |
| 769 __ bind(&loop_check); | 765 __ bind(&loop_check); |
| 770 __ cmpp(rbx, rcx); | 766 __ cmpp(rbx, rcx); |
| 771 __ j(greater, &loop_header, Label::kNear); | 767 __ j(greater, &loop_header, Label::kNear); |
| 772 } | 768 } |
| 773 | 769 |
| 774 | |
| 775 // static | 770 // static |
| 776 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 771 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 777 MacroAssembler* masm, TailCallMode tail_call_mode) { | 772 MacroAssembler* masm, TailCallMode tail_call_mode) { |
| 778 // ----------- S t a t e ------------- | 773 // ----------- S t a t e ------------- |
| 779 // -- rax : the number of arguments (not including the receiver) | 774 // -- rax : the number of arguments (not including the receiver) |
| 780 // -- rbx : the address of the first argument to be pushed. Subsequent | 775 // -- rbx : the address of the first argument to be pushed. Subsequent |
| 781 // arguments should be consecutive above this, in the same order as | 776 // arguments should be consecutive above this, in the same order as |
| 782 // they are to be pushed onto the stack. | 777 // they are to be pushed onto the stack. |
| 783 // -- rdi : the target to call (can be any Object). | 778 // -- rdi : the target to call (can be any Object). |
| 784 // ----------------------------------- | 779 // ----------------------------------- |
| 785 | 780 |
| 786 // Pop return address to allow tail-call after pushing arguments. | 781 // Pop return address to allow tail-call after pushing arguments. |
| 787 __ PopReturnAddressTo(kScratchRegister); | 782 __ PopReturnAddressTo(kScratchRegister); |
| 788 | 783 |
| 789 Generate_InterpreterPushArgs(masm, true); | 784 Generate_InterpreterPushArgs(masm, true); |
| 790 | 785 |
| 791 // Call the target. | 786 // Call the target. |
| 792 __ PushReturnAddressFrom(kScratchRegister); // Re-push return address. | 787 __ PushReturnAddressFrom(kScratchRegister); // Re-push return address. |
| 793 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 788 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 794 tail_call_mode), | 789 tail_call_mode), |
| 795 RelocInfo::CODE_TARGET); | 790 RelocInfo::CODE_TARGET); |
| 796 } | 791 } |
| 797 | 792 |
| 798 | |
| 799 // static | 793 // static |
| 800 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 794 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { |
| 801 // ----------- S t a t e ------------- | 795 // ----------- S t a t e ------------- |
| 802 // -- rax : the number of arguments (not including the receiver) | 796 // -- rax : the number of arguments (not including the receiver) |
| 803 // -- rdx : the new target (either the same as the constructor or | 797 // -- rdx : the new target (either the same as the constructor or |
| 804 // the JSFunction on which new was invoked initially) | 798 // the JSFunction on which new was invoked initially) |
| 805 // -- rdi : the constructor to call (can be any Object) | 799 // -- rdi : the constructor to call (can be any Object) |
| 806 // -- rbx : the address of the first argument to be pushed. Subsequent | 800 // -- rbx : the address of the first argument to be pushed. Subsequent |
| 807 // arguments should be consecutive above this, in the same order as | 801 // arguments should be consecutive above this, in the same order as |
| 808 // they are to be pushed onto the stack. | 802 // they are to be pushed onto the stack. |
| 809 // ----------------------------------- | 803 // ----------------------------------- |
| 810 | 804 |
| 811 // Pop return address to allow tail-call after pushing arguments. | 805 // Pop return address to allow tail-call after pushing arguments. |
| 812 __ PopReturnAddressTo(kScratchRegister); | 806 __ PopReturnAddressTo(kScratchRegister); |
| 813 | 807 |
| 814 // Push slot for the receiver to be constructed. | 808 // Push slot for the receiver to be constructed. |
| 815 __ Push(Immediate(0)); | 809 __ Push(Immediate(0)); |
| 816 | 810 |
| 817 Generate_InterpreterPushArgs(masm, false); | 811 Generate_InterpreterPushArgs(masm, false); |
| 818 | 812 |
| 819 // Push return address in preparation for the tail-call. | 813 // Push return address in preparation for the tail-call. |
| 820 __ PushReturnAddressFrom(kScratchRegister); | 814 __ PushReturnAddressFrom(kScratchRegister); |
| 821 | 815 |
| 822 // Call the constructor (rax, rdx, rdi passed on). | 816 // Call the constructor (rax, rdx, rdi passed on). |
| 823 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 817 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 824 } | 818 } |
| 825 | 819 |
| 820 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
| 821 // Set the return address to the correct point in the interpreter entry |
| 822 // trampoline. |
| 823 Smi* interpreter_entry_return_pc_offset( |
| 824 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); |
| 825 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); |
| 826 __ Move(rbx, masm->isolate()->builtins()->InterpreterEntryTrampoline()); |
| 827 __ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() + |
| 828 Code::kHeaderSize - kHeapObjectTag)); |
| 829 __ Push(rbx); |
| 826 | 830 |
| 827 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { | |
| 828 // Initialize dispatch table register. | 831 // Initialize dispatch table register. |
| 829 __ Move( | 832 __ Move( |
| 830 kInterpreterDispatchTableRegister, | 833 kInterpreterDispatchTableRegister, |
| 831 ExternalReference::interpreter_dispatch_table_address(masm->isolate())); | 834 ExternalReference::interpreter_dispatch_table_address(masm->isolate())); |
| 832 | 835 |
| 833 // Get the bytecode array pointer from the frame. | 836 // Get the bytecode array pointer from the frame. |
| 834 __ movp(kInterpreterBytecodeArrayRegister, | 837 __ movp(kInterpreterBytecodeArrayRegister, |
| 835 Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 838 Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 836 | 839 |
| 837 if (FLAG_debug_code) { | 840 if (FLAG_debug_code) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 849 kInterpreterBytecodeOffsetRegister); | 852 kInterpreterBytecodeOffsetRegister); |
| 850 | 853 |
| 851 // Dispatch to the target bytecode. | 854 // Dispatch to the target bytecode. |
| 852 __ movzxbp(rbx, Operand(kInterpreterBytecodeArrayRegister, | 855 __ movzxbp(rbx, Operand(kInterpreterBytecodeArrayRegister, |
| 853 kInterpreterBytecodeOffsetRegister, times_1, 0)); | 856 kInterpreterBytecodeOffsetRegister, times_1, 0)); |
| 854 __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx, | 857 __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx, |
| 855 times_pointer_size, 0)); | 858 times_pointer_size, 0)); |
| 856 __ jmp(rbx); | 859 __ jmp(rbx); |
| 857 } | 860 } |
| 858 | 861 |
| 859 | |
| 860 static void Generate_InterpreterNotifyDeoptimizedHelper( | |
| 861 MacroAssembler* masm, Deoptimizer::BailoutType type) { | |
| 862 // Enter an internal frame. | |
| 863 { | |
| 864 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 865 | |
| 866 // Pass the deoptimization type to the runtime system. | |
| 867 __ Push(Smi::FromInt(static_cast<int>(type))); | |
| 868 __ CallRuntime(Runtime::kNotifyDeoptimized); | |
| 869 // Tear down internal frame. | |
| 870 } | |
| 871 | |
| 872 // Drop state (we don't use these for interpreter deopts) and and pop the | |
| 873 // accumulator value into the accumulator register and push PC at top | |
| 874 // of stack (to simulate initial call to bytecode handler in interpreter entry | |
| 875 // trampoline). | |
| 876 __ Pop(rbx); | |
| 877 __ Drop(1); | |
| 878 __ Pop(kInterpreterAccumulatorRegister); | |
| 879 __ Push(rbx); | |
| 880 | |
| 881 // Enter the bytecode dispatch. | |
| 882 Generate_EnterBytecodeDispatch(masm); | |
| 883 } | |
| 884 | |
| 885 | |
| 886 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) { | |
| 887 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | |
| 888 } | |
| 889 | |
| 890 | |
| 891 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) { | |
| 892 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); | |
| 893 } | |
| 894 | |
| 895 | |
| 896 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) { | |
| 897 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | |
| 898 } | |
| 899 | |
| 900 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | |
| 901 // Set the address of the interpreter entry trampoline as a return address. | |
| 902 // This simulates the initial call to bytecode handlers in interpreter entry | |
| 903 // trampoline. The return will never actually be taken, but our stack walker | |
| 904 // uses this address to determine whether a frame is interpreted. | |
| 905 __ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline()); | |
| 906 | |
| 907 Generate_EnterBytecodeDispatch(masm); | |
| 908 } | |
| 909 | |
| 910 | |
| 911 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 862 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
| 912 // ----------- S t a t e ------------- | 863 // ----------- S t a t e ------------- |
| 913 // -- rax : argument count (preserved for callee) | 864 // -- rax : argument count (preserved for callee) |
| 914 // -- rdx : new target (preserved for callee) | 865 // -- rdx : new target (preserved for callee) |
| 915 // -- rdi : target function (preserved for callee) | 866 // -- rdi : target function (preserved for callee) |
| 916 // ----------------------------------- | 867 // ----------------------------------- |
| 917 // First lookup code, maybe we don't need to compile! | 868 // First lookup code, maybe we don't need to compile! |
| 918 Label gotta_call_runtime; | 869 Label gotta_call_runtime; |
| 919 Label maybe_call_runtime; | 870 Label maybe_call_runtime; |
| 920 Label try_shared; | 871 Label try_shared; |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 | 1125 |
| 1175 __ CallRuntime(Runtime::kNotifyDeoptimized); | 1126 __ CallRuntime(Runtime::kNotifyDeoptimized); |
| 1176 // Tear down internal frame. | 1127 // Tear down internal frame. |
| 1177 } | 1128 } |
| 1178 | 1129 |
| 1179 // Get the full codegen state from the stack and untag it. | 1130 // Get the full codegen state from the stack and untag it. |
| 1180 __ SmiToInteger32(kScratchRegister, Operand(rsp, kPCOnStackSize)); | 1131 __ SmiToInteger32(kScratchRegister, Operand(rsp, kPCOnStackSize)); |
| 1181 | 1132 |
| 1182 // Switch on the state. | 1133 // Switch on the state. |
| 1183 Label not_no_registers, not_tos_rax; | 1134 Label not_no_registers, not_tos_rax; |
| 1184 __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::NO_REGISTERS)); | 1135 __ cmpp(kScratchRegister, |
| 1136 Immediate(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS))); |
| 1185 __ j(not_equal, ¬_no_registers, Label::kNear); | 1137 __ j(not_equal, ¬_no_registers, Label::kNear); |
| 1186 __ ret(1 * kPointerSize); // Remove state. | 1138 __ ret(1 * kPointerSize); // Remove state. |
| 1187 | 1139 |
| 1188 __ bind(¬_no_registers); | 1140 __ bind(¬_no_registers); |
| 1141 DCHECK_EQ(kInterpreterAccumulatorRegister.code(), rax.code()); |
| 1189 __ movp(rax, Operand(rsp, kPCOnStackSize + kPointerSize)); | 1142 __ movp(rax, Operand(rsp, kPCOnStackSize + kPointerSize)); |
| 1190 __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::TOS_REG)); | 1143 __ cmpp(kScratchRegister, |
| 1144 Immediate(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER))); |
| 1191 __ j(not_equal, ¬_tos_rax, Label::kNear); | 1145 __ j(not_equal, ¬_tos_rax, Label::kNear); |
| 1192 __ ret(2 * kPointerSize); // Remove state, rax. | 1146 __ ret(2 * kPointerSize); // Remove state, rax. |
| 1193 | 1147 |
| 1194 __ bind(¬_tos_rax); | 1148 __ bind(¬_tos_rax); |
| 1195 __ Abort(kNoCasesLeft); | 1149 __ Abort(kNoCasesLeft); |
| 1196 } | 1150 } |
| 1197 | 1151 |
| 1198 | 1152 |
| 1199 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { | 1153 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { |
| 1200 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | 1154 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| (...skipping 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2955 __ ret(0); | 2909 __ ret(0); |
| 2956 } | 2910 } |
| 2957 | 2911 |
| 2958 | 2912 |
| 2959 #undef __ | 2913 #undef __ |
| 2960 | 2914 |
| 2961 } // namespace internal | 2915 } // namespace internal |
| 2962 } // namespace v8 | 2916 } // namespace v8 |
| 2963 | 2917 |
| 2964 #endif // V8_TARGET_ARCH_X64 | 2918 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |