| OLD | NEW |
| 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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
| 10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 // Relocation doesn't apply to Smis. | 581 // Relocation doesn't apply to Smis. |
| 582 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); | 582 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); |
| 583 } else if (CanLoadFromObjectPool(object)) { | 583 } else if (CanLoadFromObjectPool(object)) { |
| 584 // Make sure that class CallPattern is able to decode this load from the | 584 // Make sure that class CallPattern is able to decode this load from the |
| 585 // object pool. | 585 // object pool. |
| 586 const int32_t offset = ObjectPool::element_offset( | 586 const int32_t offset = ObjectPool::element_offset( |
| 587 is_unique ? object_pool_wrapper_.AddObject(object) | 587 is_unique ? object_pool_wrapper_.AddObject(object) |
| 588 : object_pool_wrapper_.FindObject(object)); | 588 : object_pool_wrapper_.FindObject(object)); |
| 589 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 589 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
| 590 } else { | 590 } else { |
| 591 ASSERT(FLAG_allow_absolute_addresses); | 591 UNREACHABLE(); |
| 592 ASSERT(object.IsOld()); | |
| 593 // Make sure that class CallPattern is able to decode this load immediate. | |
| 594 int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); | |
| 595 const uint16_t object_low = Utils::Low16Bits(object_raw); | |
| 596 const uint16_t object_high = Utils::High16Bits(object_raw); | |
| 597 lui(rd, Immediate(object_high)); | |
| 598 ori(rd, rd, Immediate(object_low)); | |
| 599 } | 592 } |
| 600 } | 593 } |
| 601 | 594 |
| 602 | 595 |
| 603 void Assembler::LoadObject(Register rd, const Object& object) { | 596 void Assembler::LoadObject(Register rd, const Object& object) { |
| 604 LoadObjectHelper(rd, object, false); | 597 LoadObjectHelper(rd, object, false); |
| 605 } | 598 } |
| 606 | 599 |
| 607 | 600 |
| 608 void Assembler::LoadUniqueObject(Register rd, const Object& object) { | 601 void Assembler::LoadUniqueObject(Register rd, const Object& object) { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 } | 898 } |
| 906 | 899 |
| 907 | 900 |
| 908 void Assembler::LeaveStubFrameAndReturn(Register ra) { | 901 void Assembler::LeaveStubFrameAndReturn(Register ra) { |
| 909 LeaveDartFrameAndReturn(ra); | 902 LeaveDartFrameAndReturn(ra); |
| 910 } | 903 } |
| 911 | 904 |
| 912 | 905 |
| 913 void Assembler::UpdateAllocationStats(intptr_t cid, | 906 void Assembler::UpdateAllocationStats(intptr_t cid, |
| 914 Register temp_reg, | 907 Register temp_reg, |
| 915 Heap::Space space, | 908 Heap::Space space) { |
| 916 bool inline_isolate) { | |
| 917 ASSERT(!in_delay_slot_); | 909 ASSERT(!in_delay_slot_); |
| 918 ASSERT(temp_reg != kNoRegister); | 910 ASSERT(temp_reg != kNoRegister); |
| 919 ASSERT(temp_reg != TMP); | 911 ASSERT(temp_reg != TMP); |
| 920 ASSERT(cid > 0); | 912 ASSERT(cid > 0); |
| 921 intptr_t counter_offset = | 913 intptr_t counter_offset = |
| 922 ClassTable::CounterOffsetFor(cid, space == Heap::kNew); | 914 ClassTable::CounterOffsetFor(cid, space == Heap::kNew); |
| 923 if (inline_isolate) { | 915 LoadIsolate(temp_reg); |
| 924 ASSERT(FLAG_allow_absolute_addresses); | 916 intptr_t table_offset = |
| 925 ClassTable* class_table = Isolate::Current()->class_table(); | 917 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); |
| 926 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); | 918 lw(temp_reg, Address(temp_reg, table_offset)); |
| 927 if (cid < kNumPredefinedCids) { | 919 AddImmediate(temp_reg, counter_offset); |
| 928 LoadImmediate( | |
| 929 temp_reg, reinterpret_cast<uword>(*table_ptr) + counter_offset); | |
| 930 } else { | |
| 931 ASSERT(temp_reg != kNoRegister); | |
| 932 LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr)); | |
| 933 lw(temp_reg, Address(temp_reg, 0)); | |
| 934 AddImmediate(temp_reg, counter_offset); | |
| 935 } | |
| 936 } else { | |
| 937 LoadIsolate(temp_reg); | |
| 938 intptr_t table_offset = | |
| 939 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); | |
| 940 lw(temp_reg, Address(temp_reg, table_offset)); | |
| 941 AddImmediate(temp_reg, counter_offset); | |
| 942 } | |
| 943 lw(TMP, Address(temp_reg, 0)); | 920 lw(TMP, Address(temp_reg, 0)); |
| 944 AddImmediate(TMP, 1); | 921 AddImmediate(TMP, 1); |
| 945 sw(TMP, Address(temp_reg, 0)); | 922 sw(TMP, Address(temp_reg, 0)); |
| 946 } | 923 } |
| 947 | 924 |
| 948 | 925 |
| 949 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid, | 926 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid, |
| 950 Register size_reg, | 927 Register size_reg, |
| 951 Register temp_reg, | 928 Register temp_reg, |
| 952 Heap::Space space, | 929 Heap::Space space) { |
| 953 bool inline_isolate) { | |
| 954 ASSERT(!in_delay_slot_); | 930 ASSERT(!in_delay_slot_); |
| 955 ASSERT(temp_reg != kNoRegister); | 931 ASSERT(temp_reg != kNoRegister); |
| 956 ASSERT(cid > 0); | 932 ASSERT(cid > 0); |
| 957 ASSERT(temp_reg != TMP); | 933 ASSERT(temp_reg != TMP); |
| 958 const uword class_offset = ClassTable::ClassOffsetFor(cid); | 934 const uword class_offset = ClassTable::ClassOffsetFor(cid); |
| 959 const uword count_field_offset = (space == Heap::kNew) ? | 935 const uword count_field_offset = (space == Heap::kNew) ? |
| 960 ClassHeapStats::allocated_since_gc_new_space_offset() : | 936 ClassHeapStats::allocated_since_gc_new_space_offset() : |
| 961 ClassHeapStats::allocated_since_gc_old_space_offset(); | 937 ClassHeapStats::allocated_since_gc_old_space_offset(); |
| 962 const uword size_field_offset = (space == Heap::kNew) ? | 938 const uword size_field_offset = (space == Heap::kNew) ? |
| 963 ClassHeapStats::allocated_size_since_gc_new_space_offset() : | 939 ClassHeapStats::allocated_size_since_gc_new_space_offset() : |
| 964 ClassHeapStats::allocated_size_since_gc_old_space_offset(); | 940 ClassHeapStats::allocated_size_since_gc_old_space_offset(); |
| 965 if (inline_isolate) { | 941 LoadIsolate(temp_reg); |
| 966 ClassTable* class_table = Isolate::Current()->class_table(); | 942 intptr_t table_offset = |
| 967 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); | 943 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); |
| 968 if (cid < kNumPredefinedCids) { | 944 lw(temp_reg, Address(temp_reg, table_offset)); |
| 969 LoadImmediate(temp_reg, | 945 AddImmediate(temp_reg, class_offset); |
| 970 reinterpret_cast<uword>(*table_ptr) + class_offset); | |
| 971 } else { | |
| 972 ASSERT(temp_reg != kNoRegister); | |
| 973 LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr)); | |
| 974 lw(temp_reg, Address(temp_reg, 0)); | |
| 975 AddImmediate(temp_reg, class_offset); | |
| 976 } | |
| 977 } else { | |
| 978 LoadIsolate(temp_reg); | |
| 979 intptr_t table_offset = | |
| 980 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); | |
| 981 lw(temp_reg, Address(temp_reg, table_offset)); | |
| 982 AddImmediate(temp_reg, class_offset); | |
| 983 } | |
| 984 lw(TMP, Address(temp_reg, count_field_offset)); | 946 lw(TMP, Address(temp_reg, count_field_offset)); |
| 985 AddImmediate(TMP, 1); | 947 AddImmediate(TMP, 1); |
| 986 sw(TMP, Address(temp_reg, count_field_offset)); | 948 sw(TMP, Address(temp_reg, count_field_offset)); |
| 987 lw(TMP, Address(temp_reg, size_field_offset)); | 949 lw(TMP, Address(temp_reg, size_field_offset)); |
| 988 addu(TMP, TMP, size_reg); | 950 addu(TMP, TMP, size_reg); |
| 989 sw(TMP, Address(temp_reg, size_field_offset)); | 951 sw(TMP, Address(temp_reg, size_field_offset)); |
| 990 } | 952 } |
| 991 | 953 |
| 992 | 954 |
| 993 void Assembler::MaybeTraceAllocation(intptr_t cid, | 955 void Assembler::MaybeTraceAllocation(intptr_t cid, |
| 994 Register temp_reg, | 956 Register temp_reg, |
| 995 Label* trace, | 957 Label* trace) { |
| 996 bool inline_isolate) { | |
| 997 ASSERT(cid > 0); | 958 ASSERT(cid > 0); |
| 998 ASSERT(!in_delay_slot_); | 959 ASSERT(!in_delay_slot_); |
| 999 ASSERT(temp_reg != kNoRegister); | 960 ASSERT(temp_reg != kNoRegister); |
| 1000 ASSERT(temp_reg != TMP); | 961 ASSERT(temp_reg != TMP); |
| 1001 intptr_t state_offset = ClassTable::StateOffsetFor(cid); | 962 intptr_t state_offset = ClassTable::StateOffsetFor(cid); |
| 1002 if (inline_isolate) { | 963 LoadIsolate(temp_reg); |
| 1003 ASSERT(FLAG_allow_absolute_addresses); | 964 intptr_t table_offset = |
| 1004 ClassTable* class_table = Isolate::Current()->class_table(); | 965 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); |
| 1005 ClassHeapStats** table_ptr = class_table->TableAddressFor(cid); | 966 lw(temp_reg, Address(temp_reg, table_offset)); |
| 1006 if (cid < kNumPredefinedCids) { | 967 AddImmediate(temp_reg, state_offset); |
| 1007 LoadImmediate(temp_reg, | |
| 1008 reinterpret_cast<uword>(*table_ptr) + state_offset); | |
| 1009 } else { | |
| 1010 LoadImmediate(temp_reg, reinterpret_cast<uword>(table_ptr)); | |
| 1011 lw(temp_reg, Address(temp_reg, 0)); | |
| 1012 AddImmediate(temp_reg, state_offset); | |
| 1013 } | |
| 1014 } else { | |
| 1015 LoadIsolate(temp_reg); | |
| 1016 intptr_t table_offset = | |
| 1017 Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid); | |
| 1018 lw(temp_reg, Address(temp_reg, table_offset)); | |
| 1019 AddImmediate(temp_reg, state_offset); | |
| 1020 } | |
| 1021 lw(temp_reg, Address(temp_reg, 0)); | 968 lw(temp_reg, Address(temp_reg, 0)); |
| 1022 andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask())); | 969 andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask())); |
| 1023 bne(CMPRES1, ZR, trace); | 970 bne(CMPRES1, ZR, trace); |
| 1024 } | 971 } |
| 1025 | 972 |
| 1026 | 973 |
| 1027 void Assembler::TryAllocate(const Class& cls, | 974 void Assembler::TryAllocate(const Class& cls, |
| 1028 Label* failure, | 975 Label* failure, |
| 1029 Register instance_reg, | 976 Register instance_reg, |
| 1030 Register temp_reg) { | 977 Register temp_reg) { |
| 1031 ASSERT(!in_delay_slot_); | 978 ASSERT(!in_delay_slot_); |
| 1032 ASSERT(failure != NULL); | 979 ASSERT(failure != NULL); |
| 1033 if (FLAG_inline_alloc) { | 980 if (FLAG_inline_alloc) { |
| 1034 // If this allocation is traced, program will jump to failure path | 981 // If this allocation is traced, program will jump to failure path |
| 1035 // (i.e. the allocation stub) which will allocate the object and trace the | 982 // (i.e. the allocation stub) which will allocate the object and trace the |
| 1036 // allocation call site. | 983 // allocation call site. |
| 1037 MaybeTraceAllocation(cls.id(), temp_reg, failure, | 984 MaybeTraceAllocation(cls.id(), temp_reg, failure); |
| 1038 /* inline_isolate = */ false); | |
| 1039 const intptr_t instance_size = cls.instance_size(); | 985 const intptr_t instance_size = cls.instance_size(); |
| 1040 Heap::Space space = Heap::SpaceForAllocation(cls.id()); | 986 Heap::Space space = Heap::SpaceForAllocation(cls.id()); |
| 1041 lw(temp_reg, Address(THR, Thread::heap_offset())); | 987 lw(temp_reg, Address(THR, Thread::heap_offset())); |
| 1042 lw(instance_reg, Address(temp_reg, Heap::TopOffset(space))); | 988 lw(instance_reg, Address(temp_reg, Heap::TopOffset(space))); |
| 1043 // TODO(koda): Protect against unsigned overflow here. | 989 // TODO(koda): Protect against unsigned overflow here. |
| 1044 AddImmediate(instance_reg, instance_size); | 990 AddImmediate(instance_reg, instance_size); |
| 1045 | 991 |
| 1046 // instance_reg: potential next object start. | 992 // instance_reg: potential next object start. |
| 1047 lw(TMP, Address(temp_reg, Heap::EndOffset(space))); | 993 lw(TMP, Address(temp_reg, Heap::EndOffset(space))); |
| 1048 // Fail if heap end unsigned less than or equal to instance_reg. | 994 // Fail if heap end unsigned less than or equal to instance_reg. |
| 1049 BranchUnsignedLessEqual(TMP, instance_reg, failure); | 995 BranchUnsignedLessEqual(TMP, instance_reg, failure); |
| 1050 | 996 |
| 1051 // Successfully allocated the object, now update top to point to | 997 // Successfully allocated the object, now update top to point to |
| 1052 // next object start and store the class in the class field of object. | 998 // next object start and store the class in the class field of object. |
| 1053 sw(instance_reg, Address(temp_reg, Heap::TopOffset(space))); | 999 sw(instance_reg, Address(temp_reg, Heap::TopOffset(space))); |
| 1054 | 1000 |
| 1055 ASSERT(instance_size >= kHeapObjectTag); | 1001 ASSERT(instance_size >= kHeapObjectTag); |
| 1056 AddImmediate(instance_reg, -instance_size + kHeapObjectTag); | 1002 AddImmediate(instance_reg, -instance_size + kHeapObjectTag); |
| 1057 UpdateAllocationStats(cls.id(), temp_reg, space, | 1003 UpdateAllocationStats(cls.id(), temp_reg, space); |
| 1058 /* inline_isolate = */ false); | |
| 1059 uword tags = 0; | 1004 uword tags = 0; |
| 1060 tags = RawObject::SizeTag::update(instance_size, tags); | 1005 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1061 ASSERT(cls.id() != kIllegalCid); | 1006 ASSERT(cls.id() != kIllegalCid); |
| 1062 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1007 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1063 LoadImmediate(TMP, tags); | 1008 LoadImmediate(TMP, tags); |
| 1064 sw(TMP, FieldAddress(instance_reg, Object::tags_offset())); | 1009 sw(TMP, FieldAddress(instance_reg, Object::tags_offset())); |
| 1065 } else { | 1010 } else { |
| 1066 b(failure); | 1011 b(failure); |
| 1067 } | 1012 } |
| 1068 } | 1013 } |
| 1069 | 1014 |
| 1070 | 1015 |
| 1071 void Assembler::TryAllocateArray(intptr_t cid, | 1016 void Assembler::TryAllocateArray(intptr_t cid, |
| 1072 intptr_t instance_size, | 1017 intptr_t instance_size, |
| 1073 Label* failure, | 1018 Label* failure, |
| 1074 Register instance, | 1019 Register instance, |
| 1075 Register end_address, | 1020 Register end_address, |
| 1076 Register temp1, | 1021 Register temp1, |
| 1077 Register temp2) { | 1022 Register temp2) { |
| 1078 if (FLAG_inline_alloc) { | 1023 if (FLAG_inline_alloc) { |
| 1079 // If this allocation is traced, program will jump to failure path | 1024 // If this allocation is traced, program will jump to failure path |
| 1080 // (i.e. the allocation stub) which will allocate the object and trace the | 1025 // (i.e. the allocation stub) which will allocate the object and trace the |
| 1081 // allocation call site. | 1026 // allocation call site. |
| 1082 MaybeTraceAllocation(cid, temp1, failure, /* inline_isolate = */ false); | 1027 MaybeTraceAllocation(cid, temp1, failure); |
| 1083 Isolate* isolate = Isolate::Current(); | 1028 Isolate* isolate = Isolate::Current(); |
| 1084 Heap* heap = isolate->heap(); | 1029 Heap* heap = isolate->heap(); |
| 1085 Heap::Space space = heap->SpaceForAllocation(cid); | 1030 Heap::Space space = heap->SpaceForAllocation(cid); |
| 1086 lw(temp1, Address(THR, Thread::heap_offset())); | 1031 lw(temp1, Address(THR, Thread::heap_offset())); |
| 1087 // Potential new object start. | 1032 // Potential new object start. |
| 1088 lw(instance, Address(temp1, heap->TopOffset(space))); | 1033 lw(instance, Address(temp1, heap->TopOffset(space))); |
| 1089 // Potential next object start. | 1034 // Potential next object start. |
| 1090 AddImmediate(end_address, instance, instance_size); | 1035 AddImmediate(end_address, instance, instance_size); |
| 1091 // Branch on unsigned overflow. | 1036 // Branch on unsigned overflow. |
| 1092 BranchUnsignedLess(end_address, instance, failure); | 1037 BranchUnsignedLess(end_address, instance, failure); |
| 1093 | 1038 |
| 1094 // Check if the allocation fits into the remaining space. | 1039 // Check if the allocation fits into the remaining space. |
| 1095 // instance: potential new object start, /* inline_isolate = */ false. | 1040 // instance: potential new object start, /* inline_isolate = */ false. |
| 1096 // end_address: potential next object start. | 1041 // end_address: potential next object start. |
| 1097 lw(temp2, Address(temp1, Heap::EndOffset(space))); | 1042 lw(temp2, Address(temp1, Heap::EndOffset(space))); |
| 1098 BranchUnsignedGreaterEqual(end_address, temp2, failure); | 1043 BranchUnsignedGreaterEqual(end_address, temp2, failure); |
| 1099 | 1044 |
| 1100 // Successfully allocated the object(s), now update top to point to | 1045 // Successfully allocated the object(s), now update top to point to |
| 1101 // next object start and initialize the object. | 1046 // next object start and initialize the object. |
| 1102 sw(end_address, Address(temp1, Heap::TopOffset(space))); | 1047 sw(end_address, Address(temp1, Heap::TopOffset(space))); |
| 1103 addiu(instance, instance, Immediate(kHeapObjectTag)); | 1048 addiu(instance, instance, Immediate(kHeapObjectTag)); |
| 1104 LoadImmediate(temp1, instance_size); | 1049 LoadImmediate(temp1, instance_size); |
| 1105 UpdateAllocationStatsWithSize(cid, temp1, temp2, space, | 1050 UpdateAllocationStatsWithSize(cid, temp1, temp2, space); |
| 1106 /* inline_isolate = */ false); | |
| 1107 | 1051 |
| 1108 // Initialize the tags. | 1052 // Initialize the tags. |
| 1109 // instance: new object start as a tagged pointer. | 1053 // instance: new object start as a tagged pointer. |
| 1110 uword tags = 0; | 1054 uword tags = 0; |
| 1111 tags = RawObject::ClassIdTag::update(cid, tags); | 1055 tags = RawObject::ClassIdTag::update(cid, tags); |
| 1112 tags = RawObject::SizeTag::update(instance_size, tags); | 1056 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1113 LoadImmediate(temp1, tags); | 1057 LoadImmediate(temp1, tags); |
| 1114 sw(temp1, FieldAddress(instance, Array::tags_offset())); // Store tags. | 1058 sw(temp1, FieldAddress(instance, Array::tags_offset())); // Store tags. |
| 1115 } else { | 1059 } else { |
| 1116 b(failure); | 1060 b(failure); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 Label stop; | 1306 Label stop; |
| 1363 b(&stop); | 1307 b(&stop); |
| 1364 Emit(reinterpret_cast<int32_t>(message)); | 1308 Emit(reinterpret_cast<int32_t>(message)); |
| 1365 Bind(&stop); | 1309 Bind(&stop); |
| 1366 break_(Instr::kStopMessageCode); | 1310 break_(Instr::kStopMessageCode); |
| 1367 } | 1311 } |
| 1368 | 1312 |
| 1369 } // namespace dart | 1313 } // namespace dart |
| 1370 | 1314 |
| 1371 #endif // defined TARGET_ARCH_MIPS | 1315 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |