| 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 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 if (sp_slot_delta < 0) { | 678 if (sp_slot_delta < 0) { |
| 679 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); | 679 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); |
| 680 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 680 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
| 681 } | 681 } |
| 682 if (frame()->needs_frame()) { | 682 if (frame()->needs_frame()) { |
| 683 __ RestoreFrameStateForTailCall(); | 683 __ RestoreFrameStateForTailCall(); |
| 684 } | 684 } |
| 685 frame_access_state()->SetFrameAccessToSP(); | 685 frame_access_state()->SetFrameAccessToSP(); |
| 686 } | 686 } |
| 687 | 687 |
| 688 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 689 Register scratch1, |
| 690 Register scratch2, |
| 691 Register scratch3) { |
| 692 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 693 Label done; |
| 694 |
| 695 // Check if current frame is an arguments adaptor frame. |
| 696 __ LoadP(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 697 __ CmpSmiLiteral(scratch1, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); |
| 698 __ bne(&done); |
| 699 |
| 700 // Load arguments count from current arguments adaptor frame (note, it |
| 701 // does not include receiver). |
| 702 Register caller_args_count_reg = scratch1; |
| 703 __ LoadP(caller_args_count_reg, |
| 704 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 705 __ SmiUntag(caller_args_count_reg); |
| 706 |
| 707 ParameterCount callee_args_count(args_reg); |
| 708 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 709 scratch3); |
| 710 __ bind(&done); |
| 711 } |
| 688 | 712 |
| 689 // Assembles an instruction after register allocation, producing machine code. | 713 // Assembles an instruction after register allocation, producing machine code. |
| 690 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 714 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 691 PPCOperandConverter i(this, instr); | 715 PPCOperandConverter i(this, instr); |
| 692 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); | 716 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); |
| 693 | 717 |
| 694 switch (opcode) { | 718 switch (opcode) { |
| 695 case kArchCallCodeObject: { | 719 case kArchCallCodeObject: { |
| 696 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( | 720 v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( |
| 697 masm()); | 721 masm()); |
| 698 EnsureSpaceForLazyDeopt(); | 722 EnsureSpaceForLazyDeopt(); |
| 699 if (HasRegisterInput(instr, 0)) { | 723 if (HasRegisterInput(instr, 0)) { |
| 700 __ addi(ip, i.InputRegister(0), | 724 __ addi(ip, i.InputRegister(0), |
| 701 Operand(Code::kHeaderSize - kHeapObjectTag)); | 725 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 702 __ Call(ip); | 726 __ Call(ip); |
| 703 } else { | 727 } else { |
| 704 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 728 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| 705 RelocInfo::CODE_TARGET); | 729 RelocInfo::CODE_TARGET); |
| 706 } | 730 } |
| 707 RecordCallPosition(instr); | 731 RecordCallPosition(instr); |
| 708 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 732 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 709 frame_access_state()->ClearSPDelta(); | 733 frame_access_state()->ClearSPDelta(); |
| 710 break; | 734 break; |
| 711 } | 735 } |
| 736 case kArchTailCallCodeObjectFromJSFunction: |
| 712 case kArchTailCallCodeObject: { | 737 case kArchTailCallCodeObject: { |
| 713 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 738 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 714 AssembleDeconstructActivationRecord(stack_param_delta); | 739 AssembleDeconstructActivationRecord(stack_param_delta); |
| 740 if (opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 741 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 742 i.TempRegister(0), i.TempRegister(1), |
| 743 i.TempRegister(2)); |
| 744 } |
| 715 if (HasRegisterInput(instr, 0)) { | 745 if (HasRegisterInput(instr, 0)) { |
| 716 __ addi(ip, i.InputRegister(0), | 746 __ addi(ip, i.InputRegister(0), |
| 717 Operand(Code::kHeaderSize - kHeapObjectTag)); | 747 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 718 __ Jump(ip); | 748 __ Jump(ip); |
| 719 } else { | 749 } else { |
| 720 // We cannot use the constant pool to load the target since | 750 // We cannot use the constant pool to load the target since |
| 721 // we've already restored the caller's frame. | 751 // we've already restored the caller's frame. |
| 722 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); | 752 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); |
| 723 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 753 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 724 RelocInfo::CODE_TARGET); | 754 RelocInfo::CODE_TARGET); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 739 __ cmp(cp, kScratchReg); | 769 __ cmp(cp, kScratchReg); |
| 740 __ Assert(eq, kWrongFunctionContext); | 770 __ Assert(eq, kWrongFunctionContext); |
| 741 } | 771 } |
| 742 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 772 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 743 __ Call(ip); | 773 __ Call(ip); |
| 744 RecordCallPosition(instr); | 774 RecordCallPosition(instr); |
| 745 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 775 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 746 frame_access_state()->ClearSPDelta(); | 776 frame_access_state()->ClearSPDelta(); |
| 747 break; | 777 break; |
| 748 } | 778 } |
| 779 case kArchTailCallJSFunctionFromJSFunction: |
| 749 case kArchTailCallJSFunction: { | 780 case kArchTailCallJSFunction: { |
| 750 Register func = i.InputRegister(0); | 781 Register func = i.InputRegister(0); |
| 751 if (FLAG_debug_code) { | 782 if (FLAG_debug_code) { |
| 752 // Check the function's context matches the context argument. | 783 // Check the function's context matches the context argument. |
| 753 __ LoadP(kScratchReg, | 784 __ LoadP(kScratchReg, |
| 754 FieldMemOperand(func, JSFunction::kContextOffset)); | 785 FieldMemOperand(func, JSFunction::kContextOffset)); |
| 755 __ cmp(cp, kScratchReg); | 786 __ cmp(cp, kScratchReg); |
| 756 __ Assert(eq, kWrongFunctionContext); | 787 __ Assert(eq, kWrongFunctionContext); |
| 757 } | 788 } |
| 758 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 789 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 759 AssembleDeconstructActivationRecord(stack_param_delta); | 790 AssembleDeconstructActivationRecord(stack_param_delta); |
| 791 if (opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 792 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 793 i.TempRegister(0), i.TempRegister(1), |
| 794 i.TempRegister(2)); |
| 795 } |
| 760 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 796 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 761 __ Jump(ip); | 797 __ Jump(ip); |
| 762 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 798 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 763 frame_access_state()->ClearSPDelta(); | 799 frame_access_state()->ClearSPDelta(); |
| 764 break; | 800 break; |
| 765 } | 801 } |
| 766 case kArchPrepareCallCFunction: { | 802 case kArchPrepareCallCFunction: { |
| 767 int const num_parameters = MiscField::decode(instr->opcode()); | 803 int const num_parameters = MiscField::decode(instr->opcode()); |
| 768 __ PrepareCallCFunction(num_parameters, kScratchReg); | 804 __ PrepareCallCFunction(num_parameters, kScratchReg); |
| 769 // Frame alignment requires using FP-relative frame addressing. | 805 // Frame alignment requires using FP-relative frame addressing. |
| (...skipping 1141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1911 padding_size -= v8::internal::Assembler::kInstrSize; | 1947 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1912 } | 1948 } |
| 1913 } | 1949 } |
| 1914 } | 1950 } |
| 1915 | 1951 |
| 1916 #undef __ | 1952 #undef __ |
| 1917 | 1953 |
| 1918 } // namespace compiler | 1954 } // namespace compiler |
| 1919 } // namespace internal | 1955 } // namespace internal |
| 1920 } // namespace v8 | 1956 } // namespace v8 |
| OLD | NEW |