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/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/arm64/macro-assembler-arm64.h" | 8 #include "src/arm64/macro-assembler-arm64.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/compiler/code-generator-impl.h" | 10 #include "src/compiler/code-generator-impl.h" |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 void CodeGenerator::AssembleDeconstructFrame() { | 530 void CodeGenerator::AssembleDeconstructFrame() { |
531 const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 531 const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
532 if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) { | 532 if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) { |
533 __ Mov(csp, fp); | 533 __ Mov(csp, fp); |
534 } else { | 534 } else { |
535 __ Mov(jssp, fp); | 535 __ Mov(jssp, fp); |
536 } | 536 } |
537 __ Pop(fp, lr); | 537 __ Pop(fp, lr); |
538 } | 538 } |
539 | 539 |
540 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 540 void CodeGenerator::AssemblePrepareTailCall() { |
541 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
542 if (sp_slot_delta > 0) { | |
543 __ Drop(sp_slot_delta); | |
544 } | |
545 frame_access_state()->SetFrameAccessToDefault(); | |
546 } | |
547 | |
548 | |
549 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
550 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
551 if (sp_slot_delta < 0) { | |
552 __ Claim(-sp_slot_delta); | |
553 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
554 } | |
555 if (frame_access_state()->has_frame()) { | 541 if (frame_access_state()->has_frame()) { |
556 __ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 542 __ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
557 __ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 543 __ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
558 } | 544 } |
559 frame_access_state()->SetFrameAccessToSP(); | 545 frame_access_state()->SetFrameAccessToSP(); |
560 } | 546 } |
561 | 547 |
562 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 548 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
563 Register scratch1, | 549 Register scratch1, |
564 Register scratch2, | 550 Register scratch2, |
(...skipping 12 matching lines...) Expand all Loading... |
577 __ Ldr(caller_args_count_reg, | 563 __ Ldr(caller_args_count_reg, |
578 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 564 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
579 __ SmiUntag(caller_args_count_reg); | 565 __ SmiUntag(caller_args_count_reg); |
580 | 566 |
581 ParameterCount callee_args_count(args_reg); | 567 ParameterCount callee_args_count(args_reg); |
582 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 568 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
583 scratch3); | 569 scratch3); |
584 __ bind(&done); | 570 __ bind(&done); |
585 } | 571 } |
586 | 572 |
| 573 namespace { |
| 574 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, |
| 575 int new_slot_above_sp, |
| 576 bool allow_shrinkage = true) { |
| 577 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 578 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 579 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 580 if (stack_slot_delta > 0) { |
| 581 masm->Claim(stack_slot_delta); |
| 582 state->IncreaseSPDelta(stack_slot_delta); |
| 583 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 584 masm->Drop(-stack_slot_delta); |
| 585 state->IncreaseSPDelta(stack_slot_delta); |
| 586 } |
| 587 } |
| 588 } // namespace |
| 589 |
| 590 void CodeGenerator::AssemblePreGaps(Instruction* instr) { |
| 591 int first_unused_stack_slot; |
| 592 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 593 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 594 first_unused_stack_slot, false); |
| 595 } |
| 596 |
| 597 void CodeGenerator::AssemblePostGaps(Instruction* instr) { |
| 598 int first_unused_stack_slot; |
| 599 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 600 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 601 first_unused_stack_slot); |
| 602 } |
| 603 |
587 // Assembles an instruction after register allocation, producing machine code. | 604 // Assembles an instruction after register allocation, producing machine code. |
588 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 605 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
589 Instruction* instr) { | 606 Instruction* instr) { |
590 Arm64OperandConverter i(this, instr); | 607 Arm64OperandConverter i(this, instr); |
591 InstructionCode opcode = instr->opcode(); | 608 InstructionCode opcode = instr->opcode(); |
592 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 609 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
593 switch (arch_opcode) { | 610 switch (arch_opcode) { |
594 case kArchCallCodeObject: { | 611 case kArchCallCodeObject: { |
595 EnsureSpaceForLazyDeopt(); | 612 EnsureSpaceForLazyDeopt(); |
596 if (instr->InputAt(0)->IsImmediate()) { | 613 if (instr->InputAt(0)->IsImmediate()) { |
(...skipping 15 matching lines...) Expand all Loading... |
612 } | 629 } |
613 if (flags & CallDescriptor::kRestoreCSP) { | 630 if (flags & CallDescriptor::kRestoreCSP) { |
614 __ Mov(csp, jssp); | 631 __ Mov(csp, jssp); |
615 __ AssertCspAligned(); | 632 __ AssertCspAligned(); |
616 } | 633 } |
617 frame_access_state()->ClearSPDelta(); | 634 frame_access_state()->ClearSPDelta(); |
618 break; | 635 break; |
619 } | 636 } |
620 case kArchTailCallCodeObjectFromJSFunction: | 637 case kArchTailCallCodeObjectFromJSFunction: |
621 case kArchTailCallCodeObject: { | 638 case kArchTailCallCodeObject: { |
622 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
623 AssembleDeconstructActivationRecord(stack_param_delta); | |
624 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 639 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
625 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 640 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
626 i.TempRegister(0), i.TempRegister(1), | 641 i.TempRegister(0), i.TempRegister(1), |
627 i.TempRegister(2)); | 642 i.TempRegister(2)); |
628 } | 643 } |
629 if (instr->InputAt(0)->IsImmediate()) { | 644 if (instr->InputAt(0)->IsImmediate()) { |
630 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 645 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
631 RelocInfo::CODE_TARGET); | 646 RelocInfo::CODE_TARGET); |
632 } else { | 647 } else { |
633 Register target = i.InputRegister(0); | 648 Register target = i.InputRegister(0); |
634 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); | 649 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
635 __ Jump(target); | 650 __ Jump(target); |
636 } | 651 } |
637 frame_access_state()->ClearSPDelta(); | 652 frame_access_state()->ClearSPDelta(); |
| 653 frame_access_state()->SetFrameAccessToDefault(); |
638 break; | 654 break; |
639 } | 655 } |
640 case kArchTailCallAddress: { | 656 case kArchTailCallAddress: { |
641 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
642 AssembleDeconstructActivationRecord(stack_param_delta); | |
643 CHECK(!instr->InputAt(0)->IsImmediate()); | 657 CHECK(!instr->InputAt(0)->IsImmediate()); |
644 __ Jump(i.InputRegister(0)); | 658 __ Jump(i.InputRegister(0)); |
645 frame_access_state()->ClearSPDelta(); | 659 frame_access_state()->ClearSPDelta(); |
| 660 frame_access_state()->SetFrameAccessToDefault(); |
646 break; | 661 break; |
647 } | 662 } |
648 case kArchCallJSFunction: { | 663 case kArchCallJSFunction: { |
649 EnsureSpaceForLazyDeopt(); | 664 EnsureSpaceForLazyDeopt(); |
650 Register func = i.InputRegister(0); | 665 Register func = i.InputRegister(0); |
651 if (FLAG_debug_code) { | 666 if (FLAG_debug_code) { |
652 // Check the function's context matches the context argument. | 667 // Check the function's context matches the context argument. |
653 UseScratchRegisterScope scope(masm()); | 668 UseScratchRegisterScope scope(masm()); |
654 Register temp = scope.AcquireX(); | 669 Register temp = scope.AcquireX(); |
655 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 670 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
(...skipping 22 matching lines...) Expand all Loading... |
678 case kArchTailCallJSFunction: { | 693 case kArchTailCallJSFunction: { |
679 Register func = i.InputRegister(0); | 694 Register func = i.InputRegister(0); |
680 if (FLAG_debug_code) { | 695 if (FLAG_debug_code) { |
681 // Check the function's context matches the context argument. | 696 // Check the function's context matches the context argument. |
682 UseScratchRegisterScope scope(masm()); | 697 UseScratchRegisterScope scope(masm()); |
683 Register temp = scope.AcquireX(); | 698 Register temp = scope.AcquireX(); |
684 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 699 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
685 __ cmp(cp, temp); | 700 __ cmp(cp, temp); |
686 __ Assert(eq, kWrongFunctionContext); | 701 __ Assert(eq, kWrongFunctionContext); |
687 } | 702 } |
688 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
689 AssembleDeconstructActivationRecord(stack_param_delta); | |
690 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 703 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
691 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 704 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
692 i.TempRegister(0), i.TempRegister(1), | 705 i.TempRegister(0), i.TempRegister(1), |
693 i.TempRegister(2)); | 706 i.TempRegister(2)); |
694 } | 707 } |
695 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 708 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
696 __ Jump(x10); | 709 __ Jump(x10); |
697 frame_access_state()->ClearSPDelta(); | 710 frame_access_state()->ClearSPDelta(); |
| 711 frame_access_state()->SetFrameAccessToDefault(); |
698 break; | 712 break; |
699 } | 713 } |
700 case kArchPrepareCallCFunction: | 714 case kArchPrepareCallCFunction: |
701 // We don't need kArchPrepareCallCFunction on arm64 as the instruction | 715 // We don't need kArchPrepareCallCFunction on arm64 as the instruction |
702 // selector already perform a Claim to reserve space on the stack and | 716 // selector already perform a Claim to reserve space on the stack and |
703 // guarantee correct alignment of stack pointer. | 717 // guarantee correct alignment of stack pointer. |
704 UNREACHABLE(); | 718 UNREACHABLE(); |
705 break; | 719 break; |
706 case kArchPrepareTailCall: | 720 case kArchPrepareTailCall: |
707 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 721 AssemblePrepareTailCall(); |
708 break; | 722 break; |
709 case kArchCallCFunction: { | 723 case kArchCallCFunction: { |
710 int const num_parameters = MiscField::decode(instr->opcode()); | 724 int const num_parameters = MiscField::decode(instr->opcode()); |
711 if (instr->InputAt(0)->IsImmediate()) { | 725 if (instr->InputAt(0)->IsImmediate()) { |
712 ExternalReference ref = i.InputExternalReference(0); | 726 ExternalReference ref = i.InputExternalReference(0); |
713 __ CallCFunction(ref, num_parameters, 0); | 727 __ CallCFunction(ref, num_parameters, 0); |
714 } else { | 728 } else { |
715 Register func = i.InputRegister(0); | 729 Register func = i.InputRegister(0); |
716 __ CallCFunction(func, num_parameters, 0); | 730 __ CallCFunction(func, num_parameters, 0); |
717 } | 731 } |
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1987 padding_size -= kInstructionSize; | 2001 padding_size -= kInstructionSize; |
1988 } | 2002 } |
1989 } | 2003 } |
1990 } | 2004 } |
1991 | 2005 |
1992 #undef __ | 2006 #undef __ |
1993 | 2007 |
1994 } // namespace compiler | 2008 } // namespace compiler |
1995 } // namespace internal | 2009 } // namespace internal |
1996 } // namespace v8 | 2010 } // namespace v8 |
OLD | NEW |