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