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

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: ia32 port, addressed 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
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 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698