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" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 // T1: potential next object start. | 64 // T1: potential next object start. |
65 // T2: allocation size. | 65 // T2: allocation size. |
66 __ LoadImmediate(T4, heap->TopAddress()); | 66 __ LoadImmediate(T4, heap->TopAddress()); |
67 __ lw(T4, Address(T4, 0)); | 67 __ lw(T4, Address(T4, 0)); |
68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); | 68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); |
69 | 69 |
70 // Successfully allocated the object(s), now update top to point to | 70 // Successfully allocated the object(s), now update top to point to |
71 // next object start and initialize the object. | 71 // next object start and initialize the object. |
72 __ sw(T1, Address(T3, 0)); | 72 __ sw(T1, Address(T3, 0)); |
73 __ addiu(T0, T0, Immediate(kHeapObjectTag)); | 73 __ addiu(T0, T0, Immediate(kHeapObjectTag)); |
| 74 __ UpdateAllocationStatsWithSize(kArrayCid, T2, T4); |
74 | 75 |
75 // Initialize the tags. | 76 // Initialize the tags. |
76 // T0: new object start as a tagged pointer. | 77 // T0: new object start as a tagged pointer. |
77 // T1: new object end address. | 78 // T1: new object end address. |
78 // T2: allocation size. | 79 // T2: allocation size. |
79 { | 80 { |
80 Label overflow, done; | 81 Label overflow, done; |
81 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 82 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
82 const Class& cls = Class::Handle(isolate->object_store()->array_class()); | 83 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
83 | 84 |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 FieldAddress(V0, GrowableObjectArray::data_offset()), | 300 FieldAddress(V0, GrowableObjectArray::data_offset()), |
300 T1); | 301 T1); |
301 | 302 |
302 // V0: new growable array object start as a tagged pointer. | 303 // V0: new growable array object start as a tagged pointer. |
303 // Store the type argument field in the growable array object. | 304 // Store the type argument field in the growable array object. |
304 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument. | 305 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument. |
305 __ StoreIntoObjectNoBarrier( | 306 __ StoreIntoObjectNoBarrier( |
306 V0, | 307 V0, |
307 FieldAddress(V0, GrowableObjectArray::type_arguments_offset()), | 308 FieldAddress(V0, GrowableObjectArray::type_arguments_offset()), |
308 T1); | 309 T1); |
309 | 310 __ UpdateAllocationStats(kGrowableObjectArrayCid, T1); |
310 // Set the length field in the growable array object to 0. | 311 // Set the length field in the growable array object to 0. |
311 __ Ret(); // Returns the newly allocated object in V0. | 312 __ Ret(); // Returns the newly allocated object in V0. |
312 __ delay_slot()->sw(ZR, | 313 __ delay_slot()->sw(ZR, |
313 FieldAddress(V0, GrowableObjectArray::length_offset())); | 314 FieldAddress(V0, GrowableObjectArray::length_offset())); |
314 | 315 |
315 __ Bind(&fall_through); | 316 __ Bind(&fall_through); |
316 } | 317 } |
317 | 318 |
318 | 319 |
319 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 320 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 /* T2: allocation size. */ \ | 492 /* T2: allocation size. */ \ |
492 __ LoadImmediate(T3, heap->EndAddress()); \ | 493 __ LoadImmediate(T3, heap->EndAddress()); \ |
493 __ lw(T3, Address(T3, 0)); \ | 494 __ lw(T3, Address(T3, 0)); \ |
494 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \ | 495 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \ |
495 \ | 496 \ |
496 /* Successfully allocated the object(s), now update top to point to */ \ | 497 /* Successfully allocated the object(s), now update top to point to */ \ |
497 /* next object start and initialize the object. */ \ | 498 /* next object start and initialize the object. */ \ |
498 __ LoadImmediate(T3, heap->TopAddress()); \ | 499 __ LoadImmediate(T3, heap->TopAddress()); \ |
499 __ sw(T1, Address(T3, 0)); \ | 500 __ sw(T1, Address(T3, 0)); \ |
500 __ AddImmediate(V0, kHeapObjectTag); \ | 501 __ AddImmediate(V0, kHeapObjectTag); \ |
501 \ | 502 __ UpdateAllocationStatsWithSize(cid, T2, T4); \ |
502 /* Initialize the tags. */ \ | 503 /* Initialize the tags. */ \ |
503 /* V0: new object start as a tagged pointer. */ \ | 504 /* V0: new object start as a tagged pointer. */ \ |
504 /* T1: new object end address. */ \ | 505 /* T1: new object end address. */ \ |
505 /* T2: allocation size. */ \ | 506 /* T2: allocation size. */ \ |
506 { \ | 507 { \ |
507 Label size_tag_overflow, done; \ | 508 Label size_tag_overflow, done; \ |
508 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, \ | 509 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, \ |
509 &size_tag_overflow); \ | 510 &size_tag_overflow); \ |
510 __ b(&done); \ | 511 __ b(&done); \ |
511 __ delay_slot()->sll(T2, T2, \ | 512 __ delay_slot()->sll(T2, T2, \ |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 __ subu(T4, ZR, T0); // T4 <- -T0 | 848 __ subu(T4, ZR, T0); // T4 <- -T0 |
848 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0 | 849 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0 |
849 __ sllv(T3, T3, T4); // T3 <- T3 << T4 | 850 __ sllv(T3, T3, T4); // T3 <- T3 << T4 |
850 __ and_(T3, T3, T1); // T3 <- T3 & T1 | 851 __ and_(T3, T3, T1); // T3 <- T3 & T1 |
851 __ srlv(T3, T3, T4); // T3 <- T3 >> T4 | 852 __ srlv(T3, T3, T4); // T3 <- T3 >> T4 |
852 // Now T3 has the bits that fall off of T1 on a left shift. | 853 // Now T3 has the bits that fall off of T1 on a left shift. |
853 __ sllv(T0, T1, T0); // T0 gets low bits. | 854 __ sllv(T0, T1, T0); // T0 gets low bits. |
854 | 855 |
855 const Class& mint_class = Class::Handle( | 856 const Class& mint_class = Class::Handle( |
856 Isolate::Current()->object_store()->mint_class()); | 857 Isolate::Current()->object_store()->mint_class()); |
857 __ TryAllocate(mint_class, &fall_through, V0); | 858 __ TryAllocate(mint_class, &fall_through, V0, T1); |
858 | 859 |
859 __ sw(T0, FieldAddress(V0, Mint::value_offset())); | 860 __ sw(T0, FieldAddress(V0, Mint::value_offset())); |
860 __ Ret(); | 861 __ Ret(); |
861 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize)); | 862 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize)); |
862 __ Bind(&fall_through); | 863 __ Bind(&fall_through); |
863 } | 864 } |
864 | 865 |
865 | 866 |
866 static void Get64SmiOrMint(Assembler* assembler, | 867 static void Get64SmiOrMint(Assembler* assembler, |
867 Register res_hi, | 868 Register res_hi, |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | 1188 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); |
1188 switch (kind) { | 1189 switch (kind) { |
1189 case Token::kADD: __ addd(D0, D0, D1); break; | 1190 case Token::kADD: __ addd(D0, D0, D1); break; |
1190 case Token::kSUB: __ subd(D0, D0, D1); break; | 1191 case Token::kSUB: __ subd(D0, D0, D1); break; |
1191 case Token::kMUL: __ muld(D0, D0, D1); break; | 1192 case Token::kMUL: __ muld(D0, D0, D1); break; |
1192 case Token::kDIV: __ divd(D0, D0, D1); break; | 1193 case Token::kDIV: __ divd(D0, D0, D1); break; |
1193 default: UNREACHABLE(); | 1194 default: UNREACHABLE(); |
1194 } | 1195 } |
1195 const Class& double_class = Class::Handle( | 1196 const Class& double_class = Class::Handle( |
1196 Isolate::Current()->object_store()->double_class()); | 1197 Isolate::Current()->object_store()->double_class()); |
1197 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1198 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
1198 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1199 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
1199 __ Ret(); | 1200 __ Ret(); |
1200 __ delay_slot()->swc1(F1, | 1201 __ delay_slot()->swc1(F1, |
1201 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1202 FieldAddress(V0, Double::value_offset() + kWordSize)); |
1202 __ Bind(&fall_through); | 1203 __ Bind(&fall_through); |
1203 } | 1204 } |
1204 | 1205 |
1205 | 1206 |
1206 void Intrinsifier::Double_add(Assembler* assembler) { | 1207 void Intrinsifier::Double_add(Assembler* assembler) { |
1207 return DoubleArithmeticOperations(assembler, Token::kADD); | 1208 return DoubleArithmeticOperations(assembler, Token::kADD); |
(...skipping 27 matching lines...) Expand all Loading... |
1235 __ SmiUntag(T0); | 1236 __ SmiUntag(T0); |
1236 __ mtc1(T0, F4); | 1237 __ mtc1(T0, F4); |
1237 __ cvtdw(D1, F4); | 1238 __ cvtdw(D1, F4); |
1238 | 1239 |
1239 __ lw(T0, Address(SP, 1 * kWordSize)); | 1240 __ lw(T0, Address(SP, 1 * kWordSize)); |
1240 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); | 1241 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); |
1241 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | 1242 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); |
1242 __ muld(D0, D0, D1); | 1243 __ muld(D0, D0, D1); |
1243 const Class& double_class = Class::Handle( | 1244 const Class& double_class = Class::Handle( |
1244 Isolate::Current()->object_store()->double_class()); | 1245 Isolate::Current()->object_store()->double_class()); |
1245 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1246 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
1246 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1247 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
1247 __ Ret(); | 1248 __ Ret(); |
1248 __ delay_slot()->swc1(F1, | 1249 __ delay_slot()->swc1(F1, |
1249 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1250 FieldAddress(V0, Double::value_offset() + kWordSize)); |
1250 __ Bind(&fall_through); | 1251 __ Bind(&fall_through); |
1251 } | 1252 } |
1252 | 1253 |
1253 | 1254 |
1254 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1255 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |
1255 Label fall_through; | 1256 Label fall_through; |
1256 | 1257 |
1257 __ lw(T0, Address(SP, 0 * kWordSize)); | 1258 __ lw(T0, Address(SP, 0 * kWordSize)); |
1258 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 1259 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
1259 __ bne(T0, ZR, &fall_through); | 1260 __ bne(T0, ZR, &fall_through); |
1260 | 1261 |
1261 // Is Smi. | 1262 // Is Smi. |
1262 __ SmiUntag(T0); | 1263 __ SmiUntag(T0); |
1263 __ mtc1(T0, F4); | 1264 __ mtc1(T0, F4); |
1264 __ cvtdw(D0, F4); | 1265 __ cvtdw(D0, F4); |
1265 const Class& double_class = Class::Handle( | 1266 const Class& double_class = Class::Handle( |
1266 Isolate::Current()->object_store()->double_class()); | 1267 Isolate::Current()->object_store()->double_class()); |
1267 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1268 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
1268 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1269 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
1269 __ Ret(); | 1270 __ Ret(); |
1270 __ delay_slot()->swc1(F1, | 1271 __ delay_slot()->swc1(F1, |
1271 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1272 FieldAddress(V0, Double::value_offset() + kWordSize)); |
1272 __ Bind(&fall_through); | 1273 __ Bind(&fall_through); |
1273 } | 1274 } |
1274 | 1275 |
1275 | 1276 |
1276 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1277 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
1277 Label is_true; | 1278 Label is_true; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1343 | 1344 |
1344 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1345 void Intrinsifier::Math_sqrt(Assembler* assembler) { |
1345 Label fall_through, is_smi, double_op; | 1346 Label fall_through, is_smi, double_op; |
1346 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1347 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1347 // Argument is double and is in T0. | 1348 // Argument is double and is in T0. |
1348 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); | 1349 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); |
1349 __ Bind(&double_op); | 1350 __ Bind(&double_op); |
1350 __ sqrtd(D0, D1); | 1351 __ sqrtd(D0, D1); |
1351 const Class& double_class = Class::Handle( | 1352 const Class& double_class = Class::Handle( |
1352 Isolate::Current()->object_store()->double_class()); | 1353 Isolate::Current()->object_store()->double_class()); |
1353 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1354 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
1354 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1355 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
1355 __ Ret(); | 1356 __ Ret(); |
1356 __ delay_slot()->swc1(F1, | 1357 __ delay_slot()->swc1(F1, |
1357 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1358 FieldAddress(V0, Double::value_offset() + kWordSize)); |
1358 | 1359 |
1359 __ Bind(&is_smi); | 1360 __ Bind(&is_smi); |
1360 __ SmiUntag(T0); | 1361 __ SmiUntag(T0); |
1361 __ mtc1(T0, F2); | 1362 __ mtc1(T0, F2); |
1362 __ b(&double_op); | 1363 __ b(&double_op); |
1363 __ delay_slot()->cvtdw(D1, F2); | 1364 __ delay_slot()->cvtdw(D1, F2); |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 // T3: heap->TopAddress(). | 1593 // T3: heap->TopAddress(). |
1593 __ LoadImmediate(T4, heap->EndAddress()); | 1594 __ LoadImmediate(T4, heap->EndAddress()); |
1594 __ lw(T4, Address(T4, 0)); | 1595 __ lw(T4, Address(T4, 0)); |
1595 __ BranchUnsignedGreaterEqual(T1, T4, failure); | 1596 __ BranchUnsignedGreaterEqual(T1, T4, failure); |
1596 | 1597 |
1597 // Successfully allocated the object(s), now update top to point to | 1598 // Successfully allocated the object(s), now update top to point to |
1598 // next object start and initialize the object. | 1599 // next object start and initialize the object. |
1599 __ sw(T1, Address(T3, 0)); | 1600 __ sw(T1, Address(T3, 0)); |
1600 __ AddImmediate(V0, kHeapObjectTag); | 1601 __ AddImmediate(V0, kHeapObjectTag); |
1601 | 1602 |
| 1603 __ UpdateAllocationStatsWithSize(kOneByteStringCid, T2, T3); |
| 1604 |
1602 // Initialize the tags. | 1605 // Initialize the tags. |
1603 // V0: new object start as a tagged pointer. | 1606 // V0: new object start as a tagged pointer. |
1604 // T1: new object end address. | 1607 // T1: new object end address. |
1605 // T2: allocation size. | 1608 // T2: allocation size. |
1606 { | 1609 { |
1607 Label overflow, done; | 1610 Label overflow, done; |
1608 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 1611 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
1609 const Class& cls = | 1612 const Class& cls = |
1610 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1613 Class::Handle(isolate->object_store()->one_byte_string_class()); |
1611 | 1614 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1775 } | 1778 } |
1776 | 1779 |
1777 | 1780 |
1778 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 1781 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |
1779 StringEquality(assembler, kTwoByteStringCid); | 1782 StringEquality(assembler, kTwoByteStringCid); |
1780 } | 1783 } |
1781 | 1784 |
1782 } // namespace dart | 1785 } // namespace dart |
1783 | 1786 |
1784 #endif // defined TARGET_ARCH_MIPS | 1787 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |