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 |
629 switch (ArchOpcodeField::decode(instr->opcode())) { | 653 switch (ArchOpcodeField::decode(instr->opcode())) { |
630 case kArchCallCodeObject: { | 654 case kArchCallCodeObject: { |
631 EnsureSpaceForLazyDeopt(); | 655 EnsureSpaceForLazyDeopt(); |
632 if (HasImmediateInput(instr, 0)) { | 656 if (HasImmediateInput(instr, 0)) { |
633 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 657 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
634 __ Call(code, RelocInfo::CODE_TARGET); | 658 __ Call(code, RelocInfo::CODE_TARGET); |
635 } else { | 659 } else { |
636 Register reg = i.InputRegister(0); | 660 Register reg = i.InputRegister(0); |
637 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 661 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
638 __ call(reg); | 662 __ call(reg); |
639 } | 663 } |
640 RecordCallPosition(instr); | 664 RecordCallPosition(instr); |
641 frame_access_state()->ClearSPDelta(); | 665 frame_access_state()->ClearSPDelta(); |
642 break; | 666 break; |
643 } | 667 } |
| 668 case kArchTailCallCodeObjectFromJSFunction: { |
| 669 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 670 AssembleDeconstructActivationRecord(stack_param_delta); |
| 671 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 672 i.TempRegister(0), i.TempRegister(1), |
| 673 i.TempRegister(2)); |
| 674 if (HasImmediateInput(instr, 0)) { |
| 675 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 676 __ jmp(code, RelocInfo::CODE_TARGET); |
| 677 } else { |
| 678 Register reg = i.InputRegister(0); |
| 679 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 680 __ jmp(reg); |
| 681 } |
| 682 frame_access_state()->ClearSPDelta(); |
| 683 break; |
| 684 } |
644 case kArchTailCallCodeObject: { | 685 case kArchTailCallCodeObject: { |
645 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 686 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
646 AssembleDeconstructActivationRecord(stack_param_delta); | 687 AssembleDeconstructActivationRecord(stack_param_delta); |
647 if (HasImmediateInput(instr, 0)) { | 688 if (HasImmediateInput(instr, 0)) { |
648 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 689 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
649 __ jmp(code, RelocInfo::CODE_TARGET); | 690 __ jmp(code, RelocInfo::CODE_TARGET); |
650 } else { | 691 } else { |
651 Register reg = i.InputRegister(0); | 692 Register reg = i.InputRegister(0); |
652 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 693 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
653 __ jmp(reg); | 694 __ jmp(reg); |
654 } | 695 } |
655 frame_access_state()->ClearSPDelta(); | 696 frame_access_state()->ClearSPDelta(); |
656 break; | 697 break; |
657 } | 698 } |
658 case kArchCallJSFunction: { | 699 case kArchCallJSFunction: { |
659 EnsureSpaceForLazyDeopt(); | 700 EnsureSpaceForLazyDeopt(); |
660 Register func = i.InputRegister(0); | 701 Register func = i.InputRegister(0); |
661 if (FLAG_debug_code) { | 702 if (FLAG_debug_code) { |
662 // Check the function's context matches the context argument. | 703 // Check the function's context matches the context argument. |
663 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); | 704 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
664 __ Assert(equal, kWrongFunctionContext); | 705 __ Assert(equal, kWrongFunctionContext); |
665 } | 706 } |
666 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 707 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
667 frame_access_state()->ClearSPDelta(); | 708 frame_access_state()->ClearSPDelta(); |
668 RecordCallPosition(instr); | 709 RecordCallPosition(instr); |
669 break; | 710 break; |
670 } | 711 } |
| 712 case kArchTailCallJSFunctionFromJSFunction: { |
| 713 Register func = i.InputRegister(0); |
| 714 if (FLAG_debug_code) { |
| 715 // Check the function's context matches the context argument. |
| 716 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
| 717 __ Assert(equal, kWrongFunctionContext); |
| 718 } |
| 719 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 720 AssembleDeconstructActivationRecord(stack_param_delta); |
| 721 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 722 i.TempRegister(0), i.TempRegister(1), |
| 723 i.TempRegister(2)); |
| 724 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
| 725 frame_access_state()->ClearSPDelta(); |
| 726 break; |
| 727 } |
671 case kArchTailCallJSFunction: { | 728 case kArchTailCallJSFunction: { |
672 Register func = i.InputRegister(0); | 729 Register func = i.InputRegister(0); |
673 if (FLAG_debug_code) { | 730 if (FLAG_debug_code) { |
674 // Check the function's context matches the context argument. | 731 // Check the function's context matches the context argument. |
675 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); | 732 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); |
676 __ Assert(equal, kWrongFunctionContext); | 733 __ Assert(equal, kWrongFunctionContext); |
677 } | 734 } |
678 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 735 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
679 AssembleDeconstructActivationRecord(stack_param_delta); | 736 AssembleDeconstructActivationRecord(stack_param_delta); |
680 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 737 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
(...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2248 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2192 __ Nop(padding_size); | 2249 __ Nop(padding_size); |
2193 } | 2250 } |
2194 } | 2251 } |
2195 | 2252 |
2196 #undef __ | 2253 #undef __ |
2197 | 2254 |
2198 } // namespace compiler | 2255 } // namespace compiler |
2199 } // namespace internal | 2256 } // namespace internal |
2200 } // namespace v8 | 2257 } // namespace v8 |
OLD | NEW |