| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 bool FlowGraphCompiler::SupportsUnboxedSimd128() { | 50 bool FlowGraphCompiler::SupportsUnboxedSimd128() { |
| 51 return FLAG_enable_simd_inline; | 51 return FLAG_enable_simd_inline; |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 bool FlowGraphCompiler::SupportsSinCos() { | 55 bool FlowGraphCompiler::SupportsSinCos() { |
| 56 return false; | 56 return false; |
| 57 } | 57 } |
| 58 | 58 |
| 59 | 59 |
| 60 void FlowGraphCompiler::EnterIntrinsicMode() { |
| 61 ASSERT(!intrinsic_mode()); |
| 62 intrinsic_mode_ = true; |
| 63 assembler()->set_allow_constant_pool(false); |
| 64 } |
| 65 |
| 66 |
| 67 void FlowGraphCompiler::ExitIntrinsicMode() { |
| 68 ASSERT(intrinsic_mode()); |
| 69 intrinsic_mode_ = false; |
| 70 assembler()->set_allow_constant_pool(true); |
| 71 } |
| 72 |
| 73 |
| 60 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, | 74 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, |
| 61 DeoptInfoBuilder* builder, | 75 DeoptInfoBuilder* builder, |
| 62 const Array& deopt_table) { | 76 const Array& deopt_table) { |
| 63 if (deopt_env_ == NULL) { | 77 if (deopt_env_ == NULL) { |
| 64 return DeoptInfo::null(); | 78 return DeoptInfo::null(); |
| 65 } | 79 } |
| 66 | 80 |
| 67 intptr_t stack_height = compiler->StackSize(); | 81 intptr_t stack_height = compiler->StackSize(); |
| 68 AllocateIncomingParametersRecursive(deopt_env_, &stack_height); | 82 AllocateIncomingParametersRecursive(deopt_env_, &stack_height); |
| 69 | 83 |
| (...skipping 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 MoveOperands* move = moves_[index]; | 1529 MoveOperands* move = moves_[index]; |
| 1516 const Location source = move->src(); | 1530 const Location source = move->src(); |
| 1517 const Location destination = move->dest(); | 1531 const Location destination = move->dest(); |
| 1518 | 1532 |
| 1519 if (source.IsRegister()) { | 1533 if (source.IsRegister()) { |
| 1520 if (destination.IsRegister()) { | 1534 if (destination.IsRegister()) { |
| 1521 __ mov(destination.reg(), source.reg()); | 1535 __ mov(destination.reg(), source.reg()); |
| 1522 } else { | 1536 } else { |
| 1523 ASSERT(destination.IsStackSlot()); | 1537 ASSERT(destination.IsStackSlot()); |
| 1524 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1538 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1525 __ StoreToOffset(source.reg(), FP, dest_offset, PP); | 1539 __ StoreToOffset(source.reg(), destination.base_reg(), dest_offset, PP); |
| 1526 } | 1540 } |
| 1527 } else if (source.IsStackSlot()) { | 1541 } else if (source.IsStackSlot()) { |
| 1528 if (destination.IsRegister()) { | 1542 if (destination.IsRegister()) { |
| 1529 const intptr_t source_offset = source.ToStackSlotOffset(); | 1543 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1530 __ LoadFromOffset(destination.reg(), FP, source_offset, PP); | 1544 __ LoadFromOffset( |
| 1545 destination.reg(), source.base_reg(), source_offset, PP); |
| 1531 } else { | 1546 } else { |
| 1532 ASSERT(destination.IsStackSlot()); | 1547 ASSERT(destination.IsStackSlot()); |
| 1533 const intptr_t source_offset = source.ToStackSlotOffset(); | 1548 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1534 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1549 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1535 __ LoadFromOffset(TMP, FP, source_offset, PP); | 1550 ScratchRegisterScope tmp(this, kNoRegister); |
| 1536 __ StoreToOffset(TMP, FP, dest_offset, PP); | 1551 __ LoadFromOffset(tmp.reg(), source.base_reg(), source_offset, PP); |
| 1552 __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP); |
| 1537 } | 1553 } |
| 1538 } else if (source.IsFpuRegister()) { | 1554 } else if (source.IsFpuRegister()) { |
| 1539 if (destination.IsFpuRegister()) { | 1555 if (destination.IsFpuRegister()) { |
| 1540 __ vmov(destination.fpu_reg(), source.fpu_reg()); | 1556 __ vmov(destination.fpu_reg(), source.fpu_reg()); |
| 1541 } else { | 1557 } else { |
| 1542 if (destination.IsDoubleStackSlot()) { | 1558 if (destination.IsDoubleStackSlot()) { |
| 1543 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1559 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1544 VRegister src = source.fpu_reg(); | 1560 VRegister src = source.fpu_reg(); |
| 1545 __ StoreDToOffset(src, FP, dest_offset, PP); | 1561 __ StoreDToOffset(src, destination.base_reg(), dest_offset, PP); |
| 1546 } else { | 1562 } else { |
| 1547 ASSERT(destination.IsQuadStackSlot()); | 1563 ASSERT(destination.IsQuadStackSlot()); |
| 1548 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1564 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1549 __ StoreQToOffset(source.fpu_reg(), FP, dest_offset, PP); | 1565 __ StoreQToOffset( |
| 1566 source.fpu_reg(), destination.base_reg(), dest_offset, PP); |
| 1550 } | 1567 } |
| 1551 } | 1568 } |
| 1552 } else if (source.IsDoubleStackSlot()) { | 1569 } else if (source.IsDoubleStackSlot()) { |
| 1553 if (destination.IsFpuRegister()) { | 1570 if (destination.IsFpuRegister()) { |
| 1554 const intptr_t dest_offset = source.ToStackSlotOffset(); | 1571 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1555 const VRegister dst = destination.fpu_reg(); | 1572 const VRegister dst = destination.fpu_reg(); |
| 1556 __ LoadDFromOffset(dst, FP, dest_offset, PP); | 1573 __ LoadDFromOffset(dst, source.base_reg(), source_offset, PP); |
| 1557 } else { | 1574 } else { |
| 1558 ASSERT(destination.IsDoubleStackSlot()); | 1575 ASSERT(destination.IsDoubleStackSlot()); |
| 1559 const intptr_t source_offset = source.ToStackSlotOffset(); | 1576 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1560 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1577 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1561 __ LoadDFromOffset(VTMP, FP, source_offset, PP); | 1578 __ LoadDFromOffset(VTMP, source.base_reg(), source_offset, PP); |
| 1562 __ StoreDToOffset(VTMP, FP, dest_offset, PP); | 1579 __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
| 1563 } | 1580 } |
| 1564 } else if (source.IsQuadStackSlot()) { | 1581 } else if (source.IsQuadStackSlot()) { |
| 1565 if (destination.IsFpuRegister()) { | 1582 if (destination.IsFpuRegister()) { |
| 1566 const intptr_t dest_offset = source.ToStackSlotOffset(); | 1583 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1567 __ LoadQFromOffset(destination.fpu_reg(), FP, dest_offset, PP); | 1584 __ LoadQFromOffset( |
| 1585 destination.fpu_reg(), source.base_reg(), source_offset, PP); |
| 1568 } else { | 1586 } else { |
| 1569 ASSERT(destination.IsQuadStackSlot()); | 1587 ASSERT(destination.IsQuadStackSlot()); |
| 1570 const intptr_t source_offset = source.ToStackSlotOffset(); | 1588 const intptr_t source_offset = source.ToStackSlotOffset(); |
| 1571 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1589 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1572 __ LoadQFromOffset(VTMP, FP, source_offset, PP); | 1590 __ LoadQFromOffset(VTMP, source.base_reg(), source_offset, PP); |
| 1573 __ StoreQToOffset(VTMP, FP, dest_offset, PP); | 1591 __ StoreQToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
| 1574 } | 1592 } |
| 1575 } else { | 1593 } else { |
| 1576 ASSERT(source.IsConstant()); | 1594 ASSERT(source.IsConstant()); |
| 1577 const Object& constant = source.constant(); | 1595 const Object& constant = source.constant(); |
| 1578 if (destination.IsRegister()) { | 1596 if (destination.IsRegister()) { |
| 1579 __ LoadObject(destination.reg(), constant, PP); | 1597 __ LoadObject(destination.reg(), constant, PP); |
| 1580 } else if (destination.IsFpuRegister()) { | 1598 } else if (destination.IsFpuRegister()) { |
| 1581 const VRegister dst = destination.fpu_reg(); | 1599 const VRegister dst = destination.fpu_reg(); |
| 1582 if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { | 1600 if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { |
| 1583 __ veor(dst, dst, dst); | 1601 __ veor(dst, dst, dst); |
| 1584 } else { | 1602 } else { |
| 1585 __ LoadObject(TMP, constant, PP); | 1603 ScratchRegisterScope tmp(this, kNoRegister); |
| 1586 __ LoadDFieldFromOffset(dst, TMP, Double::value_offset(), PP); | 1604 __ LoadObject(tmp.reg(), constant, PP); |
| 1605 __ LoadDFieldFromOffset(dst, tmp.reg(), Double::value_offset(), PP); |
| 1587 } | 1606 } |
| 1588 } else if (destination.IsDoubleStackSlot()) { | 1607 } else if (destination.IsDoubleStackSlot()) { |
| 1589 if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { | 1608 if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { |
| 1590 __ veor(VTMP, VTMP, VTMP); | 1609 __ veor(VTMP, VTMP, VTMP); |
| 1591 } else { | 1610 } else { |
| 1592 __ LoadObject(TMP, constant, PP); | 1611 ScratchRegisterScope tmp(this, kNoRegister); |
| 1593 __ LoadDFieldFromOffset(VTMP, TMP, Double::value_offset(), PP); | 1612 __ LoadObject(tmp.reg(), constant, PP); |
| 1613 __ LoadDFieldFromOffset(VTMP, tmp.reg(), Double::value_offset(), PP); |
| 1594 } | 1614 } |
| 1595 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1615 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1596 __ StoreDToOffset(VTMP, FP, dest_offset, PP); | 1616 __ StoreDToOffset(VTMP, destination.base_reg(), dest_offset, PP); |
| 1597 } else { | 1617 } else { |
| 1598 ASSERT(destination.IsStackSlot()); | 1618 ASSERT(destination.IsStackSlot()); |
| 1599 const intptr_t dest_offset = destination.ToStackSlotOffset(); | 1619 const intptr_t dest_offset = destination.ToStackSlotOffset(); |
| 1600 __ LoadObject(TMP, constant, PP); | 1620 ScratchRegisterScope tmp(this, kNoRegister); |
| 1601 __ StoreToOffset(TMP, FP, dest_offset, PP); | 1621 __ LoadObject(tmp.reg(), constant, PP); |
| 1622 __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset, PP); |
| 1602 } | 1623 } |
| 1603 } | 1624 } |
| 1604 | 1625 |
| 1605 move->Eliminate(); | 1626 move->Eliminate(); |
| 1606 } | 1627 } |
| 1607 | 1628 |
| 1608 | 1629 |
| 1609 void ParallelMoveResolver::EmitSwap(int index) { | 1630 void ParallelMoveResolver::EmitSwap(int index) { |
| 1610 MoveOperands* move = moves_[index]; | 1631 MoveOperands* move = moves_[index]; |
| 1611 const Location source = move->src(); | 1632 const Location source = move->src(); |
| 1612 const Location destination = move->dest(); | 1633 const Location destination = move->dest(); |
| 1613 | 1634 |
| 1614 if (source.IsRegister() && destination.IsRegister()) { | 1635 if (source.IsRegister() && destination.IsRegister()) { |
| 1615 ASSERT(source.reg() != TMP); | 1636 ASSERT(source.reg() != TMP); |
| 1616 ASSERT(destination.reg() != TMP); | 1637 ASSERT(destination.reg() != TMP); |
| 1617 __ mov(TMP, source.reg()); | 1638 __ mov(TMP, source.reg()); |
| 1618 __ mov(source.reg(), destination.reg()); | 1639 __ mov(source.reg(), destination.reg()); |
| 1619 __ mov(destination.reg(), TMP); | 1640 __ mov(destination.reg(), TMP); |
| 1620 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1641 } else if (source.IsRegister() && destination.IsStackSlot()) { |
| 1621 Exchange(source.reg(), destination.ToStackSlotOffset()); | 1642 Exchange(source.reg(), |
| 1643 destination.base_reg(), destination.ToStackSlotOffset()); |
| 1622 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1644 } else if (source.IsStackSlot() && destination.IsRegister()) { |
| 1623 Exchange(destination.reg(), source.ToStackSlotOffset()); | 1645 Exchange(destination.reg(), |
| 1646 source.base_reg(), source.ToStackSlotOffset()); |
| 1624 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1647 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
| 1625 Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset()); | 1648 Exchange(source.base_reg(), source.ToStackSlotOffset(), |
| 1649 destination.base_reg(), destination.ToStackSlotOffset()); |
| 1626 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { | 1650 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { |
| 1627 const VRegister dst = destination.fpu_reg(); | 1651 const VRegister dst = destination.fpu_reg(); |
| 1628 const VRegister src = source.fpu_reg(); | 1652 const VRegister src = source.fpu_reg(); |
| 1629 __ fmovdd(VTMP, src); | 1653 __ fmovdd(VTMP, src); |
| 1630 __ fmovdd(src, dst); | 1654 __ fmovdd(src, dst); |
| 1631 __ fmovdd(dst, VTMP); | 1655 __ fmovdd(dst, VTMP); |
| 1632 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { | 1656 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { |
| 1633 ASSERT(destination.IsDoubleStackSlot() || | 1657 ASSERT(destination.IsDoubleStackSlot() || |
| 1634 destination.IsQuadStackSlot() || | 1658 destination.IsQuadStackSlot() || |
| 1635 source.IsDoubleStackSlot() || | 1659 source.IsDoubleStackSlot() || |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1678 moves_[i]->set_src(destination); | 1702 moves_[i]->set_src(destination); |
| 1679 } else if (other_move.Blocks(destination)) { | 1703 } else if (other_move.Blocks(destination)) { |
| 1680 moves_[i]->set_src(source); | 1704 moves_[i]->set_src(source); |
| 1681 } | 1705 } |
| 1682 } | 1706 } |
| 1683 } | 1707 } |
| 1684 | 1708 |
| 1685 | 1709 |
| 1686 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, | 1710 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, |
| 1687 const Address& src) { | 1711 const Address& src) { |
| 1688 UNIMPLEMENTED(); | 1712 UNREACHABLE(); |
| 1689 } | 1713 } |
| 1690 | 1714 |
| 1691 | 1715 |
| 1692 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { | 1716 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { |
| 1693 UNIMPLEMENTED(); | 1717 UNREACHABLE(); |
| 1694 } | 1718 } |
| 1695 | 1719 |
| 1696 | 1720 |
| 1697 // Do not call or implement this function. Instead, use the form below that | 1721 // Do not call or implement this function. Instead, use the form below that |
| 1698 // uses an offset from the frame pointer instead of an Address. | 1722 // uses an offset from the frame pointer instead of an Address. |
| 1699 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { | 1723 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { |
| 1700 UNREACHABLE(); | 1724 UNREACHABLE(); |
| 1701 } | 1725 } |
| 1702 | 1726 |
| 1703 | 1727 |
| 1704 // Do not call or implement this function. Instead, use the form below that | 1728 // Do not call or implement this function. Instead, use the form below that |
| 1705 // uses offsets from the frame pointer instead of Addresses. | 1729 // uses offsets from the frame pointer instead of Addresses. |
| 1706 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1730 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1707 UNREACHABLE(); | 1731 UNREACHABLE(); |
| 1708 } | 1732 } |
| 1709 | 1733 |
| 1710 | 1734 |
| 1711 void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) { | 1735 void ParallelMoveResolver::Exchange(Register reg, |
| 1712 UNIMPLEMENTED(); | 1736 Register base_reg, |
| 1737 intptr_t stack_offset) { |
| 1738 ScratchRegisterScope tmp(this, kNoRegister); |
| 1739 __ mov(tmp.reg(), reg); |
| 1740 __ LoadFromOffset(reg, base_reg, stack_offset, PP); |
| 1741 __ StoreToOffset(tmp.reg(), base_reg, stack_offset, PP); |
| 1713 } | 1742 } |
| 1714 | 1743 |
| 1715 | 1744 |
| 1716 void ParallelMoveResolver::Exchange(intptr_t stack_offset1, | 1745 void ParallelMoveResolver::Exchange(Register base_reg1, |
| 1746 intptr_t stack_offset1, |
| 1747 Register base_reg2, |
| 1717 intptr_t stack_offset2) { | 1748 intptr_t stack_offset2) { |
| 1718 UNIMPLEMENTED(); | 1749 ScratchRegisterScope tmp1(this, kNoRegister); |
| 1750 ScratchRegisterScope tmp2(this, tmp1.reg()); |
| 1751 __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1, PP); |
| 1752 __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2, PP); |
| 1753 __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2, PP); |
| 1754 __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1, PP); |
| 1719 } | 1755 } |
| 1720 | 1756 |
| 1721 | 1757 |
| 1722 void ParallelMoveResolver::SpillScratch(Register reg) { | 1758 void ParallelMoveResolver::SpillScratch(Register reg) { |
| 1723 UNIMPLEMENTED(); | 1759 __ Push(reg); |
| 1724 } | 1760 } |
| 1725 | 1761 |
| 1726 | 1762 |
| 1727 void ParallelMoveResolver::RestoreScratch(Register reg) { | 1763 void ParallelMoveResolver::RestoreScratch(Register reg) { |
| 1728 UNIMPLEMENTED(); | 1764 __ Pop(reg); |
| 1729 } | 1765 } |
| 1730 | 1766 |
| 1731 | 1767 |
| 1732 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { | 1768 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { |
| 1733 UNIMPLEMENTED(); | 1769 __ PushDouble(reg); |
| 1734 } | 1770 } |
| 1735 | 1771 |
| 1736 | 1772 |
| 1737 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1773 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1738 UNIMPLEMENTED(); | 1774 __ PopDouble(reg); |
| 1739 } | 1775 } |
| 1740 | 1776 |
| 1741 | 1777 |
| 1742 #undef __ | 1778 #undef __ |
| 1743 | 1779 |
| 1744 } // namespace dart | 1780 } // namespace dart |
| 1745 | 1781 |
| 1746 #endif // defined TARGET_ARCH_ARM64 | 1782 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |