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 |