| 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 | 
|---|