| 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_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 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 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 __ mov(kInterpreterDispatchTableRegister, | 614 __ mov(kInterpreterDispatchTableRegister, |
| 615 Immediate(ExternalReference::interpreter_dispatch_table_address( | 615 Immediate(ExternalReference::interpreter_dispatch_table_address( |
| 616 masm->isolate()))); | 616 masm->isolate()))); |
| 617 | 617 |
| 618 // Dispatch to the first bytecode handler for the function. | 618 // Dispatch to the first bytecode handler for the function. |
| 619 __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, | 619 __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, |
| 620 kInterpreterBytecodeOffsetRegister, times_1, 0)); | 620 kInterpreterBytecodeOffsetRegister, times_1, 0)); |
| 621 __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, | 621 __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, |
| 622 times_pointer_size, 0)); | 622 times_pointer_size, 0)); |
| 623 __ call(ebx); | 623 __ call(ebx); |
| 624 masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); |
| 624 | 625 |
| 625 // Even though the first bytecode handler was called, we will never return. | 626 // The return value is in eax. |
| 626 __ Abort(kUnexpectedReturnFromBytecodeHandler); | 627 |
| 628 // Get the arguments + reciever count. |
| 629 __ mov(ebx, Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 630 __ mov(ebx, FieldOperand(ebx, BytecodeArray::kParameterSizeOffset)); |
| 631 |
| 632 // Leave the frame (also dropping the register file). |
| 633 __ leave(); |
| 634 |
| 635 // Drop receiver + arguments and return. |
| 636 __ pop(ecx); |
| 637 __ add(esp, ebx); |
| 638 __ push(ecx); |
| 639 __ ret(0); |
| 627 | 640 |
| 628 // Load debug copy of the bytecode array. | 641 // Load debug copy of the bytecode array. |
| 629 __ bind(&load_debug_bytecode_array); | 642 __ bind(&load_debug_bytecode_array); |
| 630 Register debug_info = kInterpreterBytecodeArrayRegister; | 643 Register debug_info = kInterpreterBytecodeArrayRegister; |
| 631 __ mov(debug_info, FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset)); | 644 __ mov(debug_info, FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset)); |
| 632 __ mov(kInterpreterBytecodeArrayRegister, | 645 __ mov(kInterpreterBytecodeArrayRegister, |
| 633 FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex)); | 646 FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex)); |
| 634 __ jmp(&bytecode_array_loaded); | 647 __ jmp(&bytecode_array_loaded); |
| 635 | 648 |
| 636 // If the bytecode array is no longer present, then the underlying function | 649 // If the bytecode array is no longer present, then the underlying function |
| 637 // has been switched to a different kind of code and we heal the closure by | 650 // has been switched to a different kind of code and we heal the closure by |
| 638 // switching the code entry field over to the new code object as well. | 651 // switching the code entry field over to the new code object as well. |
| 639 __ bind(&bytecode_array_not_present); | 652 __ bind(&bytecode_array_not_present); |
| 640 __ pop(edx); // Callee's new target. | 653 __ pop(edx); // Callee's new target. |
| 641 __ pop(edi); // Callee's JS function. | 654 __ pop(edi); // Callee's JS function. |
| 642 __ pop(esi); // Callee's context. | 655 __ pop(esi); // Callee's context. |
| 643 __ leave(); // Leave the frame so we can tail call. | 656 __ leave(); // Leave the frame so we can tail call. |
| 644 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 657 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 645 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); | 658 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); |
| 646 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 659 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 647 __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx); | 660 __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx); |
| 648 __ RecordWriteCodeEntryField(edi, ecx, ebx); | 661 __ RecordWriteCodeEntryField(edi, ecx, ebx); |
| 649 __ jmp(ecx); | 662 __ jmp(ecx); |
| 650 } | 663 } |
| 651 | 664 |
| 652 | |
| 653 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { | |
| 654 // Interpreter handler is turbofanned code, need to reset the FPU before | |
| 655 // return | |
| 656 __ fninit(); | |
| 657 | |
| 658 // The return value is in accumulator, which is already in eax. | |
| 659 | |
| 660 // Leave the frame (also dropping the register file). | |
| 661 __ leave(); | |
| 662 | |
| 663 // Drop receiver + arguments and return. | |
| 664 __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister, | |
| 665 BytecodeArray::kParameterSizeOffset)); | |
| 666 __ pop(ecx); | |
| 667 __ add(esp, ebx); | |
| 668 __ push(ecx); | |
| 669 __ ret(0); | |
| 670 } | |
| 671 | |
| 672 | |
| 673 static void Generate_InterpreterPushArgs(MacroAssembler* masm, | 665 static void Generate_InterpreterPushArgs(MacroAssembler* masm, |
| 674 Register array_limit) { | 666 Register array_limit) { |
| 675 // ----------- S t a t e ------------- | 667 // ----------- S t a t e ------------- |
| 676 // -- ebx : Pointer to the last argument in the args array. | 668 // -- ebx : Pointer to the last argument in the args array. |
| 677 // -- array_limit : Pointer to one before the first argument in the | 669 // -- array_limit : Pointer to one before the first argument in the |
| 678 // args array. | 670 // args array. |
| 679 // ----------------------------------- | 671 // ----------------------------------- |
| 680 Label loop_header, loop_check; | 672 Label loop_header, loop_check; |
| 681 __ jmp(&loop_check); | 673 __ jmp(&loop_check); |
| 682 __ bind(&loop_header); | 674 __ bind(&loop_header); |
| 683 __ Push(Operand(ebx, 0)); | 675 __ Push(Operand(ebx, 0)); |
| 684 __ sub(ebx, Immediate(kPointerSize)); | 676 __ sub(ebx, Immediate(kPointerSize)); |
| 685 __ bind(&loop_check); | 677 __ bind(&loop_check); |
| 686 __ cmp(ebx, array_limit); | 678 __ cmp(ebx, array_limit); |
| 687 __ j(greater, &loop_header, Label::kNear); | 679 __ j(greater, &loop_header, Label::kNear); |
| 688 } | 680 } |
| 689 | 681 |
| 690 | |
| 691 // static | 682 // static |
| 692 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 683 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 693 MacroAssembler* masm, TailCallMode tail_call_mode) { | 684 MacroAssembler* masm, TailCallMode tail_call_mode) { |
| 694 // ----------- S t a t e ------------- | 685 // ----------- S t a t e ------------- |
| 695 // -- eax : the number of arguments (not including the receiver) | 686 // -- eax : the number of arguments (not including the receiver) |
| 696 // -- ebx : the address of the first argument to be pushed. Subsequent | 687 // -- ebx : the address of the first argument to be pushed. Subsequent |
| 697 // arguments should be consecutive above this, in the same order as | 688 // arguments should be consecutive above this, in the same order as |
| 698 // they are to be pushed onto the stack. | 689 // they are to be pushed onto the stack. |
| 699 // -- edi : the target to call (can be any Object). | 690 // -- edi : the target to call (can be any Object). |
| 700 // ----------------------------------- | 691 // ----------------------------------- |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 // meant for receiver. | 740 // meant for receiver. |
| 750 __ mov(edi, Operand(esp, eax, times_pointer_size, 0)); | 741 __ mov(edi, Operand(esp, eax, times_pointer_size, 0)); |
| 751 | 742 |
| 752 // Re-push return address. | 743 // Re-push return address. |
| 753 __ Push(ecx); | 744 __ Push(ecx); |
| 754 | 745 |
| 755 // Call the constructor with unmodified eax, edi, ebi values. | 746 // Call the constructor with unmodified eax, edi, ebi values. |
| 756 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 747 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 757 } | 748 } |
| 758 | 749 |
| 750 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
| 751 // Set the return address to the correct point in the interpreter entry |
| 752 // trampoline. |
| 753 Smi* interpreter_entry_return_pc_offset( |
| 754 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); |
| 755 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); |
| 756 __ LoadHeapObject(ebx, |
| 757 masm->isolate()->builtins()->InterpreterEntryTrampoline()); |
| 758 __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() + |
| 759 Code::kHeaderSize - kHeapObjectTag)); |
| 760 __ push(ebx); |
| 759 | 761 |
| 760 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { | |
| 761 // Initialize the dispatch table register. | 762 // Initialize the dispatch table register. |
| 762 __ mov(kInterpreterDispatchTableRegister, | 763 __ mov(kInterpreterDispatchTableRegister, |
| 763 Immediate(ExternalReference::interpreter_dispatch_table_address( | 764 Immediate(ExternalReference::interpreter_dispatch_table_address( |
| 764 masm->isolate()))); | 765 masm->isolate()))); |
| 765 | 766 |
| 766 // Get the bytecode array pointer from the frame. | 767 // Get the bytecode array pointer from the frame. |
| 767 __ mov(kInterpreterBytecodeArrayRegister, | 768 __ mov(kInterpreterBytecodeArrayRegister, |
| 768 Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 769 Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 769 | 770 |
| 770 if (FLAG_debug_code) { | 771 if (FLAG_debug_code) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 781 __ SmiUntag(kInterpreterBytecodeOffsetRegister); | 782 __ SmiUntag(kInterpreterBytecodeOffsetRegister); |
| 782 | 783 |
| 783 // Dispatch to the target bytecode. | 784 // Dispatch to the target bytecode. |
| 784 __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, | 785 __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, |
| 785 kInterpreterBytecodeOffsetRegister, times_1, 0)); | 786 kInterpreterBytecodeOffsetRegister, times_1, 0)); |
| 786 __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, | 787 __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, |
| 787 times_pointer_size, 0)); | 788 times_pointer_size, 0)); |
| 788 __ jmp(ebx); | 789 __ jmp(ebx); |
| 789 } | 790 } |
| 790 | 791 |
| 791 | |
| 792 static void Generate_InterpreterNotifyDeoptimizedHelper( | |
| 793 MacroAssembler* masm, Deoptimizer::BailoutType type) { | |
| 794 // Enter an internal frame. | |
| 795 { | |
| 796 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 797 | |
| 798 // Pass the deoptimization type to the runtime system. | |
| 799 __ Push(Smi::FromInt(static_cast<int>(type))); | |
| 800 __ CallRuntime(Runtime::kNotifyDeoptimized); | |
| 801 // Tear down internal frame. | |
| 802 } | |
| 803 | |
| 804 // Drop state (we don't use these for interpreter deopts) and and pop the | |
| 805 // accumulator value into the accumulator register and push PC at top | |
| 806 // of stack (to simulate initial call to bytecode handler in interpreter entry | |
| 807 // trampoline). | |
| 808 __ Pop(ebx); | |
| 809 __ Drop(1); | |
| 810 __ Pop(kInterpreterAccumulatorRegister); | |
| 811 __ Push(ebx); | |
| 812 | |
| 813 // Enter the bytecode dispatch. | |
| 814 Generate_EnterBytecodeDispatch(masm); | |
| 815 } | |
| 816 | |
| 817 | |
| 818 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) { | |
| 819 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | |
| 820 } | |
| 821 | |
| 822 | |
| 823 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) { | |
| 824 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); | |
| 825 } | |
| 826 | |
| 827 | |
| 828 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) { | |
| 829 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | |
| 830 } | |
| 831 | |
| 832 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | |
| 833 // Set the address of the interpreter entry trampoline as a return address. | |
| 834 // This simulates the initial call to bytecode handlers in interpreter entry | |
| 835 // trampoline. The return will never actually be taken, but our stack walker | |
| 836 // uses this address to determine whether a frame is interpreted. | |
| 837 __ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline()); | |
| 838 | |
| 839 Generate_EnterBytecodeDispatch(masm); | |
| 840 } | |
| 841 | |
| 842 | |
| 843 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 792 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
| 844 // ----------- S t a t e ------------- | 793 // ----------- S t a t e ------------- |
| 845 // -- eax : argument count (preserved for callee) | 794 // -- eax : argument count (preserved for callee) |
| 846 // -- edx : new target (preserved for callee) | 795 // -- edx : new target (preserved for callee) |
| 847 // -- edi : target function (preserved for callee) | 796 // -- edi : target function (preserved for callee) |
| 848 // ----------------------------------- | 797 // ----------------------------------- |
| 849 // First lookup code, maybe we don't need to compile! | 798 // First lookup code, maybe we don't need to compile! |
| 850 Label gotta_call_runtime, gotta_call_runtime_no_stack; | 799 Label gotta_call_runtime, gotta_call_runtime_no_stack; |
| 851 Label maybe_call_runtime; | 800 Label maybe_call_runtime; |
| 852 Label try_shared; | 801 Label try_shared; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 | 1078 |
| 1130 // Tear down internal frame. | 1079 // Tear down internal frame. |
| 1131 } | 1080 } |
| 1132 | 1081 |
| 1133 // Get the full codegen state from the stack and untag it. | 1082 // Get the full codegen state from the stack and untag it. |
| 1134 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 1083 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 1135 __ SmiUntag(ecx); | 1084 __ SmiUntag(ecx); |
| 1136 | 1085 |
| 1137 // Switch on the state. | 1086 // Switch on the state. |
| 1138 Label not_no_registers, not_tos_eax; | 1087 Label not_no_registers, not_tos_eax; |
| 1139 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); | 1088 __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)); |
| 1140 __ j(not_equal, ¬_no_registers, Label::kNear); | 1089 __ j(not_equal, ¬_no_registers, Label::kNear); |
| 1141 __ ret(1 * kPointerSize); // Remove state. | 1090 __ ret(1 * kPointerSize); // Remove state. |
| 1142 | 1091 |
| 1143 __ bind(¬_no_registers); | 1092 __ bind(¬_no_registers); |
| 1093 DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code()); |
| 1144 __ mov(eax, Operand(esp, 2 * kPointerSize)); | 1094 __ mov(eax, Operand(esp, 2 * kPointerSize)); |
| 1145 __ cmp(ecx, FullCodeGenerator::TOS_REG); | 1095 __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)); |
| 1146 __ j(not_equal, ¬_tos_eax, Label::kNear); | 1096 __ j(not_equal, ¬_tos_eax, Label::kNear); |
| 1147 __ ret(2 * kPointerSize); // Remove state, eax. | 1097 __ ret(2 * kPointerSize); // Remove state, eax. |
| 1148 | 1098 |
| 1149 __ bind(¬_tos_eax); | 1099 __ bind(¬_tos_eax); |
| 1150 __ Abort(kNoCasesLeft); | 1100 __ Abort(kNoCasesLeft); |
| 1151 } | 1101 } |
| 1152 | 1102 |
| 1153 | 1103 |
| 1154 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { | 1104 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { |
| 1155 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | 1105 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| (...skipping 1747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2903 // And "return" to the OSR entry point of the function. | 2853 // And "return" to the OSR entry point of the function. |
| 2904 __ ret(0); | 2854 __ ret(0); |
| 2905 } | 2855 } |
| 2906 | 2856 |
| 2907 | 2857 |
| 2908 #undef __ | 2858 #undef __ |
| 2909 } // namespace internal | 2859 } // namespace internal |
| 2910 } // namespace v8 | 2860 } // namespace v8 |
| 2911 | 2861 |
| 2912 #endif // V8_TARGET_ARCH_X87 | 2862 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |