OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 Register value = i.InputRegister(3); \ | 573 Register value = i.InputRegister(3); \ |
574 __ CleanUInt32(offset); \ | 574 __ CleanUInt32(offset); \ |
575 __ asm_instr(value, operand); \ | 575 __ asm_instr(value, operand); \ |
576 __ bind(&done); \ | 576 __ bind(&done); \ |
577 } while (0) | 577 } while (0) |
578 | 578 |
579 void CodeGenerator::AssembleDeconstructFrame() { | 579 void CodeGenerator::AssembleDeconstructFrame() { |
580 __ LeaveFrame(StackFrame::MANUAL); | 580 __ LeaveFrame(StackFrame::MANUAL); |
581 } | 581 } |
582 | 582 |
583 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 583 void CodeGenerator::AssemblePrepareTailCall() { |
584 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
585 if (sp_slot_delta > 0) { | |
586 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); | |
587 } | |
588 frame_access_state()->SetFrameAccessToDefault(); | |
589 } | |
590 | |
591 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
592 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
593 if (sp_slot_delta < 0) { | |
594 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); | |
595 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
596 } | |
597 if (frame_access_state()->has_frame()) { | 584 if (frame_access_state()->has_frame()) { |
598 __ RestoreFrameStateForTailCall(); | 585 __ RestoreFrameStateForTailCall(); |
599 } | 586 } |
600 frame_access_state()->SetFrameAccessToSP(); | 587 frame_access_state()->SetFrameAccessToSP(); |
601 } | 588 } |
602 | 589 |
603 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 590 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
604 Register scratch1, | 591 Register scratch1, |
605 Register scratch2, | 592 Register scratch2, |
606 Register scratch3) { | 593 Register scratch3) { |
(...skipping 11 matching lines...) Expand all Loading... |
618 __ LoadP(caller_args_count_reg, | 605 __ LoadP(caller_args_count_reg, |
619 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 606 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
620 __ SmiUntag(caller_args_count_reg); | 607 __ SmiUntag(caller_args_count_reg); |
621 | 608 |
622 ParameterCount callee_args_count(args_reg); | 609 ParameterCount callee_args_count(args_reg); |
623 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 610 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
624 scratch3); | 611 scratch3); |
625 __ bind(&done); | 612 __ bind(&done); |
626 } | 613 } |
627 | 614 |
| 615 namespace { |
| 616 |
| 617 void FlushPendingPushRegisters(MacroAssembler* masm, |
| 618 FrameAccessState* frame_access_state, |
| 619 ZoneVector<Register>* pending_pushes) { |
| 620 switch (pending_pushes->size()) { |
| 621 case 0: |
| 622 break; |
| 623 case 1: |
| 624 masm->Push((*pending_pushes)[0]); |
| 625 break; |
| 626 case 2: |
| 627 masm->Push((*pending_pushes)[0], (*pending_pushes)[1]); |
| 628 break; |
| 629 case 3: |
| 630 masm->Push((*pending_pushes)[0], (*pending_pushes)[1], |
| 631 (*pending_pushes)[2]); |
| 632 break; |
| 633 default: |
| 634 UNREACHABLE(); |
| 635 break; |
| 636 } |
| 637 frame_access_state->IncreaseSPDelta(pending_pushes->size()); |
| 638 pending_pushes->resize(0); |
| 639 } |
| 640 |
| 641 void AddPendingPushRegister(MacroAssembler* masm, |
| 642 FrameAccessState* frame_access_state, |
| 643 ZoneVector<Register>* pending_pushes, |
| 644 Register reg) { |
| 645 pending_pushes->push_back(reg); |
| 646 if (pending_pushes->size() == 3 || reg.is(ip)) { |
| 647 FlushPendingPushRegisters(masm, frame_access_state, pending_pushes); |
| 648 } |
| 649 } |
| 650 void AdjustStackPointerForTailCall( |
| 651 MacroAssembler* masm, FrameAccessState* state, int new_slot_above_sp, |
| 652 ZoneVector<Register>* pending_pushes = nullptr, |
| 653 bool allow_shrinkage = true) { |
| 654 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 655 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 656 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 657 if (stack_slot_delta > 0) { |
| 658 if (pending_pushes != nullptr) { |
| 659 FlushPendingPushRegisters(masm, state, pending_pushes); |
| 660 } |
| 661 masm->AddP(sp, sp, Operand(-stack_slot_delta * kPointerSize)); |
| 662 state->IncreaseSPDelta(stack_slot_delta); |
| 663 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 664 if (pending_pushes != nullptr) { |
| 665 FlushPendingPushRegisters(masm, state, pending_pushes); |
| 666 } |
| 667 masm->AddP(sp, sp, Operand(-stack_slot_delta * kPointerSize)); |
| 668 state->IncreaseSPDelta(stack_slot_delta); |
| 669 } |
| 670 } |
| 671 |
| 672 } // namespace |
| 673 |
| 674 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr, |
| 675 int first_unused_stack_slot) { |
| 676 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush); |
| 677 ZoneVector<MoveOperands*> pushes(zone()); |
| 678 GetPushCompatibleMoves(instr, flags, &pushes); |
| 679 |
| 680 if (!pushes.empty() && |
| 681 (LocationOperand::cast(pushes.back()->destination()).index() + 1 == |
| 682 first_unused_stack_slot)) { |
| 683 S390OperandConverter g(this, instr); |
| 684 ZoneVector<Register> pending_pushes(zone()); |
| 685 for (auto move : pushes) { |
| 686 LocationOperand destination_location( |
| 687 LocationOperand::cast(move->destination())); |
| 688 InstructionOperand source(move->source()); |
| 689 AdjustStackPointerForTailCall( |
| 690 masm(), frame_access_state(), |
| 691 destination_location.index() - pending_pushes.size(), |
| 692 &pending_pushes); |
| 693 if (source.IsStackSlot()) { |
| 694 LocationOperand source_location(LocationOperand::cast(source)); |
| 695 __ LoadP(ip, g.SlotToMemOperand(source_location.index())); |
| 696 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 697 ip); |
| 698 } else if (source.IsRegister()) { |
| 699 LocationOperand source_location(LocationOperand::cast(source)); |
| 700 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 701 source_location.GetRegister()); |
| 702 } else if (source.IsImmediate()) { |
| 703 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, |
| 704 ip); |
| 705 } else { |
| 706 // Pushes of non-scalar data types is not supported. |
| 707 UNIMPLEMENTED(); |
| 708 } |
| 709 move->Eliminate(); |
| 710 } |
| 711 FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes); |
| 712 } |
| 713 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 714 first_unused_stack_slot, nullptr, false); |
| 715 } |
| 716 |
| 717 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, |
| 718 int first_unused_stack_slot) { |
| 719 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 720 first_unused_stack_slot); |
| 721 } |
| 722 |
628 // Assembles an instruction after register allocation, producing machine code. | 723 // Assembles an instruction after register allocation, producing machine code. |
629 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 724 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
630 Instruction* instr) { | 725 Instruction* instr) { |
631 S390OperandConverter i(this, instr); | 726 S390OperandConverter i(this, instr); |
632 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); | 727 ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode()); |
633 | 728 |
634 switch (opcode) { | 729 switch (opcode) { |
635 case kArchCallCodeObject: { | 730 case kArchCallCodeObject: { |
636 EnsureSpaceForLazyDeopt(); | 731 EnsureSpaceForLazyDeopt(); |
637 if (HasRegisterInput(instr, 0)) { | 732 if (HasRegisterInput(instr, 0)) { |
638 __ AddP(ip, i.InputRegister(0), | 733 __ AddP(ip, i.InputRegister(0), |
639 Operand(Code::kHeaderSize - kHeapObjectTag)); | 734 Operand(Code::kHeaderSize - kHeapObjectTag)); |
640 __ Call(ip); | 735 __ Call(ip); |
641 } else { | 736 } else { |
642 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 737 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
643 RelocInfo::CODE_TARGET); | 738 RelocInfo::CODE_TARGET); |
644 } | 739 } |
645 RecordCallPosition(instr); | 740 RecordCallPosition(instr); |
646 frame_access_state()->ClearSPDelta(); | 741 frame_access_state()->ClearSPDelta(); |
647 break; | 742 break; |
648 } | 743 } |
649 case kArchTailCallCodeObjectFromJSFunction: | 744 case kArchTailCallCodeObjectFromJSFunction: |
650 case kArchTailCallCodeObject: { | 745 case kArchTailCallCodeObject: { |
651 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
652 AssembleDeconstructActivationRecord(stack_param_delta); | |
653 if (opcode == kArchTailCallCodeObjectFromJSFunction) { | 746 if (opcode == kArchTailCallCodeObjectFromJSFunction) { |
654 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 747 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
655 i.TempRegister(0), i.TempRegister(1), | 748 i.TempRegister(0), i.TempRegister(1), |
656 i.TempRegister(2)); | 749 i.TempRegister(2)); |
657 } | 750 } |
658 if (HasRegisterInput(instr, 0)) { | 751 if (HasRegisterInput(instr, 0)) { |
659 __ AddP(ip, i.InputRegister(0), | 752 __ AddP(ip, i.InputRegister(0), |
660 Operand(Code::kHeaderSize - kHeapObjectTag)); | 753 Operand(Code::kHeaderSize - kHeapObjectTag)); |
661 __ Jump(ip); | 754 __ Jump(ip); |
662 } else { | 755 } else { |
663 // We cannot use the constant pool to load the target since | 756 // We cannot use the constant pool to load the target since |
664 // we've already restored the caller's frame. | 757 // we've already restored the caller's frame. |
665 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); | 758 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); |
666 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 759 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
667 RelocInfo::CODE_TARGET); | 760 RelocInfo::CODE_TARGET); |
668 } | 761 } |
669 frame_access_state()->ClearSPDelta(); | 762 frame_access_state()->ClearSPDelta(); |
| 763 frame_access_state()->SetFrameAccessToDefault(); |
670 break; | 764 break; |
671 } | 765 } |
672 case kArchTailCallAddress: { | 766 case kArchTailCallAddress: { |
673 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
674 AssembleDeconstructActivationRecord(stack_param_delta); | |
675 CHECK(!instr->InputAt(0)->IsImmediate()); | 767 CHECK(!instr->InputAt(0)->IsImmediate()); |
676 __ Jump(i.InputRegister(0)); | 768 __ Jump(i.InputRegister(0)); |
677 frame_access_state()->ClearSPDelta(); | 769 frame_access_state()->ClearSPDelta(); |
| 770 frame_access_state()->SetFrameAccessToDefault(); |
678 break; | 771 break; |
679 } | 772 } |
680 case kArchCallJSFunction: { | 773 case kArchCallJSFunction: { |
681 EnsureSpaceForLazyDeopt(); | 774 EnsureSpaceForLazyDeopt(); |
682 Register func = i.InputRegister(0); | 775 Register func = i.InputRegister(0); |
683 if (FLAG_debug_code) { | 776 if (FLAG_debug_code) { |
684 // Check the function's context matches the context argument. | 777 // Check the function's context matches the context argument. |
685 __ LoadP(kScratchReg, | 778 __ LoadP(kScratchReg, |
686 FieldMemOperand(func, JSFunction::kContextOffset)); | 779 FieldMemOperand(func, JSFunction::kContextOffset)); |
687 __ CmpP(cp, kScratchReg); | 780 __ CmpP(cp, kScratchReg); |
688 __ Assert(eq, kWrongFunctionContext); | 781 __ Assert(eq, kWrongFunctionContext); |
689 } | 782 } |
690 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 783 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
691 __ Call(ip); | 784 __ Call(ip); |
692 RecordCallPosition(instr); | 785 RecordCallPosition(instr); |
693 frame_access_state()->ClearSPDelta(); | 786 frame_access_state()->ClearSPDelta(); |
694 break; | 787 break; |
695 } | 788 } |
696 case kArchTailCallJSFunctionFromJSFunction: | 789 case kArchTailCallJSFunctionFromJSFunction: |
697 case kArchTailCallJSFunction: { | 790 case kArchTailCallJSFunction: { |
698 Register func = i.InputRegister(0); | 791 Register func = i.InputRegister(0); |
699 if (FLAG_debug_code) { | 792 if (FLAG_debug_code) { |
700 // Check the function's context matches the context argument. | 793 // Check the function's context matches the context argument. |
701 __ LoadP(kScratchReg, | 794 __ LoadP(kScratchReg, |
702 FieldMemOperand(func, JSFunction::kContextOffset)); | 795 FieldMemOperand(func, JSFunction::kContextOffset)); |
703 __ CmpP(cp, kScratchReg); | 796 __ CmpP(cp, kScratchReg); |
704 __ Assert(eq, kWrongFunctionContext); | 797 __ Assert(eq, kWrongFunctionContext); |
705 } | 798 } |
706 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
707 AssembleDeconstructActivationRecord(stack_param_delta); | |
708 if (opcode == kArchTailCallJSFunctionFromJSFunction) { | 799 if (opcode == kArchTailCallJSFunctionFromJSFunction) { |
709 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 800 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
710 i.TempRegister(0), i.TempRegister(1), | 801 i.TempRegister(0), i.TempRegister(1), |
711 i.TempRegister(2)); | 802 i.TempRegister(2)); |
712 } | 803 } |
713 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 804 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
714 __ Jump(ip); | 805 __ Jump(ip); |
715 frame_access_state()->ClearSPDelta(); | 806 frame_access_state()->ClearSPDelta(); |
| 807 frame_access_state()->SetFrameAccessToDefault(); |
716 break; | 808 break; |
717 } | 809 } |
718 case kArchPrepareCallCFunction: { | 810 case kArchPrepareCallCFunction: { |
719 int const num_parameters = MiscField::decode(instr->opcode()); | 811 int const num_parameters = MiscField::decode(instr->opcode()); |
720 __ PrepareCallCFunction(num_parameters, kScratchReg); | 812 __ PrepareCallCFunction(num_parameters, kScratchReg); |
721 // Frame alignment requires using FP-relative frame addressing. | 813 // Frame alignment requires using FP-relative frame addressing. |
722 frame_access_state()->SetFrameAccessToFP(); | 814 frame_access_state()->SetFrameAccessToFP(); |
723 break; | 815 break; |
724 } | 816 } |
725 case kArchPrepareTailCall: | 817 case kArchPrepareTailCall: |
726 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 818 AssemblePrepareTailCall(); |
727 break; | 819 break; |
728 case kArchCallCFunction: { | 820 case kArchCallCFunction: { |
729 int const num_parameters = MiscField::decode(instr->opcode()); | 821 int const num_parameters = MiscField::decode(instr->opcode()); |
730 if (instr->InputAt(0)->IsImmediate()) { | 822 if (instr->InputAt(0)->IsImmediate()) { |
731 ExternalReference ref = i.InputExternalReference(0); | 823 ExternalReference ref = i.InputExternalReference(0); |
732 __ CallCFunction(ref, num_parameters); | 824 __ CallCFunction(ref, num_parameters); |
733 } else { | 825 } else { |
734 Register func = i.InputRegister(0); | 826 Register func = i.InputRegister(0); |
735 __ CallCFunction(func, num_parameters); | 827 __ CallCFunction(func, num_parameters); |
736 } | 828 } |
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2255 padding_size -= 2; | 2347 padding_size -= 2; |
2256 } | 2348 } |
2257 } | 2349 } |
2258 } | 2350 } |
2259 | 2351 |
2260 #undef __ | 2352 #undef __ |
2261 | 2353 |
2262 } // namespace compiler | 2354 } // namespace compiler |
2263 } // namespace internal | 2355 } // namespace internal |
2264 } // namespace v8 | 2356 } // namespace v8 |
OLD | NEW |