| 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 |
| 575 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, |
| 576 int new_slot_above_sp, |
| 577 bool allow_shrinkage = true) { |
| 578 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 579 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 580 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 581 if (stack_slot_delta > 0) { |
| 582 masm->Claim(stack_slot_delta); |
| 583 state->IncreaseSPDelta(stack_slot_delta); |
| 584 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 585 masm->Drop(-stack_slot_delta); |
| 586 state->IncreaseSPDelta(stack_slot_delta); |
| 587 } |
| 588 } |
| 589 |
| 590 } // namespace |
| 591 |
| 592 void CodeGenerator::AssemblePreGaps(Instruction* instr) { |
| 593 int first_unused_stack_slot; |
| 594 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 595 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 596 first_unused_stack_slot, false); |
| 597 } |
| 598 |
| 599 void CodeGenerator::AssemblePostGaps(Instruction* instr) { |
| 600 int first_unused_stack_slot; |
| 601 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 602 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 603 first_unused_stack_slot); |
| 604 } |
| 605 |
| 587 // Assembles an instruction after register allocation, producing machine code. | 606 // Assembles an instruction after register allocation, producing machine code. |
| 588 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 607 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
| 589 Instruction* instr) { | 608 Instruction* instr) { |
| 590 Arm64OperandConverter i(this, instr); | 609 Arm64OperandConverter i(this, instr); |
| 591 InstructionCode opcode = instr->opcode(); | 610 InstructionCode opcode = instr->opcode(); |
| 592 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 611 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 593 switch (arch_opcode) { | 612 switch (arch_opcode) { |
| 594 case kArchCallCodeObject: { | 613 case kArchCallCodeObject: { |
| 595 EnsureSpaceForLazyDeopt(); | 614 EnsureSpaceForLazyDeopt(); |
| 596 if (instr->InputAt(0)->IsImmediate()) { | 615 if (instr->InputAt(0)->IsImmediate()) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 612 } | 631 } |
| 613 if (flags & CallDescriptor::kRestoreCSP) { | 632 if (flags & CallDescriptor::kRestoreCSP) { |
| 614 __ Mov(csp, jssp); | 633 __ Mov(csp, jssp); |
| 615 __ AssertCspAligned(); | 634 __ AssertCspAligned(); |
| 616 } | 635 } |
| 617 frame_access_state()->ClearSPDelta(); | 636 frame_access_state()->ClearSPDelta(); |
| 618 break; | 637 break; |
| 619 } | 638 } |
| 620 case kArchTailCallCodeObjectFromJSFunction: | 639 case kArchTailCallCodeObjectFromJSFunction: |
| 621 case kArchTailCallCodeObject: { | 640 case kArchTailCallCodeObject: { |
| 622 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 623 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 624 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 641 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 625 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 642 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 626 i.TempRegister(0), i.TempRegister(1), | 643 i.TempRegister(0), i.TempRegister(1), |
| 627 i.TempRegister(2)); | 644 i.TempRegister(2)); |
| 628 } | 645 } |
| 629 if (instr->InputAt(0)->IsImmediate()) { | 646 if (instr->InputAt(0)->IsImmediate()) { |
| 630 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 647 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 631 RelocInfo::CODE_TARGET); | 648 RelocInfo::CODE_TARGET); |
| 632 } else { | 649 } else { |
| 633 Register target = i.InputRegister(0); | 650 Register target = i.InputRegister(0); |
| 634 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); | 651 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
| 635 __ Jump(target); | 652 __ Jump(target); |
| 636 } | 653 } |
| 637 frame_access_state()->ClearSPDelta(); | 654 frame_access_state()->ClearSPDelta(); |
| 655 frame_access_state()->SetFrameAccessToDefault(); |
| 638 break; | 656 break; |
| 639 } | 657 } |
| 640 case kArchTailCallAddress: { | 658 case kArchTailCallAddress: { |
| 641 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 642 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 643 CHECK(!instr->InputAt(0)->IsImmediate()); | 659 CHECK(!instr->InputAt(0)->IsImmediate()); |
| 644 __ Jump(i.InputRegister(0)); | 660 __ Jump(i.InputRegister(0)); |
| 645 frame_access_state()->ClearSPDelta(); | 661 frame_access_state()->ClearSPDelta(); |
| 662 frame_access_state()->SetFrameAccessToDefault(); |
| 646 break; | 663 break; |
| 647 } | 664 } |
| 648 case kArchCallJSFunction: { | 665 case kArchCallJSFunction: { |
| 649 EnsureSpaceForLazyDeopt(); | 666 EnsureSpaceForLazyDeopt(); |
| 650 Register func = i.InputRegister(0); | 667 Register func = i.InputRegister(0); |
| 651 if (FLAG_debug_code) { | 668 if (FLAG_debug_code) { |
| 652 // Check the function's context matches the context argument. | 669 // Check the function's context matches the context argument. |
| 653 UseScratchRegisterScope scope(masm()); | 670 UseScratchRegisterScope scope(masm()); |
| 654 Register temp = scope.AcquireX(); | 671 Register temp = scope.AcquireX(); |
| 655 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 672 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 678 case kArchTailCallJSFunction: { | 695 case kArchTailCallJSFunction: { |
| 679 Register func = i.InputRegister(0); | 696 Register func = i.InputRegister(0); |
| 680 if (FLAG_debug_code) { | 697 if (FLAG_debug_code) { |
| 681 // Check the function's context matches the context argument. | 698 // Check the function's context matches the context argument. |
| 682 UseScratchRegisterScope scope(masm()); | 699 UseScratchRegisterScope scope(masm()); |
| 683 Register temp = scope.AcquireX(); | 700 Register temp = scope.AcquireX(); |
| 684 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 701 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 685 __ cmp(cp, temp); | 702 __ cmp(cp, temp); |
| 686 __ Assert(eq, kWrongFunctionContext); | 703 __ Assert(eq, kWrongFunctionContext); |
| 687 } | 704 } |
| 688 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 689 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 690 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 705 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 691 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 706 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 692 i.TempRegister(0), i.TempRegister(1), | 707 i.TempRegister(0), i.TempRegister(1), |
| 693 i.TempRegister(2)); | 708 i.TempRegister(2)); |
| 694 } | 709 } |
| 695 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 710 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 696 __ Jump(x10); | 711 __ Jump(x10); |
| 697 frame_access_state()->ClearSPDelta(); | 712 frame_access_state()->ClearSPDelta(); |
| 713 frame_access_state()->SetFrameAccessToDefault(); |
| 698 break; | 714 break; |
| 699 } | 715 } |
| 700 case kArchPrepareCallCFunction: | 716 case kArchPrepareCallCFunction: |
| 701 // We don't need kArchPrepareCallCFunction on arm64 as the instruction | 717 // We don't need kArchPrepareCallCFunction on arm64 as the instruction |
| 702 // selector already perform a Claim to reserve space on the stack and | 718 // selector already perform a Claim to reserve space on the stack and |
| 703 // guarantee correct alignment of stack pointer. | 719 // guarantee correct alignment of stack pointer. |
| 704 UNREACHABLE(); | 720 UNREACHABLE(); |
| 705 break; | 721 break; |
| 706 case kArchPrepareTailCall: | 722 case kArchPrepareTailCall: |
| 707 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 723 AssemblePrepareTailCall(); |
| 708 break; | 724 break; |
| 709 case kArchCallCFunction: { | 725 case kArchCallCFunction: { |
| 710 int const num_parameters = MiscField::decode(instr->opcode()); | 726 int const num_parameters = MiscField::decode(instr->opcode()); |
| 711 if (instr->InputAt(0)->IsImmediate()) { | 727 if (instr->InputAt(0)->IsImmediate()) { |
| 712 ExternalReference ref = i.InputExternalReference(0); | 728 ExternalReference ref = i.InputExternalReference(0); |
| 713 __ CallCFunction(ref, num_parameters, 0); | 729 __ CallCFunction(ref, num_parameters, 0); |
| 714 } else { | 730 } else { |
| 715 Register func = i.InputRegister(0); | 731 Register func = i.InputRegister(0); |
| 716 __ CallCFunction(func, num_parameters, 0); | 732 __ CallCFunction(func, num_parameters, 0); |
| 717 } | 733 } |
| (...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1987 padding_size -= kInstructionSize; | 2003 padding_size -= kInstructionSize; |
| 1988 } | 2004 } |
| 1989 } | 2005 } |
| 1990 } | 2006 } |
| 1991 | 2007 |
| 1992 #undef __ | 2008 #undef __ |
| 1993 | 2009 |
| 1994 } // namespace compiler | 2010 } // namespace compiler |
| 1995 } // namespace internal | 2011 } // namespace internal |
| 1996 } // namespace v8 | 2012 } // namespace v8 |
| OLD | NEW |