Chromium Code Reviews| 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 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { | 623 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { |
| 624 ldr(dest, Address(base, offset, Address::Offset, sz), sz); | 624 ldr(dest, Address(base, offset, Address::Offset, sz), sz); |
| 625 } else { | 625 } else { |
| 626 // Since offset is 32-bits, it won't be loaded from the pool. | 626 // Since offset is 32-bits, it won't be loaded from the pool. |
| 627 AddImmediate(TMP2, base, offset, kNoPP); | 627 AddImmediate(TMP2, base, offset, kNoPP); |
| 628 ldr(dest, Address(TMP2), sz); | 628 ldr(dest, Address(TMP2), sz); |
| 629 } | 629 } |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) { | |
| 634 ASSERT(base != TMP2); | |
|
regis
2014/05/02 19:59:16
I would move this assert to the else branch.
zra
2014/05/02 20:16:11
Done.
| |
| 635 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { | |
| 636 fldrd(dest, Address(base, offset, Address::Offset, kDWord)); | |
| 637 } else { | |
| 638 // Since offset is 32-bits, it won't be loaded from the pool. | |
| 639 AddImmediate(TMP2, base, offset, kNoPP); | |
| 640 fldrd(dest, Address(TMP2)); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 | |
| 633 void Assembler::StoreToOffset( | 645 void Assembler::StoreToOffset( |
| 634 Register src, Register base, int32_t offset, OperandSize sz) { | 646 Register src, Register base, int32_t offset, OperandSize sz) { |
| 635 ASSERT(src != TMP2); | 647 ASSERT(src != TMP2); |
| 636 ASSERT(base != TMP2); | 648 ASSERT(base != TMP2); |
| 637 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { | 649 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { |
| 638 str(src, Address(base, offset, Address::Offset, sz), sz); | 650 str(src, Address(base, offset, Address::Offset, sz), sz); |
| 639 } else { | 651 } else { |
| 640 // Since offset is 32-bits, it won't be loaded from the pool. | 652 // Since offset is 32-bits, it won't be loaded from the pool. |
| 641 AddImmediate(TMP2, base, offset, kNoPP); | 653 AddImmediate(TMP2, base, offset, kNoPP); |
| 642 str(src, Address(TMP2), sz); | 654 str(src, Address(TMP2), sz); |
| 643 } | 655 } |
| 644 } | 656 } |
| 645 | 657 |
| 646 | 658 |
| 659 void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) { | |
| 660 ASSERT(base != TMP2); | |
|
regis
2014/05/02 19:59:16
ditto
zra
2014/05/02 20:16:11
Done.
| |
| 661 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { | |
| 662 fstrd(src, Address(base, offset, Address::Offset, kDWord)); | |
| 663 } else { | |
| 664 // Since offset is 32-bits, it won't be loaded from the pool. | |
| 665 AddImmediate(TMP2, base, offset, kNoPP); | |
| 666 fstrd(src, Address(TMP2)); | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 | |
| 647 // Store into object. | 671 // Store into object. |
| 648 // Preserves object and value registers. | 672 // Preserves object and value registers. |
| 649 void Assembler::StoreIntoObjectFilterNoSmi(Register object, | 673 void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| 650 Register value, | 674 Register value, |
| 651 Label* no_update) { | 675 Label* no_update) { |
| 652 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && | 676 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| 653 (kOldObjectAlignmentOffset == 0), young_alignment); | 677 (kOldObjectAlignmentOffset == 0), young_alignment); |
| 654 | 678 |
| 655 // Write-barrier triggers if the value is in the new space (has bit set) and | 679 // Write-barrier triggers if the value is in the new space (has bit set) and |
| 656 // the object is in the old space (has bit cleared). | 680 // the object is in the old space (has bit cleared). |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 866 // Restore and untag PP. | 890 // Restore and untag PP. |
| 867 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); | 891 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); |
| 868 sub(PP, PP, Operand(kHeapObjectTag)); | 892 sub(PP, PP, Operand(kHeapObjectTag)); |
| 869 LeaveFrame(); | 893 LeaveFrame(); |
| 870 } | 894 } |
| 871 | 895 |
| 872 | 896 |
| 873 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { | 897 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { |
| 874 EnterFrame(0); | 898 EnterFrame(0); |
| 875 | 899 |
| 876 // TODO(zra): also save volatile FPU registers. | 900 // Store fpu registers with the lowest register number at the lowest |
| 901 // address. | |
| 902 for (int i = kNumberOfVRegisters - 1; i >= 0; i--) { | |
| 903 if ((i >= kAbiFirstPreservedFpuReg) && (i <= kAbiLastPreservedFpuReg)) { | |
| 904 // TODO(zra): When SIMD is added, we must also preserve the top | |
| 905 // 64-bits of the callee-saved registers. | |
| 906 continue; | |
| 907 } | |
| 908 // TODO(zra): Save the whole V register. | |
| 909 VRegister reg = static_cast<VRegister>(i); | |
| 910 PushDouble(reg); | |
| 911 } | |
| 877 | 912 |
| 878 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | 913 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
| 879 const Register reg = static_cast<Register>(i); | 914 const Register reg = static_cast<Register>(i); |
| 880 if ((reg != R16) && (reg != R17)) { | 915 if ((reg != TMP) && (reg != TMP2)) { |
| 881 Push(reg); | 916 Push(reg); |
| 882 } | 917 } |
| 883 } | 918 } |
| 884 | 919 |
| 885 ReserveAlignedFrameSpace(frame_size); | 920 ReserveAlignedFrameSpace(frame_size); |
| 886 } | 921 } |
| 887 | 922 |
| 888 | 923 |
| 889 void Assembler::LeaveCallRuntimeFrame() { | 924 void Assembler::LeaveCallRuntimeFrame() { |
| 890 // SP might have been modified to reserve space for arguments | 925 // SP might have been modified to reserve space for arguments |
| 891 // and ensure proper alignment of the stack frame. | 926 // and ensure proper alignment of the stack frame. |
| 892 // We need to restore it before restoring registers. | 927 // We need to restore it before restoring registers. |
| 893 // TODO(zra): Also include FPU regs in this count once they are added. | 928 // TODO(zra): Also include FPU regs in this count once they are added. |
| 894 const intptr_t kPushedRegistersSize = | 929 const intptr_t kPushedRegistersSize = |
| 895 kDartVolatileCpuRegCount * kWordSize; | 930 kDartVolatileCpuRegCount * kWordSize + |
| 931 kDartVolatileFpuRegCount * kWordSize; | |
| 896 AddImmediate(SP, FP, -kPushedRegistersSize, PP); | 932 AddImmediate(SP, FP, -kPushedRegistersSize, PP); |
| 897 for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) { | 933 for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) { |
| 898 const Register reg = static_cast<Register>(i); | 934 const Register reg = static_cast<Register>(i); |
| 899 if ((reg != R16) && (reg != R17)) { | 935 if ((reg != TMP) && (reg != TMP2)) { |
| 900 Pop(reg); | 936 Pop(reg); |
| 901 } | 937 } |
| 902 } | 938 } |
| 903 | 939 |
| 940 for (int i = 0; i < kNumberOfVRegisters; i++) { | |
| 941 if ((i >= kAbiFirstPreservedFpuReg) && (i <= kAbiLastPreservedFpuReg)) { | |
| 942 // TODO(zra): When SIMD is added, we must also restore the top | |
| 943 // 64-bits of the callee-saved registers. | |
| 944 continue; | |
| 945 } | |
| 946 // TODO(zra): Restore the whole V register. | |
| 947 VRegister reg = static_cast<VRegister>(i); | |
| 948 PopDouble(reg); | |
| 949 } | |
| 950 | |
| 904 Pop(FP); | 951 Pop(FP); |
| 905 Pop(LR); | 952 Pop(LR); |
| 906 } | 953 } |
| 907 | 954 |
| 908 | 955 |
| 909 void Assembler::CallRuntime(const RuntimeEntry& entry, | 956 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 910 intptr_t argument_count) { | 957 intptr_t argument_count) { |
| 911 entry.Call(this, argument_count); | 958 entry.Call(this, argument_count); |
| 912 } | 959 } |
| 913 | 960 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 AddImmediate(temp_reg, temp_reg, class_offset, pp); | 1057 AddImmediate(temp_reg, temp_reg, class_offset, pp); |
| 1011 ldr(TMP, Address(temp_reg, count_field_offset)); | 1058 ldr(TMP, Address(temp_reg, count_field_offset)); |
| 1012 AddImmediate(TMP, TMP, 1, pp); | 1059 AddImmediate(TMP, TMP, 1, pp); |
| 1013 str(TMP, Address(temp_reg, count_field_offset)); | 1060 str(TMP, Address(temp_reg, count_field_offset)); |
| 1014 ldr(TMP, Address(temp_reg, size_field_offset)); | 1061 ldr(TMP, Address(temp_reg, size_field_offset)); |
| 1015 add(TMP, TMP, Operand(size_reg)); | 1062 add(TMP, TMP, Operand(size_reg)); |
| 1016 str(TMP, Address(temp_reg, size_field_offset)); | 1063 str(TMP, Address(temp_reg, size_field_offset)); |
| 1017 } | 1064 } |
| 1018 } | 1065 } |
| 1019 | 1066 |
| 1067 | |
| 1068 void Assembler::TryAllocate(const Class& cls, | |
| 1069 Label* failure, | |
| 1070 Register instance_reg, | |
| 1071 Register temp_reg, | |
| 1072 Register pp) { | |
| 1073 ASSERT(failure != NULL); | |
| 1074 if (FLAG_inline_alloc) { | |
| 1075 Heap* heap = Isolate::Current()->heap(); | |
| 1076 const intptr_t instance_size = cls.instance_size(); | |
| 1077 LoadImmediate(instance_reg, heap->TopAddress(), pp); | |
| 1078 ldr(instance_reg, Address(instance_reg)); | |
| 1079 AddImmediate(instance_reg, instance_reg, instance_size, pp); | |
| 1080 | |
| 1081 // instance_reg: potential next object start. | |
| 1082 LoadImmediate(TMP, heap->EndAddress(), pp); | |
| 1083 ldr(TMP, Address(TMP)); | |
| 1084 CompareRegisters(TMP, instance_reg); | |
| 1085 // fail if heap end unsigned less than or equal to instance_reg. | |
| 1086 b(failure, LS); | |
| 1087 | |
| 1088 // Successfully allocated the object, now update top to point to | |
| 1089 // next object start and store the class in the class field of object. | |
| 1090 LoadImmediate(TMP, heap->TopAddress(), pp); | |
| 1091 str(instance_reg, Address(TMP)); | |
| 1092 | |
| 1093 ASSERT(instance_size >= kHeapObjectTag); | |
| 1094 AddImmediate( | |
| 1095 instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp); | |
| 1096 UpdateAllocationStats(cls.id(), temp_reg, pp); | |
| 1097 | |
| 1098 uword tags = 0; | |
| 1099 tags = RawObject::SizeTag::update(instance_size, tags); | |
| 1100 ASSERT(cls.id() != kIllegalCid); | |
| 1101 tags = RawObject::ClassIdTag::update(cls.id(), tags); | |
| 1102 LoadImmediate(TMP, tags, pp); | |
| 1103 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset()); | |
| 1104 } else { | |
| 1105 b(failure); | |
| 1106 } | |
| 1107 } | |
| 1108 | |
| 1020 } // namespace dart | 1109 } // namespace dart |
| 1021 | 1110 |
| 1022 #endif // defined TARGET_ARCH_ARM64 | 1111 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |