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 |