OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1526 | 1526 |
1527 | 1527 |
1528 intptr_t Assembler::FindImmediate(int32_t imm) { | 1528 intptr_t Assembler::FindImmediate(int32_t imm) { |
1529 return object_pool_wrapper_.FindImmediate(imm); | 1529 return object_pool_wrapper_.FindImmediate(imm); |
1530 } | 1530 } |
1531 | 1531 |
1532 | 1532 |
1533 // Uses a code sequence that can easily be decoded. | 1533 // Uses a code sequence that can easily be decoded. |
1534 void Assembler::LoadWordFromPoolOffset(Register rd, | 1534 void Assembler::LoadWordFromPoolOffset(Register rd, |
1535 int32_t offset, | 1535 int32_t offset, |
1536 Register pp, | |
1536 Condition cond) { | 1537 Condition cond) { |
1537 ASSERT(constant_pool_allowed()); | 1538 ASSERT((pp != PP) || constant_pool_allowed()); |
1538 ASSERT(rd != PP); | 1539 ASSERT(rd != pp); |
1539 int32_t offset_mask = 0; | 1540 int32_t offset_mask = 0; |
1540 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { | 1541 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { |
1541 ldr(rd, Address(PP, offset), cond); | 1542 ldr(rd, Address(pp, offset), cond); |
1542 } else { | 1543 } else { |
1543 int32_t offset_hi = offset & ~offset_mask; // signed | 1544 int32_t offset_hi = offset & ~offset_mask; // signed |
1544 uint32_t offset_lo = offset & offset_mask; // unsigned | 1545 uint32_t offset_lo = offset & offset_mask; // unsigned |
1545 // Inline a simplified version of AddImmediate(rd, PP, offset_hi). | 1546 // Inline a simplified version of AddImmediate(rd, pp, offset_hi). |
1546 Operand o; | 1547 Operand o; |
1547 if (Operand::CanHold(offset_hi, &o)) { | 1548 if (Operand::CanHold(offset_hi, &o)) { |
1548 add(rd, PP, o, cond); | 1549 add(rd, pp, o, cond); |
1549 } else { | 1550 } else { |
1550 LoadImmediate(rd, offset_hi, cond); | 1551 LoadImmediate(rd, offset_hi, cond); |
1551 add(rd, PP, Operand(rd), cond); | 1552 add(rd, pp, Operand(rd), cond); |
1552 } | 1553 } |
1553 ldr(rd, Address(rd, offset_lo), cond); | 1554 ldr(rd, Address(rd, offset_lo), cond); |
1554 } | 1555 } |
1555 } | 1556 } |
1556 | 1557 |
1558 void Assembler::CheckCodePointer() { | |
1559 #ifdef DEBUG | |
rmacnak
2015/09/12 23:12:43
This seems a bit heavy even for debug mode. When f
Florian Schneider
2015/09/14 11:15:15
Yes, it is, but my guess is that in DEBUG mode, ge
| |
1560 Label cid_ok, instructions_ok; | |
1561 Push(R0); | |
1562 Push(IP); | |
1563 CompareClassId(CODE_REG, kCodeCid, R0); | |
1564 b(&cid_ok, EQ); | |
1565 bkpt(0); | |
1566 Bind(&cid_ok); | |
1557 | 1567 |
1558 void Assembler::LoadPoolPointer() { | 1568 const intptr_t offset = CodeSize() + Instr::kPCReadOffset; |
1559 const intptr_t object_pool_pc_dist = | 1569 mov(R0, Operand(PC)); |
1560 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1570 AddImmediate(R0, R0, -offset); |
1561 CodeSize() + Instr::kPCReadOffset; | 1571 ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset())); |
1562 LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist); | 1572 cmp(R0, Operand(IP)); |
1563 set_constant_pool_allowed(true); | 1573 b(&instructions_ok, EQ); |
1574 bkpt(1); | |
1575 Bind(&instructions_ok); | |
1576 Pop(IP); | |
1577 Pop(R0); | |
1578 #endif | |
1564 } | 1579 } |
1565 | 1580 |
1566 | 1581 |
1582 void Assembler::RestoreCodePointer() { | |
1583 ldr(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize)); | |
1584 CheckCodePointer(); | |
1585 } | |
1586 | |
1587 | |
1588 void Assembler::LoadPoolPointer(Register reg) { | |
1589 // Load new pool pointer. | |
1590 CheckCodePointer(); | |
1591 ldr(reg, FieldAddress(CODE_REG, Code::object_pool_offset())); | |
1592 set_constant_pool_allowed(reg == PP); | |
1593 } | |
1594 | |
1595 | |
1567 void Assembler::LoadIsolate(Register rd) { | 1596 void Assembler::LoadIsolate(Register rd) { |
1568 ldr(rd, Address(THR, Thread::isolate_offset())); | 1597 ldr(rd, Address(THR, Thread::isolate_offset())); |
1569 } | 1598 } |
1570 | 1599 |
1571 | 1600 |
1572 void Assembler::LoadObjectHelper(Register rd, | 1601 void Assembler::LoadObjectHelper(Register rd, |
1573 const Object& object, | 1602 const Object& object, |
1574 Condition cond, | 1603 Condition cond, |
1575 bool is_unique) { | 1604 bool is_unique, |
1605 Register pp) { | |
1576 // Load common VM constants from the thread. This works also in places where | 1606 // Load common VM constants from the thread. This works also in places where |
1577 // no constant pool is set up (e.g. intrinsic code). | 1607 // no constant pool is set up (e.g. intrinsic code). |
1578 if (Thread::CanLoadFromThread(object)) { | 1608 if (Thread::CanLoadFromThread(object)) { |
1579 ldr(rd, Address(THR, Thread::OffsetFromThread(object)), cond); | 1609 ldr(rd, Address(THR, Thread::OffsetFromThread(object)), cond); |
1580 return; | 1610 return; |
1581 } | 1611 } |
1582 // Smis and VM heap objects are never relocated; do not use object pool. | 1612 // Smis and VM heap objects are never relocated; do not use object pool. |
1583 if (object.IsSmi()) { | 1613 if (object.IsSmi()) { |
1584 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); | 1614 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); |
1585 } else if (object.InVMHeap() || !constant_pool_allowed()) { | 1615 } else if (object.InVMHeap() || !constant_pool_allowed()) { |
1586 // Make sure that class CallPattern is able to decode this load immediate. | 1616 // Make sure that class CallPattern is able to decode this load immediate. |
1587 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); | 1617 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); |
1588 LoadImmediate(rd, object_raw, cond); | 1618 LoadImmediate(rd, object_raw, cond); |
1589 } else { | 1619 } else { |
1590 // Make sure that class CallPattern is able to decode this load from the | 1620 // Make sure that class CallPattern is able to decode this load from the |
1591 // object pool. | 1621 // object pool. |
1592 const int32_t offset = ObjectPool::element_offset( | 1622 const int32_t offset = ObjectPool::element_offset( |
1593 is_unique ? object_pool_wrapper_.AddObject(object) | 1623 is_unique ? object_pool_wrapper_.AddObject(object) |
1594 : object_pool_wrapper_.FindObject(object)); | 1624 : object_pool_wrapper_.FindObject(object)); |
1595 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); | 1625 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond); |
1596 } | 1626 } |
1597 } | 1627 } |
1598 | 1628 |
1599 | 1629 |
1600 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) { | 1630 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) { |
1601 LoadObjectHelper(rd, object, cond, false); | 1631 LoadObjectHelper(rd, object, cond, /* is_unique = */ false, PP); |
1602 } | 1632 } |
1603 | 1633 |
1604 | 1634 |
1605 void Assembler::LoadUniqueObject(Register rd, | 1635 void Assembler::LoadUniqueObject(Register rd, |
1606 const Object& object, | 1636 const Object& object, |
1607 Condition cond) { | 1637 Condition cond) { |
1608 LoadObjectHelper(rd, object, cond, true); | 1638 LoadObjectHelper(rd, object, cond, /* is_unique = */ true, PP); |
1609 } | 1639 } |
1610 | 1640 |
1611 | 1641 |
1612 void Assembler::LoadExternalLabel(Register rd, | 1642 void Assembler::LoadExternalLabel(Register rd, |
1613 const ExternalLabel* label, | 1643 const ExternalLabel* label, |
1614 Patchability patchable, | 1644 Patchability patchable, |
1615 Condition cond) { | 1645 Condition cond) { |
1616 const int32_t offset = ObjectPool::element_offset( | 1646 const int32_t offset = ObjectPool::element_offset( |
1617 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 1647 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
1618 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); | 1648 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond); |
1619 } | 1649 } |
1620 | 1650 |
1621 | 1651 |
1652 void Assembler::LoadFunctionFromCalleePool(Register dst, | |
1653 const Function& function, | |
1654 Register new_pp) { | |
1655 const int32_t offset = | |
1656 ObjectPool::element_offset(object_pool_wrapper_.FindObject(function)); | |
1657 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp, AL); | |
1658 } | |
1659 | |
1660 | |
1622 void Assembler::PushObject(const Object& object) { | 1661 void Assembler::PushObject(const Object& object) { |
1623 LoadObject(IP, object); | 1662 LoadObject(IP, object); |
1624 Push(IP); | 1663 Push(IP); |
1625 } | 1664 } |
1626 | 1665 |
1627 | 1666 |
1628 void Assembler::CompareObject(Register rn, const Object& object) { | 1667 void Assembler::CompareObject(Register rn, const Object& object) { |
1629 ASSERT(rn != IP); | 1668 ASSERT(rn != IP); |
1630 if (object.IsSmi()) { | 1669 if (object.IsSmi()) { |
1631 CompareImmediate(rn, reinterpret_cast<int32_t>(object.raw())); | 1670 CompareImmediate(rn, reinterpret_cast<int32_t>(object.raw())); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1805 bool can_value_be_smi) { | 1844 bool can_value_be_smi) { |
1806 ASSERT(object != value); | 1845 ASSERT(object != value); |
1807 VerifiedWrite(dest, value, kHeapObjectOrSmi); | 1846 VerifiedWrite(dest, value, kHeapObjectOrSmi); |
1808 Label done; | 1847 Label done; |
1809 if (can_value_be_smi) { | 1848 if (can_value_be_smi) { |
1810 StoreIntoObjectFilter(object, value, &done); | 1849 StoreIntoObjectFilter(object, value, &done); |
1811 } else { | 1850 } else { |
1812 StoreIntoObjectFilterNoSmi(object, value, &done); | 1851 StoreIntoObjectFilterNoSmi(object, value, &done); |
1813 } | 1852 } |
1814 // A store buffer update is required. | 1853 // A store buffer update is required. |
1815 RegList regs = (1 << LR); | 1854 RegList regs = (1 << CODE_REG) | (1 << LR); |
1816 if (value != R0) { | 1855 if (value != R0) { |
1817 regs |= (1 << R0); // Preserve R0. | 1856 regs |= (1 << R0); // Preserve R0. |
1818 } | 1857 } |
1819 PushList(regs); | 1858 PushList(regs); |
1820 if (object != R0) { | 1859 if (object != R0) { |
1821 mov(R0, Operand(object)); | 1860 mov(R0, Operand(object)); |
1822 } | 1861 } |
1862 ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset())); | |
1823 ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset())); | 1863 ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
1824 blx(LR); | 1864 blx(LR); |
1825 PopList(regs); | 1865 PopList(regs); |
1826 Bind(&done); | 1866 Bind(&done); |
1827 } | 1867 } |
1828 | 1868 |
1829 | 1869 |
1830 void Assembler::StoreIntoObjectOffset(Register object, | 1870 void Assembler::StoreIntoObjectOffset(Register object, |
1831 int32_t offset, | 1871 int32_t offset, |
1832 Register value, | 1872 Register value, |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2671 void Assembler::Vdivqs(QRegister qd, QRegister qn, QRegister qm) { | 2711 void Assembler::Vdivqs(QRegister qd, QRegister qn, QRegister qm) { |
2672 ASSERT(qd != QTMP); | 2712 ASSERT(qd != QTMP); |
2673 ASSERT(qn != QTMP); | 2713 ASSERT(qn != QTMP); |
2674 ASSERT(qm != QTMP); | 2714 ASSERT(qm != QTMP); |
2675 | 2715 |
2676 Vreciprocalqs(qd, qm); | 2716 Vreciprocalqs(qd, qm); |
2677 vmulqs(qd, qn, qd); | 2717 vmulqs(qd, qn, qd); |
2678 } | 2718 } |
2679 | 2719 |
2680 | 2720 |
2681 void Assembler::Branch(const StubEntry& stub_entry, Condition cond) { | 2721 void Assembler::Branch(const StubEntry& stub_entry, |
2682 // Address is never patched. | 2722 Patchability patchable, |
2683 LoadImmediate(IP, stub_entry.label().address(), cond); | 2723 Register pp, |
2724 Condition cond) { | |
2725 const Code& target_code = Code::Handle(stub_entry.code()); | |
2726 const int32_t offset = ObjectPool::element_offset( | |
2727 object_pool_wrapper_.FindObject(target_code, kPatchable)); | |
rmacnak
2015/09/12 23:12:44
patchable
Florian Schneider
2015/09/14 11:15:15
Done.
| |
2728 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp, cond); | |
2729 ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset()), cond); | |
2684 bx(IP, cond); | 2730 bx(IP, cond); |
2685 } | 2731 } |
2686 | 2732 |
2687 | 2733 |
2688 void Assembler::BranchPatchable(const StubEntry& stub_entry) { | 2734 void Assembler::BranchLink(const Code& target, Patchability patchable) { |
2689 // Use a fixed size code sequence, since a function prologue may be patched | 2735 // Make sure that class CallPattern is able to patch the label referred |
2690 // with this branch sequence. | 2736 // to by this code sequence. |
2691 // Contrarily to BranchLinkPatchable, BranchPatchable requires an instruction | 2737 // For added code robustness, use 'blx lr' in a patchable sequence and |
2692 // cache flush upon patching. | 2738 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
2693 LoadPatchableImmediate(IP, stub_entry.label().address()); | 2739 const int32_t offset = ObjectPool::element_offset( |
2694 bx(IP); | 2740 object_pool_wrapper_.FindObject(target, patchable)); |
2741 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP); | |
2742 ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset())); | |
2743 blx(LR); // Use blx instruction so that the return branch prediction works. | |
2744 } | |
2745 | |
2746 | |
2747 void Assembler::BranchLink(const StubEntry& stub_entry, | |
2748 Patchability patchable) { | |
2749 const Code& code = Code::Handle(stub_entry.code()); | |
2750 BranchLink(code, patchable); | |
2751 } | |
2752 | |
2753 | |
2754 void Assembler::BranchLinkPatchable(const Code& target) { | |
2755 BranchLink(target, kPatchable); | |
2695 } | 2756 } |
2696 | 2757 |
2697 | 2758 |
2698 void Assembler::BranchLink(const ExternalLabel* label) { | 2759 void Assembler::BranchLink(const ExternalLabel* label) { |
2699 LoadImmediate(LR, label->address()); // Target address is never patched. | 2760 LoadImmediate(LR, label->address()); // Target address is never patched. |
2700 blx(LR); // Use blx instruction so that the return branch prediction works. | 2761 blx(LR); // Use blx instruction so that the return branch prediction works. |
2701 } | 2762 } |
2702 | 2763 |
2703 | 2764 |
2704 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { | 2765 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
2705 // Make sure that class CallPattern is able to patch the label referred | 2766 BranchLinkPatchable(Code::Handle(stub_entry.code())); |
2706 // to by this code sequence. | |
2707 // For added code robustness, use 'blx lr' in a patchable sequence and | |
2708 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). | |
2709 const int32_t offset = ObjectPool::element_offset( | |
2710 object_pool_wrapper_.FindExternalLabel(label, patchable)); | |
2711 LoadWordFromPoolOffset(LR, offset - kHeapObjectTag); | |
2712 blx(LR); // Use blx instruction so that the return branch prediction works. | |
2713 } | 2767 } |
2714 | 2768 |
2715 | 2769 |
2716 void Assembler::BranchLink(const StubEntry& stub_entry, | |
2717 Patchability patchable) { | |
2718 BranchLink(&stub_entry.label(), patchable); | |
2719 } | |
2720 | |
2721 | |
2722 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { | |
2723 BranchLink(&stub_entry.label(), kPatchable); | |
2724 } | |
2725 | |
2726 | |
2727 void Assembler::BranchLinkOffset(Register base, int32_t offset) { | 2770 void Assembler::BranchLinkOffset(Register base, int32_t offset) { |
2728 ASSERT(base != PC); | 2771 ASSERT(base != PC); |
2729 ASSERT(base != IP); | 2772 ASSERT(base != IP); |
2730 LoadFromOffset(kWord, IP, base, offset); | 2773 LoadFromOffset(kWord, IP, base, offset); |
2731 blx(IP); // Use blx instruction so that the return branch prediction works. | 2774 blx(IP); // Use blx instruction so that the return branch prediction works. |
2732 } | 2775 } |
2733 | 2776 |
2734 | 2777 |
2735 void Assembler::LoadPatchableImmediate( | 2778 void Assembler::LoadPatchableImmediate( |
2736 Register rd, int32_t value, Condition cond) { | 2779 Register rd, int32_t value, Condition cond) { |
(...skipping 17 matching lines...) Expand all Loading... | |
2754 } | 2797 } |
2755 } | 2798 } |
2756 | 2799 |
2757 | 2800 |
2758 void Assembler::LoadDecodableImmediate( | 2801 void Assembler::LoadDecodableImmediate( |
2759 Register rd, int32_t value, Condition cond) { | 2802 Register rd, int32_t value, Condition cond) { |
2760 const ARMVersion version = TargetCPUFeatures::arm_version(); | 2803 const ARMVersion version = TargetCPUFeatures::arm_version(); |
2761 if ((version == ARMv5TE) || (version == ARMv6)) { | 2804 if ((version == ARMv5TE) || (version == ARMv6)) { |
2762 if (constant_pool_allowed()) { | 2805 if (constant_pool_allowed()) { |
2763 const int32_t offset = Array::element_offset(FindImmediate(value)); | 2806 const int32_t offset = Array::element_offset(FindImmediate(value)); |
2764 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 2807 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP); |
2765 } else { | 2808 } else { |
2766 LoadPatchableImmediate(rd, value, cond); | 2809 LoadPatchableImmediate(rd, value, cond); |
2767 } | 2810 } |
2768 } else { | 2811 } else { |
2769 ASSERT(version == ARMv7); | 2812 ASSERT(version == ARMv7); |
2770 movw(rd, Utils::Low16Bits(value), cond); | 2813 movw(rd, Utils::Low16Bits(value), cond); |
2771 const uint16_t value_high = Utils::High16Bits(value); | 2814 const uint16_t value_high = Utils::High16Bits(value); |
2772 if (value_high != 0) { | 2815 if (value_high != 0) { |
2773 movt(rd, value_high, cond); | 2816 movt(rd, value_high, cond); |
2774 } | 2817 } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3289 } | 3332 } |
3290 | 3333 |
3291 | 3334 |
3292 void Assembler::CallRuntime(const RuntimeEntry& entry, | 3335 void Assembler::CallRuntime(const RuntimeEntry& entry, |
3293 intptr_t argument_count) { | 3336 intptr_t argument_count) { |
3294 entry.Call(this, argument_count); | 3337 entry.Call(this, argument_count); |
3295 } | 3338 } |
3296 | 3339 |
3297 | 3340 |
3298 void Assembler::EnterDartFrame(intptr_t frame_size) { | 3341 void Assembler::EnterDartFrame(intptr_t frame_size) { |
3342 CheckCodePointer(); | |
3299 ASSERT(!constant_pool_allowed()); | 3343 ASSERT(!constant_pool_allowed()); |
3300 const intptr_t offset = CodeSize(); | |
3301 | 3344 |
3302 // Save PC in frame for fast identification of corresponding code. | 3345 // Registers are pushed in descending order: R9 | R10 | R11 | R14. |
3303 // Note that callee-saved registers can be added to the register list. | 3346 EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << LR), 0); |
3304 EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0); | |
3305 | |
3306 if (offset != 0) { | |
3307 // Adjust saved PC for any intrinsic code that could have been generated | |
3308 // before a frame is created. Use PP as temp register. | |
3309 ldr(PP, Address(FP, 2 * kWordSize)); | |
3310 AddImmediate(PP, PP, -offset); | |
3311 str(PP, Address(FP, 2 * kWordSize)); | |
3312 } | |
3313 | 3347 |
3314 // Setup pool pointer for this dart function. | 3348 // Setup pool pointer for this dart function. |
3315 LoadPoolPointer(); | 3349 LoadPoolPointer(); |
3316 | 3350 |
3317 // Reserve space for locals. | 3351 // Reserve space for locals. |
3318 AddImmediate(SP, -frame_size); | 3352 AddImmediate(SP, -frame_size); |
3319 } | 3353 } |
3320 | 3354 |
3321 | 3355 |
3322 // On entry to a function compiled for OSR, the caller's frame pointer, the | 3356 // On entry to a function compiled for OSR, the caller's frame pointer, the |
3323 // stack locals, and any copied parameters are already in place. The frame | 3357 // stack locals, and any copied parameters are already in place. The frame |
3324 // pointer is already set up. The PC marker is not correct for the | 3358 // pointer is already set up. The PC marker is not correct for the |
3325 // optimized function and there may be extra space for spill slots to | 3359 // optimized function and there may be extra space for spill slots to |
3326 // allocate. We must also set up the pool pointer for the function. | 3360 // allocate. We must also set up the pool pointer for the function. |
3327 void Assembler::EnterOsrFrame(intptr_t extra_size) { | 3361 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
3328 ASSERT(!constant_pool_allowed()); | 3362 ASSERT(!constant_pool_allowed()); |
3329 // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be | |
3330 // different from EntryPointToPcMarkerOffset(). | |
3331 const intptr_t offset = | |
3332 CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset(); | |
3333 | |
3334 Comment("EnterOsrFrame"); | 3363 Comment("EnterOsrFrame"); |
3335 mov(IP, Operand(PC)); | 3364 RestoreCodePointer(); |
3336 | |
3337 AddImmediate(IP, -offset); | |
3338 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); | |
3339 | |
3340 // Setup pool pointer for this dart function. | |
3341 LoadPoolPointer(); | 3365 LoadPoolPointer(); |
3342 | 3366 |
3343 AddImmediate(SP, -extra_size); | 3367 AddImmediate(SP, -extra_size); |
3344 } | 3368 } |
3345 | 3369 |
3346 | 3370 |
3347 void Assembler::LeaveDartFrame() { | 3371 void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
3348 set_constant_pool_allowed(false); | 3372 if (restore_pp == kRestoreCallerPP) { |
3349 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); | 3373 ldr(PP, Address(FP, kSavedCallerPpSlotFromFp * kWordSize)); |
3350 // Adjust SP for PC pushed in EnterDartFrame. | 3374 set_constant_pool_allowed(false); |
3351 AddImmediate(SP, kWordSize); | 3375 } |
3376 Drop(2); // Drop saved PP, PC marker. | |
3377 LeaveFrame((1 << FP) | (1 << LR)); | |
3352 } | 3378 } |
3353 | 3379 |
3354 | 3380 |
3355 void Assembler::EnterStubFrame() { | 3381 void Assembler::EnterStubFrame() { |
3356 set_constant_pool_allowed(false); | 3382 EnterDartFrame(0); |
3357 // Push 0 as saved PC for stub frames. | |
rmacnak
2015/09/12 23:12:44
GC stack walker should be able to assert the pc-ma
Florian Schneider
2015/09/14 11:15:15
Done. Added assertion to StackFrame::GetCodeObject
| |
3358 mov(IP, Operand(LR)); | |
3359 mov(LR, Operand(0)); | |
3360 RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR); | |
3361 EnterFrame(regs, 0); | |
3362 // Setup pool pointer for this stub. | |
3363 LoadPoolPointer(); | |
3364 } | 3383 } |
3365 | 3384 |
3366 | 3385 |
3367 void Assembler::LeaveStubFrame() { | 3386 void Assembler::LeaveStubFrame() { |
3368 LeaveDartFrame(); | 3387 LeaveDartFrame(); |
3369 } | 3388 } |
3370 | 3389 |
3371 | 3390 |
3372 void Assembler::LoadAllocationStatsAddress(Register dest, | 3391 void Assembler::LoadAllocationStatsAddress(Register dest, |
3373 intptr_t cid, | 3392 intptr_t cid, |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3653 | 3672 |
3654 | 3673 |
3655 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3674 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3656 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 3675 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
3657 return fpu_reg_names[reg]; | 3676 return fpu_reg_names[reg]; |
3658 } | 3677 } |
3659 | 3678 |
3660 } // namespace dart | 3679 } // namespace dart |
3661 | 3680 |
3662 #endif // defined TARGET_ARCH_ARM | 3681 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |