| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 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 30 matching lines...) Expand all Loading... |
| 41 // Not adding Object::null() to the index table. It is at index 0 in the | 41 // Not adding Object::null() to the index table. It is at index 0 in the |
| 42 // object pool, but the HashMap uses 0 to indicate not found. | 42 // object pool, but the HashMap uses 0 to indicate not found. |
| 43 | 43 |
| 44 object_pool_.Add(Bool::True(), Heap::kOld); | 44 object_pool_.Add(Bool::True(), Heap::kOld); |
| 45 patchable_pool_entries_.Add(kNotPatchable); | 45 patchable_pool_entries_.Add(kNotPatchable); |
| 46 object_pool_index_table_.Insert(ObjIndexPair(Bool::True().raw(), 1)); | 46 object_pool_index_table_.Insert(ObjIndexPair(Bool::True().raw(), 1)); |
| 47 | 47 |
| 48 object_pool_.Add(Bool::False(), Heap::kOld); | 48 object_pool_.Add(Bool::False(), Heap::kOld); |
| 49 patchable_pool_entries_.Add(kNotPatchable); | 49 patchable_pool_entries_.Add(kNotPatchable); |
| 50 object_pool_index_table_.Insert(ObjIndexPair(Bool::False().raw(), 2)); | 50 object_pool_index_table_.Insert(ObjIndexPair(Bool::False().raw(), 2)); |
| 51 |
| 52 if (StubCode::UpdateStoreBuffer_entry() != NULL) { |
| 53 FindExternalLabel(&StubCode::UpdateStoreBufferLabel(), kNotPatchable); |
| 54 } else { |
| 55 object_pool_.Add(Object::null_object(), Heap::kOld); |
| 56 patchable_pool_entries_.Add(kNotPatchable); |
| 57 } |
| 58 |
| 59 if (StubCode::CallToRuntime_entry() != NULL) { |
| 60 FindExternalLabel(&StubCode::CallToRuntimeLabel(), kNotPatchable); |
| 61 } else { |
| 62 object_pool_.Add(Object::null_object(), Heap::kOld); |
| 63 patchable_pool_entries_.Add(kNotPatchable); |
| 64 } |
| 65 |
| 66 // Create fixed object pool entry for debugger stub. |
| 67 if (StubCode::BreakpointRuntime_entry() != NULL) { |
| 68 intptr_t index = |
| 69 FindExternalLabel(&StubCode::BreakpointRuntimeLabel(), kNotPatchable); |
| 70 ASSERT(index == kBreakpointRuntimeCPIndex); |
| 71 } else { |
| 72 object_pool_.Add(Object::null_object(), Heap::kOld); |
| 73 patchable_pool_entries_.Add(kNotPatchable); |
| 74 } |
| 51 } | 75 } |
| 52 } | 76 } |
| 53 | 77 |
| 54 | 78 |
| 55 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 79 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| 56 ASSERT(Utils::IsAligned(data, 4)); | 80 ASSERT(Utils::IsAligned(data, 4)); |
| 57 ASSERT(Utils::IsAligned(length, 4)); | 81 ASSERT(Utils::IsAligned(length, 4)); |
| 58 const uword end = data + length; | 82 const uword end = data + length; |
| 59 while (data < end) { | 83 while (data < end) { |
| 60 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; | 84 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 const Address& dest, | 693 const Address& dest, |
| 670 const Object& value) { | 694 const Object& value) { |
| 671 ASSERT(value.IsSmi() || value.InVMHeap() || | 695 ASSERT(value.IsSmi() || value.InVMHeap() || |
| 672 (value.IsOld() && value.IsNotTemporaryScopedHandle())); | 696 (value.IsOld() && value.IsNotTemporaryScopedHandle())); |
| 673 // No store buffer update. | 697 // No store buffer update. |
| 674 LoadObject(TMP, value, PP); | 698 LoadObject(TMP, value, PP); |
| 675 str(TMP, dest); | 699 str(TMP, dest); |
| 676 } | 700 } |
| 677 | 701 |
| 678 | 702 |
| 703 void Assembler::LoadClassId(Register result, Register object) { |
| 704 ASSERT(RawObject::kClassIdTagBit == 16); |
| 705 ASSERT(RawObject::kClassIdTagSize == 16); |
| 706 const intptr_t class_id_offset = Object::tags_offset() + |
| 707 RawObject::kClassIdTagBit / kBitsPerByte; |
| 708 LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, |
| 709 kUnsignedHalfword); |
| 710 } |
| 711 |
| 712 |
| 713 void Assembler::LoadClassById(Register result, Register class_id) { |
| 714 ASSERT(result != class_id); |
| 715 LoadFieldFromOffset(result, CTX, Context::isolate_offset()); |
| 716 const intptr_t table_offset_in_isolate = |
| 717 Isolate::class_table_offset() + ClassTable::table_offset(); |
| 718 LoadFromOffset(result, result, table_offset_in_isolate); |
| 719 ldr(result, Address(result, class_id, UXTX, Address::Scaled)); |
| 720 } |
| 721 |
| 722 |
| 723 void Assembler::LoadClass(Register result, Register object) { |
| 724 ASSERT(object != TMP); |
| 725 LoadClassId(TMP, object); |
| 726 LoadClassById(result, TMP); |
| 727 } |
| 728 |
| 729 |
| 730 void Assembler::CompareClassId(Register object, |
| 731 intptr_t class_id) { |
| 732 LoadClassId(TMP, object); |
| 733 CompareImmediate(TMP, class_id, PP); |
| 734 } |
| 735 |
| 736 |
| 679 // Frame entry and exit. | 737 // Frame entry and exit. |
| 680 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 738 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
| 681 // Reserve space for arguments and align frame before entering | 739 // Reserve space for arguments and align frame before entering |
| 682 // the C++ world. | 740 // the C++ world. |
| 683 AddImmediate(SP, SP, -frame_space, kNoRegister); | 741 AddImmediate(SP, SP, -frame_space, kNoRegister); |
| 684 if (OS::ActivationFrameAlignment() > 1) { | 742 if (OS::ActivationFrameAlignment() > 1) { |
| 685 mov(TMP, SP); // SP can't be register operand of andi. | 743 mov(TMP, SP); // SP can't be register operand of andi. |
| 686 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1)); | 744 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1)); |
| 687 mov(SP, TMP); | 745 mov(SP, TMP); |
| 688 } | 746 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 702 | 760 |
| 703 void Assembler::LeaveFrame() { | 761 void Assembler::LeaveFrame() { |
| 704 mov(SP, FP); | 762 mov(SP, FP); |
| 705 Pop(FP); | 763 Pop(FP); |
| 706 Pop(LR); | 764 Pop(LR); |
| 707 } | 765 } |
| 708 | 766 |
| 709 | 767 |
| 710 void Assembler::EnterDartFrame(intptr_t frame_size) { | 768 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 711 // Setup the frame. | 769 // Setup the frame. |
| 712 adr(TMP, 0); // TMP gets PC of this instruction. | 770 adr(TMP, -CodeSize()); // TMP gets PC marker. |
| 713 EnterFrame(0); | 771 EnterFrame(0); |
| 714 Push(TMP); // Save PC Marker. | 772 Push(TMP); // Save PC Marker. |
| 715 TagAndPushPP(); // Save PP. | 773 TagAndPushPP(); // Save PP. |
| 716 | 774 |
| 717 // Load the pool pointer. | 775 // Load the pool pointer. |
| 718 LoadPoolPointer(PP); | 776 LoadPoolPointer(PP); |
| 719 | 777 |
| 720 // Reserve space. | 778 // Reserve space. |
| 721 if (frame_size > 0) { | 779 if (frame_size > 0) { |
| 722 sub(SP, SP, Operand(frame_size)); | 780 AddImmediate(SP, SP, -frame_size, PP); |
| 723 } | 781 } |
| 724 } | 782 } |
| 725 | 783 |
| 726 | 784 |
| 727 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { | 785 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { |
| 728 // Setup the frame. | 786 // Setup the frame. |
| 729 adr(TMP, 0); // TMP gets PC of this instruction. | 787 adr(TMP, -CodeSize()); // TMP gets PC marker. |
| 730 EnterFrame(0); | 788 EnterFrame(0); |
| 731 Push(TMP); // Save PC Marker. | 789 Push(TMP); // Save PC Marker. |
| 732 TagAndPushPP(); // Save PP. | 790 TagAndPushPP(); // Save PP. |
| 733 | 791 |
| 734 // Load the pool pointer. | 792 // Load the pool pointer. |
| 735 if (new_pp == kNoRegister) { | 793 if (new_pp == kNoRegister) { |
| 736 LoadPoolPointer(PP); | 794 LoadPoolPointer(PP); |
| 737 } else { | 795 } else { |
| 738 mov(PP, new_pp); | 796 mov(PP, new_pp); |
| 739 } | 797 } |
| 740 | 798 |
| 741 // Reserve space. | 799 // Reserve space. |
| 742 if (frame_size > 0) { | 800 if (frame_size > 0) { |
| 743 sub(SP, SP, Operand(frame_size)); | 801 AddImmediate(SP, SP, -frame_size, PP); |
| 744 } | 802 } |
| 745 } | 803 } |
| 746 | 804 |
| 747 | 805 |
| 748 // On entry to a function compiled for OSR, the caller's frame pointer, the | 806 // On entry to a function compiled for OSR, the caller's frame pointer, the |
| 749 // stack locals, and any copied parameters are already in place. The frame | 807 // stack locals, and any copied parameters are already in place. The frame |
| 750 // pointer is already set up. The PC marker is not correct for the | 808 // pointer is already set up. The PC marker is not correct for the |
| 751 // optimized function and there may be extra space for spill slots to | 809 // optimized function and there may be extra space for spill slots to |
| 752 // allocate. We must also set up the pool pointer for the function. | 810 // allocate. We must also set up the pool pointer for the function. |
| 753 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { | 811 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { |
| 754 const intptr_t offset = CodeSize(); | 812 const intptr_t offset = CodeSize(); |
| 755 | 813 |
| 756 Comment("EnterOsrFrame"); | 814 Comment("EnterOsrFrame"); |
| 757 adr(TMP, 0); | 815 adr(TMP, -CodeSize()); |
| 758 | 816 |
| 759 AddImmediate(TMP, TMP, -offset, kNoRegister); | 817 AddImmediate(TMP, TMP, -offset, kNoRegister); |
| 760 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize); | 818 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize); |
| 761 | 819 |
| 762 // Setup pool pointer for this dart function. | 820 // Setup pool pointer for this dart function. |
| 763 if (new_pp == kNoRegister) { | 821 if (new_pp == kNoRegister) { |
| 764 LoadPoolPointer(PP); | 822 LoadPoolPointer(PP); |
| 765 } else { | 823 } else { |
| 766 mov(PP, new_pp); | 824 mov(PP, new_pp); |
| 767 } | 825 } |
| 768 | 826 |
| 769 if (extra_size > 0) { | 827 if (extra_size > 0) { |
| 770 sub(SP, SP, Operand(extra_size)); | 828 AddImmediate(SP, SP, -extra_size, PP); |
| 771 } | 829 } |
| 772 } | 830 } |
| 773 | 831 |
| 774 | 832 |
| 775 void Assembler::LeaveDartFrame() { | 833 void Assembler::LeaveDartFrame() { |
| 776 // Restore and untag PP. | 834 // Restore and untag PP. |
| 777 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); | 835 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); |
| 778 sub(PP, PP, Operand(kHeapObjectTag)); | 836 sub(PP, PP, Operand(kHeapObjectTag)); |
| 779 LeaveFrame(); | 837 LeaveFrame(); |
| 780 } | 838 } |
| 781 | 839 |
| 782 | 840 |
| 783 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { | 841 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { |
| 784 EnterFrame(0); | 842 EnterFrame(0); |
| 785 | 843 |
| 786 // TODO(zra): also save volatile FPU registers. | 844 // TODO(zra): also save volatile FPU registers. |
| 787 | 845 |
| 788 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | 846 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
| 789 const Register reg = static_cast<Register>(i); | 847 const Register reg = static_cast<Register>(i); |
| 790 Push(reg); | 848 if ((reg != R16) && (reg != R17)) { |
| 849 Push(reg); |
| 850 } |
| 791 } | 851 } |
| 792 | 852 |
| 793 ReserveAlignedFrameSpace(frame_size); | 853 ReserveAlignedFrameSpace(frame_size); |
| 794 } | 854 } |
| 795 | 855 |
| 796 | 856 |
| 797 void Assembler::LeaveCallRuntimeFrame() { | 857 void Assembler::LeaveCallRuntimeFrame() { |
| 798 // SP might have been modified to reserve space for arguments | 858 // SP might have been modified to reserve space for arguments |
| 799 // and ensure proper alignment of the stack frame. | 859 // and ensure proper alignment of the stack frame. |
| 800 // We need to restore it before restoring registers. | 860 // We need to restore it before restoring registers. |
| 801 // TODO(zra): Also include FPU regs in this count once they are added. | 861 // TODO(zra): Also include FPU regs in this count once they are added. |
| 802 const intptr_t kPushedRegistersSize = | 862 const intptr_t kPushedRegistersSize = |
| 803 kDartVolatileCpuRegCount * kWordSize; | 863 kDartVolatileCpuRegCount * kWordSize; |
| 804 AddImmediate(SP, FP, -kPushedRegistersSize, PP); | 864 AddImmediate(SP, FP, -kPushedRegistersSize, PP); |
| 805 for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) { | 865 for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) { |
| 806 const Register reg = static_cast<Register>(i); | 866 const Register reg = static_cast<Register>(i); |
| 807 Pop(reg); | 867 if ((reg != R16) && (reg != R17)) { |
| 868 Pop(reg); |
| 869 } |
| 808 } | 870 } |
| 809 | 871 |
| 810 Pop(FP); | 872 Pop(FP); |
| 811 Pop(LR); | 873 Pop(LR); |
| 812 } | 874 } |
| 813 | 875 |
| 814 | 876 |
| 815 void Assembler::CallRuntime(const RuntimeEntry& entry, | 877 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 816 intptr_t argument_count) { | 878 intptr_t argument_count) { |
| 817 entry.Call(this, argument_count); | 879 entry.Call(this, argument_count); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 831 void Assembler::LeaveStubFrame() { | 893 void Assembler::LeaveStubFrame() { |
| 832 // Restore and untag PP. | 894 // Restore and untag PP. |
| 833 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); | 895 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); |
| 834 sub(PP, PP, Operand(kHeapObjectTag)); | 896 sub(PP, PP, Operand(kHeapObjectTag)); |
| 835 LeaveFrame(); | 897 LeaveFrame(); |
| 836 } | 898 } |
| 837 | 899 |
| 838 } // namespace dart | 900 } // namespace dart |
| 839 | 901 |
| 840 #endif // defined TARGET_ARCH_ARM64 | 902 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |