OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 if (sp_slot_delta < 0) { | 614 if (sp_slot_delta < 0) { |
615 __ subq(rsp, Immediate(-sp_slot_delta * kPointerSize)); | 615 __ subq(rsp, Immediate(-sp_slot_delta * kPointerSize)); |
616 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 616 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
617 } | 617 } |
618 if (frame()->needs_frame()) { | 618 if (frame()->needs_frame()) { |
619 __ movq(rbp, MemOperand(rbp, 0)); | 619 __ movq(rbp, MemOperand(rbp, 0)); |
620 } | 620 } |
621 frame_access_state()->SetFrameAccessToSP(); | 621 frame_access_state()->SetFrameAccessToSP(); |
622 } | 622 } |
623 | 623 |
| 624 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 625 Register scratch1, |
| 626 Register scratch2, |
| 627 Register scratch3) { |
| 628 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 629 Label done; |
| 630 |
| 631 // Check if current frame is an arguments adaptor frame. |
| 632 __ Cmp(Operand(rbp, StandardFrameConstants::kContextOffset), |
| 633 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 634 __ j(not_equal, &done, Label::kNear); |
| 635 |
| 636 // Load arguments count from current arguments adaptor frame (note, it |
| 637 // does not include receiver). |
| 638 Register caller_args_count_reg = scratch1; |
| 639 __ SmiToInteger32( |
| 640 caller_args_count_reg, |
| 641 Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 642 |
| 643 ParameterCount callee_args_count(args_reg); |
| 644 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 645 scratch3, ReturnAddressState::kOnStack); |
| 646 __ bind(&done); |
| 647 } |
624 | 648 |
625 // Assembles an instruction after register allocation, producing machine code. | 649 // Assembles an instruction after register allocation, producing machine code. |
626 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 650 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
627 X64OperandConverter i(this, instr); | 651 X64OperandConverter i(this, instr); |
628 | 652 InstructionCode opcode = instr->opcode(); |
629 switch (ArchOpcodeField::decode(instr->opcode())) { | 653 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 654 switch (arch_opcode) { |
630 case kArchCallCodeObject: { | 655 case kArchCallCodeObject: { |
631 EnsureSpaceForLazyDeopt(); | 656 EnsureSpaceForLazyDeopt(); |
632 if (HasImmediateInput(instr, 0)) { | 657 if (HasImmediateInput(instr, 0)) { |
633 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 658 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
634 __ Call(code, RelocInfo::CODE_TARGET); | 659 __ Call(code, RelocInfo::CODE_TARGET); |
635 } else { | 660 } else { |
636 Register reg = i.InputRegister(0); | 661 Register reg = i.InputRegister(0); |
637 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 662 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
638 __ call(reg); | 663 __ call(reg); |
639 } | 664 } |
640 RecordCallPosition(instr); | 665 RecordCallPosition(instr); |
641 frame_access_state()->ClearSPDelta(); | 666 frame_access_state()->ClearSPDelta(); |
642 break; | 667 break; |
643 } | 668 } |
| 669 case kArchTailCallCodeObjectFromJSFunction: |
644 case kArchTailCallCodeObject: { | 670 case kArchTailCallCodeObject: { |
645 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 671 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
646 AssembleDeconstructActivationRecord(stack_param_delta); | 672 AssembleDeconstructActivationRecord(stack_param_delta); |
| 673 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 674 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 675 i.TempRegister(0), i.TempRegister(1), |
| 676 i.TempRegister(2)); |
| 677 } |
647 if (HasImmediateInput(instr, 0)) { | 678 if (HasImmediateInput(instr, 0)) { |
648 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 679 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
649 __ jmp(code, RelocInfo::CODE_TARGET); | 680 __ jmp(code, RelocInfo::CODE_TARGET); |
650 } else { | 681 } else { |
651 Register reg = i.InputRegister(0); | 682 Register reg = i.InputRegister(0); |
652 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 683 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
653 __ jmp(reg); | 684 __ jmp(reg); |
654 } | 685 } |
655 frame_access_state()->ClearSPDelta(); | 686 frame_access_state()->ClearSPDelta(); |
656 break; | 687 break; |
657 } | 688 } |
658 case kArchCallJSFunction: { | 689 case kArchCallJSFunction: { |
659 EnsureSpaceForLazyDeopt(); | 690 EnsureSpaceForLazyDeopt(); |
660 Register func = i.InputRegister(0); | 691 Register func = i.InputRegister(0); |
661 if (FLAG_debug_code) { | 692 if (FLAG_debug_code) { |
662 // Check the function's context matches the context argument. | 693 // Check the function's context matches the context argument. |
663 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); | 694 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
664 __ Assert(equal, kWrongFunctionContext); | 695 __ Assert(equal, kWrongFunctionContext); |
665 } | 696 } |
666 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 697 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
667 frame_access_state()->ClearSPDelta(); | 698 frame_access_state()->ClearSPDelta(); |
668 RecordCallPosition(instr); | 699 RecordCallPosition(instr); |
669 break; | 700 break; |
670 } | 701 } |
| 702 case kArchTailCallJSFunctionFromJSFunction: |
671 case kArchTailCallJSFunction: { | 703 case kArchTailCallJSFunction: { |
672 Register func = i.InputRegister(0); | 704 Register func = i.InputRegister(0); |
673 if (FLAG_debug_code) { | 705 if (FLAG_debug_code) { |
674 // Check the function's context matches the context argument. | 706 // Check the function's context matches the context argument. |
675 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); | 707 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
676 __ Assert(equal, kWrongFunctionContext); | 708 __ Assert(equal, kWrongFunctionContext); |
677 } | 709 } |
678 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 710 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
679 AssembleDeconstructActivationRecord(stack_param_delta); | 711 AssembleDeconstructActivationRecord(stack_param_delta); |
| 712 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 713 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 714 i.TempRegister(0), i.TempRegister(1), |
| 715 i.TempRegister(2)); |
| 716 } |
680 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 717 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
681 frame_access_state()->ClearSPDelta(); | 718 frame_access_state()->ClearSPDelta(); |
682 break; | 719 break; |
683 } | 720 } |
684 case kArchPrepareCallCFunction: { | 721 case kArchPrepareCallCFunction: { |
685 // Frame alignment requires using FP-relative frame addressing. | 722 // Frame alignment requires using FP-relative frame addressing. |
686 frame_access_state()->SetFrameAccessToFP(); | 723 frame_access_state()->SetFrameAccessToFP(); |
687 int const num_parameters = MiscField::decode(instr->opcode()); | 724 int const num_parameters = MiscField::decode(instr->opcode()); |
688 __ PrepareCallCFunction(num_parameters); | 725 __ PrepareCallCFunction(num_parameters); |
689 break; | 726 break; |
(...skipping 1501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2228 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2192 __ Nop(padding_size); | 2229 __ Nop(padding_size); |
2193 } | 2230 } |
2194 } | 2231 } |
2195 | 2232 |
2196 #undef __ | 2233 #undef __ |
2197 | 2234 |
2198 } // namespace compiler | 2235 } // namespace compiler |
2199 } // namespace internal | 2236 } // namespace internal |
2200 } // namespace v8 | 2237 } // namespace v8 |
OLD | NEW |