OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 } else { \ | 721 } else { \ |
722 __ asm_instrx(value, operand); \ | 722 __ asm_instrx(value, operand); \ |
723 } \ | 723 } \ |
724 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ | 724 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ |
725 } while (0) | 725 } while (0) |
726 | 726 |
727 void CodeGenerator::AssembleDeconstructFrame() { | 727 void CodeGenerator::AssembleDeconstructFrame() { |
728 __ LeaveFrame(StackFrame::MANUAL); | 728 __ LeaveFrame(StackFrame::MANUAL); |
729 } | 729 } |
730 | 730 |
731 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 731 void CodeGenerator::AssemblePrepareTailCall() { |
732 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
733 if (sp_slot_delta > 0) { | |
734 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); | |
735 } | |
736 frame_access_state()->SetFrameAccessToDefault(); | |
737 } | |
738 | |
739 | |
740 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
741 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
742 if (sp_slot_delta < 0) { | |
743 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); | |
744 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
745 } | |
746 if (frame_access_state()->has_frame()) { | 732 if (frame_access_state()->has_frame()) { |
747 __ RestoreFrameStateForTailCall(); | 733 __ RestoreFrameStateForTailCall(); |
748 } | 734 } |
749 frame_access_state()->SetFrameAccessToSP(); | 735 frame_access_state()->SetFrameAccessToSP(); |
750 } | 736 } |
751 | 737 |
752 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 738 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
753 Register scratch1, | 739 Register scratch1, |
754 Register scratch2, | 740 Register scratch2, |
755 Register scratch3) { | 741 Register scratch3) { |
(...skipping 11 matching lines...) Expand all Loading... |
767 __ LoadP(caller_args_count_reg, | 753 __ LoadP(caller_args_count_reg, |
768 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 754 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
769 __ SmiUntag(caller_args_count_reg); | 755 __ SmiUntag(caller_args_count_reg); |
770 | 756 |
771 ParameterCount callee_args_count(args_reg); | 757 ParameterCount callee_args_count(args_reg); |
772 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 758 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
773 scratch3); | 759 scratch3); |
774 __ bind(&done); | 760 __ bind(&done); |
775 } | 761 } |
776 | 762 |
| 763 namespace { |
| 764 |
| 765 void FlushPendingPushRegisters(MacroAssembler* masm, |
| 766 FrameAccessState* frame_access_state, |
| 767 ZoneVector<Register>* pending_pushes) { |
| 768 switch (pending_pushes->size()) { |
| 769 case 0: |
| 770 break; |
| 771 case 1: |
| 772 masm->Push((*pending_pushes)[0]); |
| 773 break; |
| 774 case 2: |
| 775 masm->Push((*pending_pushes)[0], (*pending_pushes)[1]); |
| 776 break; |
| 777 case 3: |
| 778 masm->Push((*pending_pushes)[0], (*pending_pushes)[1], |
| 779 (*pending_pushes)[2]); |
| 780 break; |
| 781 default: |
| 782 UNREACHABLE(); |
| 783 break; |
| 784 } |
| 785 frame_access_state->IncreaseSPDelta(pending_pushes->size()); |
| 786 pending_pushes->resize(0); |
| 787 } |
| 788 |
| 789 void AddPendingPushRegister(MacroAssembler* masm, |
| 790 FrameAccessState* frame_access_state, |
| 791 ZoneVector<Register>* pending_pushes, |
| 792 Register reg) { |
| 793 pending_pushes->push_back(reg); |
| 794 if (pending_pushes->size() == 3 || reg.is(ip)) { |
| 795 FlushPendingPushRegisters(masm, frame_access_state, pending_pushes); |
| 796 } |
| 797 } |
| 798 |
| 799 void AdjustStackPointerForTailCall( |
| 800 MacroAssembler* masm, FrameAccessState* state, int new_slot_above_sp, |
| 801 ZoneVector<Register>* pending_pushes = nullptr, |
| 802 bool allow_shrinkage = true) { |
| 803 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 804 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 805 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 806 if (stack_slot_delta > 0) { |
| 807 if (pending_pushes != nullptr) { |
| 808 FlushPendingPushRegisters(masm, state, pending_pushes); |
| 809 } |
| 810 masm->Add(sp, sp, -stack_slot_delta * kPointerSize, r0); |
| 811 state->IncreaseSPDelta(stack_slot_delta); |
| 812 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 813 if (pending_pushes != nullptr) { |
| 814 FlushPendingPushRegisters(masm, state, pending_pushes); |
| 815 } |
| 816 masm->Add(sp, sp, -stack_slot_delta * kPointerSize, r0); |
| 817 state->IncreaseSPDelta(stack_slot_delta); |
| 818 } |
| 819 } |
| 820 |
| 821 } // namespace |
| 822 |
| 823 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr, |
| 824 int first_unused_stack_slot) { |
| 825 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush); |
| 826 ZoneVector<MoveOperands*> pushes(zone()); |
| 827 GetPushCompatibleMoves(instr, flags, &pushes); |
| 828 |
| 829 if (!pushes.empty() && |
| 830 (LocationOperand::cast(pushes.back()->destination()).index() + 1 == |
| 831 first_unused_stack_slot)) { |
| 832 PPCOperandConverter g(this, instr); |
| 833 ZoneVector<Register> pending_pushes(zone()); |
| 834 for (auto move : pushes) { |
| 835 LocationOperand destination_location( |
| 836 LocationOperand::cast(move->destination())); |
| 837 InstructionOperand source(move->source()); |
| 838 AdjustStackPointerForTailCall( |
| 839 masm(), frame_access_state(), |
| 840 destination_location.index() - pending_pushes.size(), |
| 841 &pending_pushes); |
| 842 if (source.IsStackSlot()) { |
| 843 LocationOperand source_location(LocationOperand::cast(source)); |
| 844 __ LoadP(ip, g.SlotToMemOperand(source_location.index())); |
| 845 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 846 ip); |
| 847 } else if (source.IsRegister()) { |
| 848 LocationOperand source_location(LocationOperand::cast(source)); |
| 849 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 850 source_location.GetRegister()); |
| 851 } else if (source.IsImmediate()) { |
| 852 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 853 ip); |
| 854 } else { |
| 855 // Pushes of non-scalar data types is not supported. |
| 856 UNIMPLEMENTED(); |
| 857 } |
| 858 move->Eliminate(); |
| 859 } |
| 860 FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes); |
| 861 } |
| 862 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 863 first_unused_stack_slot, nullptr, false); |
| 864 } |
| 865 |
| 866 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, |
| 867 int first_unused_stack_slot) { |
| 868 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 869 first_unused_stack_slot); |
| 870 } |
| 871 |
| 872 |
777 // Assembles an instruction after register allocation, producing machine code. | 873 // Assembles an instruction after register allocation, producing machine code. |
778 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 874 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
779 Instruction* instr) { | 875 Instruction* instr) { |
780 PPCOperandConverter i(this, instr); | 876 PPCOperandConverter i(this, instr); |
781 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); | 877 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); |
782 | 878 |
783 switch (opcode) { | 879 switch (opcode) { |
784 case kArchCallCodeObject: { | 880 case kArchCallCodeObject: { |
785 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | 881 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( |
786 masm()); | 882 masm()); |
787 EnsureSpaceForLazyDeopt(); | 883 EnsureSpaceForLazyDeopt(); |
788 if (HasRegisterInput(instr, 0)) { | 884 if (HasRegisterInput(instr, 0)) { |
789 __ addi(ip, i.InputRegister(0), | 885 __ addi(ip, i.InputRegister(0), |
790 Operand(Code::kHeaderSize - kHeapObjectTag)); | 886 Operand(Code::kHeaderSize - kHeapObjectTag)); |
791 __ Call(ip); | 887 __ Call(ip); |
792 } else { | 888 } else { |
793 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 889 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
794 RelocInfo::CODE_TARGET); | 890 RelocInfo::CODE_TARGET); |
795 } | 891 } |
796 RecordCallPosition(instr); | 892 RecordCallPosition(instr); |
797 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 893 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
798 frame_access_state()->ClearSPDelta(); | 894 frame_access_state()->ClearSPDelta(); |
799 break; | 895 break; |
800 } | 896 } |
801 case kArchTailCallCodeObjectFromJSFunction: | 897 case kArchTailCallCodeObjectFromJSFunction: |
802 case kArchTailCallCodeObject: { | 898 case kArchTailCallCodeObject: { |
803 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
804 AssembleDeconstructActivationRecord(stack_param_delta); | |
805 if (opcode == kArchTailCallCodeObjectFromJSFunction) { | 899 if (opcode == kArchTailCallCodeObjectFromJSFunction) { |
806 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 900 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
807 i.TempRegister(0), i.TempRegister(1), | 901 i.TempRegister(0), i.TempRegister(1), |
808 i.TempRegister(2)); | 902 i.TempRegister(2)); |
809 } | 903 } |
810 if (HasRegisterInput(instr, 0)) { | 904 if (HasRegisterInput(instr, 0)) { |
811 __ addi(ip, i.InputRegister(0), | 905 __ addi(ip, i.InputRegister(0), |
812 Operand(Code::kHeaderSize - kHeapObjectTag)); | 906 Operand(Code::kHeaderSize - kHeapObjectTag)); |
813 __ Jump(ip); | 907 __ Jump(ip); |
814 } else { | 908 } else { |
815 // We cannot use the constant pool to load the target since | 909 // We cannot use the constant pool to load the target since |
816 // we've already restored the caller's frame. | 910 // we've already restored the caller's frame. |
817 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); | 911 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); |
818 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 912 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
819 RelocInfo::CODE_TARGET); | 913 RelocInfo::CODE_TARGET); |
820 } | 914 } |
821 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 915 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
822 frame_access_state()->ClearSPDelta(); | 916 frame_access_state()->ClearSPDelta(); |
| 917 frame_access_state()->SetFrameAccessToDefault(); |
823 break; | 918 break; |
824 } | 919 } |
825 case kArchTailCallAddress: { | 920 case kArchTailCallAddress: { |
826 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
827 AssembleDeconstructActivationRecord(stack_param_delta); | |
828 CHECK(!instr->InputAt(0)->IsImmediate()); | 921 CHECK(!instr->InputAt(0)->IsImmediate()); |
829 __ Jump(i.InputRegister(0)); | 922 __ Jump(i.InputRegister(0)); |
830 frame_access_state()->ClearSPDelta(); | 923 frame_access_state()->ClearSPDelta(); |
| 924 frame_access_state()->SetFrameAccessToDefault(); |
831 break; | 925 break; |
832 } | 926 } |
833 case kArchCallJSFunction: { | 927 case kArchCallJSFunction: { |
834 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | 928 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( |
835 masm()); | 929 masm()); |
836 EnsureSpaceForLazyDeopt(); | 930 EnsureSpaceForLazyDeopt(); |
837 Register func = i.InputRegister(0); | 931 Register func = i.InputRegister(0); |
838 if (FLAG_debug_code) { | 932 if (FLAG_debug_code) { |
839 // Check the function's context matches the context argument. | 933 // Check the function's context matches the context argument. |
840 __ LoadP(kScratchReg, | 934 __ LoadP(kScratchReg, |
(...skipping 11 matching lines...) Expand all Loading... |
852 case kArchTailCallJSFunctionFromJSFunction: | 946 case kArchTailCallJSFunctionFromJSFunction: |
853 case kArchTailCallJSFunction: { | 947 case kArchTailCallJSFunction: { |
854 Register func = i.InputRegister(0); | 948 Register func = i.InputRegister(0); |
855 if (FLAG_debug_code) { | 949 if (FLAG_debug_code) { |
856 // Check the function's context matches the context argument. | 950 // Check the function's context matches the context argument. |
857 __ LoadP(kScratchReg, | 951 __ LoadP(kScratchReg, |
858 FieldMemOperand(func, JSFunction::kContextOffset)); | 952 FieldMemOperand(func, JSFunction::kContextOffset)); |
859 __ cmp(cp, kScratchReg); | 953 __ cmp(cp, kScratchReg); |
860 __ Assert(eq, kWrongFunctionContext); | 954 __ Assert(eq, kWrongFunctionContext); |
861 } | 955 } |
862 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
863 AssembleDeconstructActivationRecord(stack_param_delta); | |
864 if (opcode == kArchTailCallJSFunctionFromJSFunction) { | 956 if (opcode == kArchTailCallJSFunctionFromJSFunction) { |
865 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 957 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
866 i.TempRegister(0), i.TempRegister(1), | 958 i.TempRegister(0), i.TempRegister(1), |
867 i.TempRegister(2)); | 959 i.TempRegister(2)); |
868 } | 960 } |
869 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 961 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
870 __ Jump(ip); | 962 __ Jump(ip); |
871 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 963 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
872 frame_access_state()->ClearSPDelta(); | 964 frame_access_state()->ClearSPDelta(); |
| 965 frame_access_state()->SetFrameAccessToDefault(); |
873 break; | 966 break; |
874 } | 967 } |
875 case kArchPrepareCallCFunction: { | 968 case kArchPrepareCallCFunction: { |
876 int const num_parameters = MiscField::decode(instr->opcode()); | 969 int const num_parameters = MiscField::decode(instr->opcode()); |
877 __ PrepareCallCFunction(num_parameters, kScratchReg); | 970 __ PrepareCallCFunction(num_parameters, kScratchReg); |
878 // Frame alignment requires using FP-relative frame addressing. | 971 // Frame alignment requires using FP-relative frame addressing. |
879 frame_access_state()->SetFrameAccessToFP(); | 972 frame_access_state()->SetFrameAccessToFP(); |
880 break; | 973 break; |
881 } | 974 } |
882 case kArchPrepareTailCall: | 975 case kArchPrepareTailCall: |
883 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 976 AssemblePrepareTailCall(); |
884 break; | 977 break; |
885 case kArchCallCFunction: { | 978 case kArchCallCFunction: { |
886 int const num_parameters = MiscField::decode(instr->opcode()); | 979 int const num_parameters = MiscField::decode(instr->opcode()); |
887 if (instr->InputAt(0)->IsImmediate()) { | 980 if (instr->InputAt(0)->IsImmediate()) { |
888 ExternalReference ref = i.InputExternalReference(0); | 981 ExternalReference ref = i.InputExternalReference(0); |
889 __ CallCFunction(ref, num_parameters); | 982 __ CallCFunction(ref, num_parameters); |
890 } else { | 983 } else { |
891 Register func = i.InputRegister(0); | 984 Register func = i.InputRegister(0); |
892 __ CallCFunction(func, num_parameters); | 985 __ CallCFunction(func, num_parameters); |
893 } | 986 } |
(...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 padding_size -= v8::internal::Assembler::kInstrSize; | 2344 padding_size -= v8::internal::Assembler::kInstrSize; |
2252 } | 2345 } |
2253 } | 2346 } |
2254 } | 2347 } |
2255 | 2348 |
2256 #undef __ | 2349 #undef __ |
2257 | 2350 |
2258 } // namespace compiler | 2351 } // namespace compiler |
2259 } // namespace internal | 2352 } // namespace internal |
2260 } // namespace v8 | 2353 } // namespace v8 |
OLD | NEW |