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

Side by Side Diff: runtime/vm/assembler_arm.cc

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed comments Created 5 years, 3 months 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 | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm64.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 (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 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 1527
1528 1528
1529 intptr_t Assembler::FindImmediate(int32_t imm) { 1529 intptr_t Assembler::FindImmediate(int32_t imm) {
1530 return object_pool_wrapper_.FindImmediate(imm); 1530 return object_pool_wrapper_.FindImmediate(imm);
1531 } 1531 }
1532 1532
1533 1533
1534 // Uses a code sequence that can easily be decoded. 1534 // Uses a code sequence that can easily be decoded.
1535 void Assembler::LoadWordFromPoolOffset(Register rd, 1535 void Assembler::LoadWordFromPoolOffset(Register rd,
1536 int32_t offset, 1536 int32_t offset,
1537 Register pp,
1537 Condition cond) { 1538 Condition cond) {
1538 ASSERT(constant_pool_allowed()); 1539 ASSERT((pp != PP) || constant_pool_allowed());
1539 ASSERT(rd != PP); 1540 ASSERT(rd != pp);
1540 int32_t offset_mask = 0; 1541 int32_t offset_mask = 0;
1541 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { 1542 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) {
1542 ldr(rd, Address(PP, offset), cond); 1543 ldr(rd, Address(pp, offset), cond);
1543 } else { 1544 } else {
1544 int32_t offset_hi = offset & ~offset_mask; // signed 1545 int32_t offset_hi = offset & ~offset_mask; // signed
1545 uint32_t offset_lo = offset & offset_mask; // unsigned 1546 uint32_t offset_lo = offset & offset_mask; // unsigned
1546 // Inline a simplified version of AddImmediate(rd, PP, offset_hi). 1547 // Inline a simplified version of AddImmediate(rd, pp, offset_hi).
1547 Operand o; 1548 Operand o;
1548 if (Operand::CanHold(offset_hi, &o)) { 1549 if (Operand::CanHold(offset_hi, &o)) {
1549 add(rd, PP, o, cond); 1550 add(rd, pp, o, cond);
1550 } else { 1551 } else {
1551 LoadImmediate(rd, offset_hi, cond); 1552 LoadImmediate(rd, offset_hi, cond);
1552 add(rd, PP, Operand(rd), cond); 1553 add(rd, pp, Operand(rd), cond);
1553 } 1554 }
1554 ldr(rd, Address(rd, offset_lo), cond); 1555 ldr(rd, Address(rd, offset_lo), cond);
1555 } 1556 }
1556 } 1557 }
1557 1558
1559 void Assembler::CheckCodePointer() {
1560 #ifdef DEBUG
1561 Label cid_ok, instructions_ok;
1562 Push(R0);
1563 Push(IP);
1564 CompareClassId(CODE_REG, kCodeCid, R0);
1565 b(&cid_ok, EQ);
1566 bkpt(0);
1567 Bind(&cid_ok);
1558 1568
1559 void Assembler::LoadPoolPointer() { 1569 const intptr_t offset = CodeSize() + Instr::kPCReadOffset +
1560 const intptr_t object_pool_pc_dist = 1570 Instructions::HeaderSize() - kHeapObjectTag;
1561 Instructions::HeaderSize() - Instructions::object_pool_offset() + 1571 mov(R0, Operand(PC));
1562 CodeSize() + Instr::kPCReadOffset; 1572 AddImmediate(R0, R0, -offset);
1563 LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist); 1573 ldr(IP, FieldAddress(CODE_REG, Code::saved_instructions_offset()));
1564 set_constant_pool_allowed(true); 1574 cmp(R0, Operand(IP));
1575 b(&instructions_ok, EQ);
1576 bkpt(1);
1577 Bind(&instructions_ok);
1578 Pop(IP);
1579 Pop(R0);
1580 #endif
1565 } 1581 }
1566 1582
1567 1583
1584 void Assembler::RestoreCodePointer() {
1585 ldr(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize));
1586 CheckCodePointer();
1587 }
1588
1589
1590 void Assembler::LoadPoolPointer(Register reg) {
1591 // Load new pool pointer.
1592 CheckCodePointer();
1593 ldr(reg, FieldAddress(CODE_REG, Code::object_pool_offset()));
1594 set_constant_pool_allowed(reg == PP);
1595 }
1596
1597
1568 void Assembler::LoadIsolate(Register rd) { 1598 void Assembler::LoadIsolate(Register rd) {
1569 ldr(rd, Address(THR, Thread::isolate_offset())); 1599 ldr(rd, Address(THR, Thread::isolate_offset()));
1570 } 1600 }
1571 1601
1572 1602
1573 bool Assembler::CanLoadFromObjectPool(const Object& object) const { 1603 bool Assembler::CanLoadFromObjectPool(const Object& object) const {
1574 ASSERT(!Thread::CanLoadFromThread(object)); 1604 ASSERT(!Thread::CanLoadFromThread(object));
1575 if (!constant_pool_allowed()) { 1605 if (!constant_pool_allowed()) {
1576 return false; 1606 return false;
1577 } 1607 }
1578 1608
1579 ASSERT(object.IsNotTemporaryScopedHandle()); 1609 ASSERT(object.IsNotTemporaryScopedHandle());
1580 ASSERT(object.IsOld()); 1610 ASSERT(object.IsOld());
1581 return true; 1611 return true;
1582 } 1612 }
1583 1613
1584 1614
1585 void Assembler::LoadObjectHelper(Register rd, 1615 void Assembler::LoadObjectHelper(Register rd,
1586 const Object& object, 1616 const Object& object,
1587 Condition cond, 1617 Condition cond,
1588 bool is_unique) { 1618 bool is_unique,
1619 Register pp) {
1620 // Load common VM constants from the thread. This works also in places where
1621 // no constant pool is set up (e.g. intrinsic code).
1589 if (Thread::CanLoadFromThread(object)) { 1622 if (Thread::CanLoadFromThread(object)) {
1590 // Load common VM constants from the thread. This works also in places where 1623 // Load common VM constants from the thread. This works also in places where
1591 // no constant pool is set up (e.g. intrinsic code). 1624 // no constant pool is set up (e.g. intrinsic code).
1592 ldr(rd, Address(THR, Thread::OffsetFromThread(object)), cond); 1625 ldr(rd, Address(THR, Thread::OffsetFromThread(object)), cond);
1593 } else if (object.IsSmi()) { 1626 } else if (object.IsSmi()) {
1594 // Relocation doesn't apply to Smis. 1627 // Relocation doesn't apply to Smis.
1595 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); 1628 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond);
1596 } else if (CanLoadFromObjectPool(object)) { 1629 } else if (CanLoadFromObjectPool(object)) {
1597 // Make sure that class CallPattern is able to decode this load from the 1630 // Make sure that class CallPattern is able to decode this load from the
1598 // object pool. 1631 // object pool.
1599 const int32_t offset = ObjectPool::element_offset( 1632 const int32_t offset = ObjectPool::element_offset(
1600 is_unique ? object_pool_wrapper_.AddObject(object) 1633 is_unique ? object_pool_wrapper_.AddObject(object)
1601 : object_pool_wrapper_.FindObject(object)); 1634 : object_pool_wrapper_.FindObject(object));
1602 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); 1635 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
1603 } else { 1636 } else {
1604 ASSERT(FLAG_allow_absolute_addresses); 1637 ASSERT(FLAG_allow_absolute_addresses);
1605 ASSERT(object.IsOld()); 1638 ASSERT(object.IsOld());
1606 // Make sure that class CallPattern is able to decode this load immediate. 1639 // Make sure that class CallPattern is able to decode this load immediate.
1607 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); 1640 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
1608 LoadImmediate(rd, object_raw, cond); 1641 LoadImmediate(rd, object_raw, cond);
1609 } 1642 }
1610 } 1643 }
1611 1644
1612 1645
1613 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) { 1646 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) {
1614 LoadObjectHelper(rd, object, cond, false); 1647 LoadObjectHelper(rd, object, cond, /* is_unique = */ false, PP);
1615 } 1648 }
1616 1649
1617 1650
1618 void Assembler::LoadUniqueObject(Register rd, 1651 void Assembler::LoadUniqueObject(Register rd,
1619 const Object& object, 1652 const Object& object,
1620 Condition cond) { 1653 Condition cond) {
1621 LoadObjectHelper(rd, object, cond, true); 1654 LoadObjectHelper(rd, object, cond, /* is_unique = */ true, PP);
1622 } 1655 }
1623 1656
1624 1657
1625 void Assembler::LoadExternalLabel(Register rd, 1658 void Assembler::LoadExternalLabel(Register rd,
1626 const ExternalLabel* label, 1659 const ExternalLabel* label,
1627 Patchability patchable, 1660 Patchability patchable,
1628 Condition cond) { 1661 Condition cond) {
1629 const int32_t offset = ObjectPool::element_offset( 1662 const int32_t offset = ObjectPool::element_offset(
1630 object_pool_wrapper_.FindExternalLabel(label, patchable)); 1663 object_pool_wrapper_.FindExternalLabel(label, patchable));
1631 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); 1664 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
1632 } 1665 }
1633 1666
1634 1667
1668 void Assembler::LoadFunctionFromCalleePool(Register dst,
1669 const Function& function,
1670 Register new_pp) {
1671 const int32_t offset =
1672 ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
1673 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp, AL);
1674 }
1675
1676
1635 void Assembler::LoadNativeEntry(Register rd, 1677 void Assembler::LoadNativeEntry(Register rd,
1636 const ExternalLabel* label, 1678 const ExternalLabel* label,
1637 Patchability patchable, 1679 Patchability patchable,
1638 Condition cond) { 1680 Condition cond) {
1639 const int32_t offset = ObjectPool::element_offset( 1681 const int32_t offset = ObjectPool::element_offset(
1640 object_pool_wrapper_.FindNativeEntry(label, patchable)); 1682 object_pool_wrapper_.FindNativeEntry(label, patchable));
1641 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); 1683 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
1642 } 1684 }
1643 1685
1644 1686
1645 void Assembler::PushObject(const Object& object) { 1687 void Assembler::PushObject(const Object& object) {
1646 LoadObject(IP, object); 1688 LoadObject(IP, object);
1647 Push(IP); 1689 Push(IP);
1648 } 1690 }
1649 1691
1650 1692
1651 void Assembler::CompareObject(Register rn, const Object& object) { 1693 void Assembler::CompareObject(Register rn, const Object& object) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1828 bool can_value_be_smi) { 1870 bool can_value_be_smi) {
1829 ASSERT(object != value); 1871 ASSERT(object != value);
1830 VerifiedWrite(dest, value, kHeapObjectOrSmi); 1872 VerifiedWrite(dest, value, kHeapObjectOrSmi);
1831 Label done; 1873 Label done;
1832 if (can_value_be_smi) { 1874 if (can_value_be_smi) {
1833 StoreIntoObjectFilter(object, value, &done); 1875 StoreIntoObjectFilter(object, value, &done);
1834 } else { 1876 } else {
1835 StoreIntoObjectFilterNoSmi(object, value, &done); 1877 StoreIntoObjectFilterNoSmi(object, value, &done);
1836 } 1878 }
1837 // A store buffer update is required. 1879 // A store buffer update is required.
1838 RegList regs = (1 << LR); 1880 RegList regs = (1 << CODE_REG) | (1 << LR);
1839 if (value != R0) { 1881 if (value != R0) {
1840 regs |= (1 << R0); // Preserve R0. 1882 regs |= (1 << R0); // Preserve R0.
1841 } 1883 }
1842 PushList(regs); 1884 PushList(regs);
1843 if (object != R0) { 1885 if (object != R0) {
1844 mov(R0, Operand(object)); 1886 mov(R0, Operand(object));
1845 } 1887 }
1888 ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
1846 ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset())); 1889 ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset()));
1847 blx(LR); 1890 blx(LR);
1848 PopList(regs); 1891 PopList(regs);
1849 Bind(&done); 1892 Bind(&done);
1850 } 1893 }
1851 1894
1852 1895
1853 void Assembler::StoreIntoObjectOffset(Register object, 1896 void Assembler::StoreIntoObjectOffset(Register object,
1854 int32_t offset, 1897 int32_t offset,
1855 Register value, 1898 Register value,
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after
2691 void Assembler::Vdivqs(QRegister qd, QRegister qn, QRegister qm) { 2734 void Assembler::Vdivqs(QRegister qd, QRegister qn, QRegister qm) {
2692 ASSERT(qd != QTMP); 2735 ASSERT(qd != QTMP);
2693 ASSERT(qn != QTMP); 2736 ASSERT(qn != QTMP);
2694 ASSERT(qm != QTMP); 2737 ASSERT(qm != QTMP);
2695 2738
2696 Vreciprocalqs(qd, qm); 2739 Vreciprocalqs(qd, qm);
2697 vmulqs(qd, qn, qd); 2740 vmulqs(qd, qn, qd);
2698 } 2741 }
2699 2742
2700 2743
2701 void Assembler::Branch(const StubEntry& stub_entry, Condition cond) { 2744 void Assembler::Branch(const StubEntry& stub_entry,
2702 // Address is never patched. 2745 Patchability patchable,
2703 LoadImmediate(IP, stub_entry.label().address(), cond); 2746 Register pp,
2747 Condition cond) {
2748 const Code& target_code = Code::Handle(stub_entry.code());
2749 const int32_t offset = ObjectPool::element_offset(
2750 object_pool_wrapper_.FindObject(target_code, patchable));
2751 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp, cond);
2752 ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset()), cond);
2704 bx(IP, cond); 2753 bx(IP, cond);
2705 } 2754 }
2706 2755
2707 2756
2708 void Assembler::BranchPatchable(const StubEntry& stub_entry) { 2757 void Assembler::BranchLink(const Code& target, Patchability patchable) {
2709 // Use a fixed size code sequence, since a function prologue may be patched 2758 // Make sure that class CallPattern is able to patch the label referred
2710 // with this branch sequence. 2759 // to by this code sequence.
2711 // Contrarily to BranchLinkPatchable, BranchPatchable requires an instruction 2760 // For added code robustness, use 'blx lr' in a patchable sequence and
2712 // cache flush upon patching. 2761 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
2713 LoadPatchableImmediate(IP, stub_entry.label().address()); 2762 const int32_t offset = ObjectPool::element_offset(
2714 bx(IP); 2763 object_pool_wrapper_.FindObject(target, patchable));
2764 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP, AL);
2765 ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset()));
2766 blx(LR); // Use blx instruction so that the return branch prediction works.
2767 }
2768
2769
2770 void Assembler::BranchLink(const StubEntry& stub_entry,
2771 Patchability patchable) {
2772 const Code& code = Code::Handle(stub_entry.code());
2773 BranchLink(code, patchable);
2774 }
2775
2776
2777 void Assembler::BranchLinkPatchable(const Code& target) {
2778 BranchLink(target, kPatchable);
2715 } 2779 }
2716 2780
2717 2781
2718 void Assembler::BranchLink(const ExternalLabel* label) { 2782 void Assembler::BranchLink(const ExternalLabel* label) {
2719 LoadImmediate(LR, label->address()); // Target address is never patched. 2783 LoadImmediate(LR, label->address()); // Target address is never patched.
2720 blx(LR); // Use blx instruction so that the return branch prediction works. 2784 blx(LR); // Use blx instruction so that the return branch prediction works.
2721 } 2785 }
2722 2786
2723 2787
2724 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { 2788 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
2725 // Make sure that class CallPattern is able to patch the label referred 2789 BranchLinkPatchable(Code::Handle(stub_entry.code()));
2726 // to by this code sequence.
2727 // For added code robustness, use 'blx lr' in a patchable sequence and
2728 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
2729 const int32_t offset = ObjectPool::element_offset(
2730 object_pool_wrapper_.FindExternalLabel(label, patchable));
2731 LoadWordFromPoolOffset(LR, offset - kHeapObjectTag, AL);
2732 blx(LR); // Use blx instruction so that the return branch prediction works.
2733 } 2790 }
2734 2791
2735 2792
2736 void Assembler::BranchLink(const StubEntry& stub_entry,
2737 Patchability patchable) {
2738 BranchLink(&stub_entry.label(), patchable);
2739 }
2740
2741
2742 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
2743 BranchLink(&stub_entry.label(), kPatchable);
2744 }
2745
2746
2747 void Assembler::BranchLinkOffset(Register base, int32_t offset) { 2793 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
2748 ASSERT(base != PC); 2794 ASSERT(base != PC);
2749 ASSERT(base != IP); 2795 ASSERT(base != IP);
2750 LoadFromOffset(kWord, IP, base, offset); 2796 LoadFromOffset(kWord, IP, base, offset);
2751 blx(IP); // Use blx instruction so that the return branch prediction works. 2797 blx(IP); // Use blx instruction so that the return branch prediction works.
2752 } 2798 }
2753 2799
2754 2800
2755 void Assembler::LoadPatchableImmediate( 2801 void Assembler::LoadPatchableImmediate(
2756 Register rd, int32_t value, Condition cond) { 2802 Register rd, int32_t value, Condition cond) {
(...skipping 17 matching lines...) Expand all
2774 } 2820 }
2775 } 2821 }
2776 2822
2777 2823
2778 void Assembler::LoadDecodableImmediate( 2824 void Assembler::LoadDecodableImmediate(
2779 Register rd, int32_t value, Condition cond) { 2825 Register rd, int32_t value, Condition cond) {
2780 const ARMVersion version = TargetCPUFeatures::arm_version(); 2826 const ARMVersion version = TargetCPUFeatures::arm_version();
2781 if ((version == ARMv5TE) || (version == ARMv6)) { 2827 if ((version == ARMv5TE) || (version == ARMv6)) {
2782 if (constant_pool_allowed()) { 2828 if (constant_pool_allowed()) {
2783 const int32_t offset = Array::element_offset(FindImmediate(value)); 2829 const int32_t offset = Array::element_offset(FindImmediate(value));
2784 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond); 2830 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
2785 } else { 2831 } else {
2786 LoadPatchableImmediate(rd, value, cond); 2832 LoadPatchableImmediate(rd, value, cond);
2787 } 2833 }
2788 } else { 2834 } else {
2789 ASSERT(version == ARMv7); 2835 ASSERT(version == ARMv7);
2790 movw(rd, Utils::Low16Bits(value), cond); 2836 movw(rd, Utils::Low16Bits(value), cond);
2791 const uint16_t value_high = Utils::High16Bits(value); 2837 const uint16_t value_high = Utils::High16Bits(value);
2792 if (value_high != 0) { 2838 if (value_high != 0) {
2793 movt(rd, value_high, cond); 2839 movt(rd, value_high, cond);
2794 } 2840 }
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
3310 3356
3311 3357
3312 void Assembler::CallRuntime(const RuntimeEntry& entry, 3358 void Assembler::CallRuntime(const RuntimeEntry& entry,
3313 intptr_t argument_count) { 3359 intptr_t argument_count) {
3314 entry.Call(this, argument_count); 3360 entry.Call(this, argument_count);
3315 } 3361 }
3316 3362
3317 3363
3318 void Assembler::EnterDartFrame(intptr_t frame_size) { 3364 void Assembler::EnterDartFrame(intptr_t frame_size) {
3319 ASSERT(!constant_pool_allowed()); 3365 ASSERT(!constant_pool_allowed());
3320 const intptr_t offset = CodeSize();
3321 3366
3322 // Save PC in frame for fast identification of corresponding code. 3367 // Registers are pushed in descending order: R9 | R10 | R11 | R14.
3323 // Note that callee-saved registers can be added to the register list. 3368 EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << LR), 0);
3324 EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
3325
3326 if (offset != 0) {
3327 // Adjust saved PC for any intrinsic code that could have been generated
3328 // before a frame is created. Use PP as temp register.
3329 ldr(PP, Address(FP, 2 * kWordSize));
3330 AddImmediate(PP, PP, -offset);
3331 str(PP, Address(FP, 2 * kWordSize));
3332 }
3333 3369
3334 // Setup pool pointer for this dart function. 3370 // Setup pool pointer for this dart function.
3335 LoadPoolPointer(); 3371 LoadPoolPointer();
3336 3372
3337 // Reserve space for locals. 3373 // Reserve space for locals.
3338 AddImmediate(SP, -frame_size); 3374 AddImmediate(SP, -frame_size);
3339 } 3375 }
3340 3376
3341 3377
3342 // On entry to a function compiled for OSR, the caller's frame pointer, the 3378 // On entry to a function compiled for OSR, the caller's frame pointer, the
3343 // stack locals, and any copied parameters are already in place. The frame 3379 // stack locals, and any copied parameters are already in place. The frame
3344 // pointer is already set up. The PC marker is not correct for the 3380 // pointer is already set up. The PC marker is not correct for the
3345 // optimized function and there may be extra space for spill slots to 3381 // optimized function and there may be extra space for spill slots to
3346 // allocate. We must also set up the pool pointer for the function. 3382 // allocate. We must also set up the pool pointer for the function.
3347 void Assembler::EnterOsrFrame(intptr_t extra_size) { 3383 void Assembler::EnterOsrFrame(intptr_t extra_size) {
3348 ASSERT(!constant_pool_allowed()); 3384 ASSERT(!constant_pool_allowed());
3349 // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be
3350 // different from EntryPointToPcMarkerOffset().
3351 const intptr_t offset =
3352 CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset();
3353
3354 Comment("EnterOsrFrame"); 3385 Comment("EnterOsrFrame");
3355 mov(IP, Operand(PC)); 3386 RestoreCodePointer();
3356
3357 AddImmediate(IP, -offset);
3358 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
3359
3360 // Setup pool pointer for this dart function.
3361 LoadPoolPointer(); 3387 LoadPoolPointer();
3362 3388
3363 AddImmediate(SP, -extra_size); 3389 AddImmediate(SP, -extra_size);
3364 } 3390 }
3365 3391
3366 3392
3367 void Assembler::LeaveDartFrame() { 3393 void Assembler::LeaveDartFrame(RestorePP restore_pp) {
3368 set_constant_pool_allowed(false); 3394 if (restore_pp == kRestoreCallerPP) {
3369 LeaveFrame((1 << PP) | (1 << FP) | (1 << LR)); 3395 ldr(PP, Address(FP, kSavedCallerPpSlotFromFp * kWordSize));
3370 // Adjust SP for PC pushed in EnterDartFrame. 3396 set_constant_pool_allowed(false);
3371 AddImmediate(SP, kWordSize); 3397 }
3398 Drop(2); // Drop saved PP, PC marker.
3399 LeaveFrame((1 << FP) | (1 << LR));
3372 } 3400 }
3373 3401
3374 3402
3375 void Assembler::EnterStubFrame() { 3403 void Assembler::EnterStubFrame() {
3376 set_constant_pool_allowed(false); 3404 EnterDartFrame(0);
3377 // Push 0 as saved PC for stub frames.
3378 mov(IP, Operand(LR));
3379 mov(LR, Operand(0));
3380 RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR);
3381 EnterFrame(regs, 0);
3382 // Setup pool pointer for this stub.
3383 LoadPoolPointer();
3384 } 3405 }
3385 3406
3386 3407
3387 void Assembler::LeaveStubFrame() { 3408 void Assembler::LeaveStubFrame() {
3388 LeaveDartFrame(); 3409 LeaveDartFrame();
3389 } 3410 }
3390 3411
3391 3412
3392 void Assembler::LoadAllocationStatsAddress(Register dest, 3413 void Assembler::LoadAllocationStatsAddress(Register dest,
3393 intptr_t cid, 3414 intptr_t cid,
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
3674 3695
3675 3696
3676 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3697 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3677 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 3698 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
3678 return fpu_reg_names[reg]; 3699 return fpu_reg_names[reg];
3679 } 3700 }
3680 3701
3681 } // namespace dart 3702 } // namespace dart
3682 3703
3683 #endif // defined TARGET_ARCH_ARM 3704 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698