Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Side by Side Diff: src/compiler/x64/code-generator-x64.cc

Issue 1460183002: [turbofan] Add general support for sp-based frame access (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Last comment addressed Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/pipeline.cc ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/compiler/code-generator-impl.h" 7 #include "src/compiler/code-generator-impl.h"
8 #include "src/compiler/gap-resolver.h" 8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/node-matchers.h" 9 #include "src/compiler/node-matchers.h"
10 #include "src/compiler/osr.h" 10 #include "src/compiler/osr.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 Constant constant = ToConstant(operand); 42 Constant constant = ToConstant(operand);
43 if (constant.type() == Constant::kFloat64) { 43 if (constant.type() == Constant::kFloat64) {
44 DCHECK_EQ(0, bit_cast<int64_t>(constant.ToFloat64())); 44 DCHECK_EQ(0, bit_cast<int64_t>(constant.ToFloat64()));
45 return Immediate(0); 45 return Immediate(0);
46 } 46 }
47 return Immediate(constant.ToInt32()); 47 return Immediate(constant.ToInt32());
48 } 48 }
49 49
50 Operand ToOperand(InstructionOperand* op, int extra = 0) { 50 Operand ToOperand(InstructionOperand* op, int extra = 0) {
51 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); 51 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
52 FrameOffset offset = 52 FrameOffset offset = frame_access_state()->GetFrameOffset(
53 linkage()->GetFrameOffset(AllocatedOperand::cast(op)->index(), frame()); 53 AllocatedOperand::cast(op)->index());
54 return Operand(offset.from_stack_pointer() ? rsp : rbp, 54 return Operand(offset.from_stack_pointer() ? rsp : rbp,
55 offset.offset() + extra); 55 offset.offset() + extra);
56 } 56 }
57 57
58 static size_t NextOffset(size_t* offset) { 58 static size_t NextOffset(size_t* offset) {
59 size_t i = *offset; 59 size_t i = *offset;
60 (*offset)++; 60 (*offset)++;
61 return i; 61 return i;
62 } 62 }
63 63
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \ 571 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \
572 } \ 572 } \
573 } while (false) 573 } while (false)
574 574
575 575
576 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 576 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
577 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 577 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
578 if (sp_slot_delta > 0) { 578 if (sp_slot_delta > 0) {
579 __ addq(rsp, Immediate(sp_slot_delta * kPointerSize)); 579 __ addq(rsp, Immediate(sp_slot_delta * kPointerSize));
580 } 580 }
581 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 581 if (frame()->needs_frame()) {
582 int spill_slots = frame()->GetSpillSlotCount();
583 bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0;
584 if (has_frame) {
585 __ popq(rbp); 582 __ popq(rbp);
586 } 583 }
584 frame_access_state()->SetFrameAccessToDefault();
587 } 585 }
588 586
589 587
590 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 588 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
591 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 589 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
592 if (sp_slot_delta < 0) { 590 if (sp_slot_delta < 0) {
593 __ subq(rsp, Immediate(-sp_slot_delta * kPointerSize)); 591 __ subq(rsp, Immediate(-sp_slot_delta * kPointerSize));
592 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
594 } 593 }
594 frame_access_state()->SetFrameAccessToSP();
595 } 595 }
596 596
597 597
598 // Assembles an instruction after register allocation, producing machine code. 598 // Assembles an instruction after register allocation, producing machine code.
599 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { 599 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
600 X64OperandConverter i(this, instr); 600 X64OperandConverter i(this, instr);
601 601
602 switch (ArchOpcodeField::decode(instr->opcode())) { 602 switch (ArchOpcodeField::decode(instr->opcode())) {
603 case kArchCallCodeObject: { 603 case kArchCallCodeObject: {
604 EnsureSpaceForLazyDeopt(); 604 EnsureSpaceForLazyDeopt();
605 if (HasImmediateInput(instr, 0)) { 605 if (HasImmediateInput(instr, 0)) {
606 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 606 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
607 __ Call(code, RelocInfo::CODE_TARGET); 607 __ Call(code, RelocInfo::CODE_TARGET);
608 } else { 608 } else {
609 Register reg = i.InputRegister(0); 609 Register reg = i.InputRegister(0);
610 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 610 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
611 __ call(reg); 611 __ call(reg);
612 } 612 }
613 RecordCallPosition(instr); 613 RecordCallPosition(instr);
614 frame_access_state()->ClearSPDelta();
614 break; 615 break;
615 } 616 }
616 case kArchTailCallCodeObject: { 617 case kArchTailCallCodeObject: {
617 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 618 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
618 AssembleDeconstructActivationRecord(stack_param_delta); 619 AssembleDeconstructActivationRecord(stack_param_delta);
619 if (HasImmediateInput(instr, 0)) { 620 if (HasImmediateInput(instr, 0)) {
620 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 621 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
621 __ jmp(code, RelocInfo::CODE_TARGET); 622 __ jmp(code, RelocInfo::CODE_TARGET);
622 } else { 623 } else {
623 Register reg = i.InputRegister(0); 624 Register reg = i.InputRegister(0);
624 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 625 __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
625 __ jmp(reg); 626 __ jmp(reg);
626 } 627 }
628 frame_access_state()->ClearSPDelta();
627 break; 629 break;
628 } 630 }
629 case kArchCallJSFunction: { 631 case kArchCallJSFunction: {
630 EnsureSpaceForLazyDeopt(); 632 EnsureSpaceForLazyDeopt();
631 Register func = i.InputRegister(0); 633 Register func = i.InputRegister(0);
632 if (FLAG_debug_code) { 634 if (FLAG_debug_code) {
633 // Check the function's context matches the context argument. 635 // Check the function's context matches the context argument.
634 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); 636 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
635 __ Assert(equal, kWrongFunctionContext); 637 __ Assert(equal, kWrongFunctionContext);
636 } 638 }
637 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset)); 639 __ Call(FieldOperand(func, JSFunction::kCodeEntryOffset));
640 frame_access_state()->ClearSPDelta();
638 RecordCallPosition(instr); 641 RecordCallPosition(instr);
639 break; 642 break;
640 } 643 }
641 case kArchTailCallJSFunction: { 644 case kArchTailCallJSFunction: {
642 Register func = i.InputRegister(0); 645 Register func = i.InputRegister(0);
643 if (FLAG_debug_code) { 646 if (FLAG_debug_code) {
644 // Check the function's context matches the context argument. 647 // Check the function's context matches the context argument.
645 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); 648 __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
646 __ Assert(equal, kWrongFunctionContext); 649 __ Assert(equal, kWrongFunctionContext);
647 } 650 }
648 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 651 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
649 AssembleDeconstructActivationRecord(stack_param_delta); 652 AssembleDeconstructActivationRecord(stack_param_delta);
650 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); 653 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
654 frame_access_state()->ClearSPDelta();
651 break; 655 break;
652 } 656 }
653 case kArchLazyBailout: { 657 case kArchLazyBailout: {
654 EnsureSpaceForLazyDeopt(); 658 EnsureSpaceForLazyDeopt();
655 RecordCallPosition(instr); 659 RecordCallPosition(instr);
656 break; 660 break;
657 } 661 }
658 case kArchPrepareCallCFunction: { 662 case kArchPrepareCallCFunction: {
663 // Frame alignment requires using FP-relative frame addressing.
664 frame_access_state()->SetFrameAccessToFP();
659 int const num_parameters = MiscField::decode(instr->opcode()); 665 int const num_parameters = MiscField::decode(instr->opcode());
660 __ PrepareCallCFunction(num_parameters); 666 __ PrepareCallCFunction(num_parameters);
661 break; 667 break;
662 } 668 }
663 case kArchPrepareTailCall: 669 case kArchPrepareTailCall:
664 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 670 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
665 break; 671 break;
666 case kArchCallCFunction: { 672 case kArchCallCFunction: {
667 int const num_parameters = MiscField::decode(instr->opcode()); 673 int const num_parameters = MiscField::decode(instr->opcode());
668 if (HasImmediateInput(instr, 0)) { 674 if (HasImmediateInput(instr, 0)) {
669 ExternalReference ref = i.InputExternalReference(0); 675 ExternalReference ref = i.InputExternalReference(0);
670 __ CallCFunction(ref, num_parameters); 676 __ CallCFunction(ref, num_parameters);
671 } else { 677 } else {
672 Register func = i.InputRegister(0); 678 Register func = i.InputRegister(0);
673 __ CallCFunction(func, num_parameters); 679 __ CallCFunction(func, num_parameters);
674 } 680 }
681 frame_access_state()->SetFrameAccessToDefault();
682 frame_access_state()->ClearSPDelta();
675 break; 683 break;
676 } 684 }
677 case kArchJmp: 685 case kArchJmp:
678 AssembleArchJump(i.InputRpo(0)); 686 AssembleArchJump(i.InputRpo(0));
679 break; 687 break;
680 case kArchLookupSwitch: 688 case kArchLookupSwitch:
681 AssembleArchLookupSwitch(instr); 689 AssembleArchLookupSwitch(instr);
682 break; 690 break;
683 case kArchTableSwitch: 691 case kArchTableSwitch:
684 AssembleArchTableSwitch(instr); 692 AssembleArchTableSwitch(instr);
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 break; 1436 break;
1429 case kX64Dec32: 1437 case kX64Dec32:
1430 __ decl(i.OutputRegister()); 1438 __ decl(i.OutputRegister());
1431 break; 1439 break;
1432 case kX64Inc32: 1440 case kX64Inc32:
1433 __ incl(i.OutputRegister()); 1441 __ incl(i.OutputRegister());
1434 break; 1442 break;
1435 case kX64Push: 1443 case kX64Push:
1436 if (HasImmediateInput(instr, 0)) { 1444 if (HasImmediateInput(instr, 0)) {
1437 __ pushq(i.InputImmediate(0)); 1445 __ pushq(i.InputImmediate(0));
1446 frame_access_state()->IncreaseSPDelta(1);
1438 } else { 1447 } else {
1439 if (instr->InputAt(0)->IsRegister()) { 1448 if (instr->InputAt(0)->IsRegister()) {
1440 __ pushq(i.InputRegister(0)); 1449 __ pushq(i.InputRegister(0));
1450 frame_access_state()->IncreaseSPDelta(1);
1441 } else if (instr->InputAt(0)->IsDoubleRegister()) { 1451 } else if (instr->InputAt(0)->IsDoubleRegister()) {
1442 // TODO(titzer): use another machine instruction? 1452 // TODO(titzer): use another machine instruction?
1443 __ subq(rsp, Immediate(kDoubleSize)); 1453 __ subq(rsp, Immediate(kDoubleSize));
1454 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1444 __ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0)); 1455 __ Movsd(Operand(rsp, 0), i.InputDoubleRegister(0));
1445 } else { 1456 } else {
1446 __ pushq(i.InputOperand(0)); 1457 __ pushq(i.InputOperand(0));
1458 frame_access_state()->IncreaseSPDelta(1);
1447 } 1459 }
1448 } 1460 }
1449 break; 1461 break;
1450 case kX64Poke: { 1462 case kX64Poke: {
1451 int const slot = MiscField::decode(instr->opcode()); 1463 int const slot = MiscField::decode(instr->opcode());
1452 if (HasImmediateInput(instr, 0)) { 1464 if (HasImmediateInput(instr, 0)) {
1453 __ movq(Operand(rsp, slot * kPointerSize), i.InputImmediate(0)); 1465 __ movq(Operand(rsp, slot * kPointerSize), i.InputImmediate(0));
1454 } else { 1466 } else {
1455 __ movq(Operand(rsp, slot * kPointerSize), i.InputRegister(0)); 1467 __ movq(Operand(rsp, slot * kPointerSize), i.InputRegister(0));
1456 } 1468 }
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 1687
1676 namespace { 1688 namespace {
1677 1689
1678 static const int kQuadWordSize = 16; 1690 static const int kQuadWordSize = 16;
1679 1691
1680 } // namespace 1692 } // namespace
1681 1693
1682 1694
1683 void CodeGenerator::AssemblePrologue() { 1695 void CodeGenerator::AssemblePrologue() {
1684 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1696 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1685 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1697 if (descriptor->IsCFunctionCall()) {
1686 __ pushq(rbp); 1698 __ pushq(rbp);
1687 __ movq(rbp, rsp); 1699 __ movq(rbp, rsp);
1688 } else if (descriptor->IsJSFunctionCall()) { 1700 } else if (descriptor->IsJSFunctionCall()) {
1689 CompilationInfo* info = this->info(); 1701 CompilationInfo* info = this->info();
1690 __ Prologue(info->IsCodePreAgingActive()); 1702 __ Prologue(info->IsCodePreAgingActive());
1691 } else if (needs_frame_) { 1703 } else if (frame()->needs_frame()) {
1692 __ StubPrologue(); 1704 __ StubPrologue();
1693 } else { 1705 } else {
1694 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); 1706 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
1695 } 1707 }
1708 frame_access_state()->SetFrameAccessToDefault();
1696 1709
1697 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1710 int stack_shrink_slots = frame()->GetSpillSlotCount();
1698 if (info()->is_osr()) { 1711 if (info()->is_osr()) {
1699 // TurboFan OSR-compiled functions cannot be entered directly. 1712 // TurboFan OSR-compiled functions cannot be entered directly.
1700 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1713 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1701 1714
1702 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1715 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1703 // frame is still on the stack. Optimized code uses OSR values directly from 1716 // frame is still on the stack. Optimized code uses OSR values directly from
1704 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1717 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1705 // remaining stack slots. 1718 // remaining stack slots.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { 1780 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1768 if (!((1 << i) & saves_fp)) continue; 1781 if (!((1 << i) & saves_fp)) continue;
1769 __ movdqu(XMMRegister::from_code(i), 1782 __ movdqu(XMMRegister::from_code(i),
1770 Operand(rsp, kQuadWordSize * slot_idx)); 1783 Operand(rsp, kQuadWordSize * slot_idx));
1771 slot_idx++; 1784 slot_idx++;
1772 } 1785 }
1773 // Adjust the stack pointer. 1786 // Adjust the stack pointer.
1774 __ addp(rsp, Immediate(stack_size)); 1787 __ addp(rsp, Immediate(stack_size));
1775 } 1788 }
1776 1789
1777 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1790 if (descriptor->IsCFunctionCall()) {
1778 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. 1791 __ movq(rsp, rbp); // Move stack pointer back to frame pointer.
1779 __ popq(rbp); // Pop caller's frame pointer. 1792 __ popq(rbp); // Pop caller's frame pointer.
1780 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { 1793 } else if (frame()->needs_frame()) {
1781 // Canonicalize JSFunction return sites for now. 1794 // Canonicalize JSFunction return sites for now.
1782 if (return_label_.is_bound()) { 1795 if (return_label_.is_bound()) {
1783 __ jmp(&return_label_); 1796 __ jmp(&return_label_);
1784 return; 1797 return;
1785 } else { 1798 } else {
1786 __ bind(&return_label_); 1799 __ bind(&return_label_);
1787 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. 1800 __ movq(rsp, rbp); // Move stack pointer back to frame pointer.
1788 __ popq(rbp); // Pop caller's frame pointer. 1801 __ popq(rbp); // Pop caller's frame pointer.
1789 } 1802 }
1790 } 1803 }
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; 1997 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
1985 __ Nop(padding_size); 1998 __ Nop(padding_size);
1986 } 1999 }
1987 } 2000 }
1988 2001
1989 #undef __ 2002 #undef __
1990 2003
1991 } // namespace compiler 2004 } // namespace compiler
1992 } // namespace internal 2005 } // namespace internal
1993 } // namespace v8 2006 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/pipeline.cc ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698