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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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 // R2: allocation size. | 64 // R2: allocation size. |
65 __ LoadImmediate(R3, heap->EndAddress()); | 65 __ LoadImmediate(R3, heap->EndAddress()); |
66 __ ldr(R3, Address(R3, 0)); | 66 __ ldr(R3, Address(R3, 0)); |
67 __ cmp(R1, ShifterOperand(R3)); | 67 __ cmp(R1, ShifterOperand(R3)); |
68 __ b(&fall_through, CS); | 68 __ b(&fall_through, CS); |
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 __ str(R1, Address(R6, 0)); | 72 __ str(R1, Address(R6, 0)); |
73 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); | 73 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); |
| 74 __ UpdateAllocationStatsWithSize(kArrayCid, R2, R4); |
74 | 75 |
75 // Initialize the tags. | 76 // Initialize the tags. |
76 // R0: new object start as a tagged pointer. | 77 // R0: new object start as a tagged pointer. |
77 // R1: new object end address. | 78 // R1: new object end address. |
78 // R2: allocation size. | 79 // R2: allocation size. |
79 { | 80 { |
80 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 81 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
81 const Class& cls = Class::Handle(isolate->object_store()->array_class()); | 82 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
82 | 83 |
83 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); | 84 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 // Store the type argument field in the growable array object. | 300 // Store the type argument field in the growable array object. |
300 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. | 301 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. |
301 __ StoreIntoObjectNoBarrier( | 302 __ StoreIntoObjectNoBarrier( |
302 R0, | 303 R0, |
303 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), | 304 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), |
304 R1); | 305 R1); |
305 | 306 |
306 // Set the length field in the growable array object to 0. | 307 // Set the length field in the growable array object to 0. |
307 __ LoadImmediate(R1, 0); | 308 __ LoadImmediate(R1, 0); |
308 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); | 309 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); |
| 310 __ UpdateAllocationStats(kGrowableObjectArrayCid, R1); |
309 __ Ret(); // Returns the newly allocated object in R0. | 311 __ Ret(); // Returns the newly allocated object in R0. |
310 | 312 |
311 __ Bind(&fall_through); | 313 __ Bind(&fall_through); |
312 } | 314 } |
313 | 315 |
314 | 316 |
315 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 317 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { |
316 __ ldr(R0, Address(SP, 0 * kWordSize)); | 318 __ ldr(R0, Address(SP, 0 * kWordSize)); |
317 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); | 319 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); |
318 __ Ret(); | 320 __ Ret(); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 __ LoadImmediate(R3, heap->EndAddress()); \ | 486 __ LoadImmediate(R3, heap->EndAddress()); \ |
485 __ ldr(R3, Address(R3, 0)); \ | 487 __ ldr(R3, Address(R3, 0)); \ |
486 __ cmp(R1, ShifterOperand(R3)); \ | 488 __ cmp(R1, ShifterOperand(R3)); \ |
487 __ b(&fall_through, CS); \ | 489 __ b(&fall_through, CS); \ |
488 \ | 490 \ |
489 /* Successfully allocated the object(s), now update top to point to */ \ | 491 /* Successfully allocated the object(s), now update top to point to */ \ |
490 /* next object start and initialize the object. */ \ | 492 /* next object start and initialize the object. */ \ |
491 __ LoadImmediate(R3, heap->TopAddress()); \ | 493 __ LoadImmediate(R3, heap->TopAddress()); \ |
492 __ str(R1, Address(R3, 0)); \ | 494 __ str(R1, Address(R3, 0)); \ |
493 __ AddImmediate(R0, kHeapObjectTag); \ | 495 __ AddImmediate(R0, kHeapObjectTag); \ |
494 \ | 496 __ UpdateAllocationStatsWithSize(cid, R2, R4); \ |
495 /* Initialize the tags. */ \ | 497 /* Initialize the tags. */ \ |
496 /* R0: new object start as a tagged pointer. */ \ | 498 /* R0: new object start as a tagged pointer. */ \ |
497 /* R1: new object end address. */ \ | 499 /* R1: new object end address. */ \ |
498 /* R2: allocation size. */ \ | 500 /* R2: allocation size. */ \ |
499 { \ | 501 { \ |
500 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ | 502 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ |
501 __ mov(R2, ShifterOperand(R2, LSL, \ | 503 __ mov(R2, ShifterOperand(R2, LSL, \ |
502 RawObject::kSizeTagBit - kObjectAlignmentLog2), LS); \ | 504 RawObject::kSizeTagBit - kObjectAlignmentLog2), LS); \ |
503 __ mov(R2, ShifterOperand(0), HI); \ | 505 __ mov(R2, ShifterOperand(0), HI); \ |
504 \ | 506 \ |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
839 __ sub(R7, R7, ShifterOperand(1)); // R7 <- R7 - 1 | 841 __ sub(R7, R7, ShifterOperand(1)); // R7 <- R7 - 1 |
840 __ rsb(R8, R0, ShifterOperand(32)); // R8 <- 32 - R0 | 842 __ rsb(R8, R0, ShifterOperand(32)); // R8 <- 32 - R0 |
841 __ mov(R7, ShifterOperand(R7, LSL, R8)); // R7 <- R7 << R8 | 843 __ mov(R7, ShifterOperand(R7, LSL, R8)); // R7 <- R7 << R8 |
842 __ and_(R7, R1, ShifterOperand(R7)); // R7 <- R7 & R1 | 844 __ and_(R7, R1, ShifterOperand(R7)); // R7 <- R7 & R1 |
843 __ mov(R7, ShifterOperand(R7, LSR, R8)); // R7 <- R7 >> R8 | 845 __ mov(R7, ShifterOperand(R7, LSR, R8)); // R7 <- R7 >> R8 |
844 // Now R7 has the bits that fall off of R1 on a left shift. | 846 // Now R7 has the bits that fall off of R1 on a left shift. |
845 __ mov(R1, ShifterOperand(R1, LSL, R0)); // R1 gets the low bits. | 847 __ mov(R1, ShifterOperand(R1, LSL, R0)); // R1 gets the low bits. |
846 | 848 |
847 const Class& mint_class = Class::Handle( | 849 const Class& mint_class = Class::Handle( |
848 Isolate::Current()->object_store()->mint_class()); | 850 Isolate::Current()->object_store()->mint_class()); |
849 __ TryAllocate(mint_class, &fall_through, R0); | 851 __ TryAllocate(mint_class, &fall_through, R0, R2); |
850 | 852 |
851 | 853 |
852 __ str(R1, FieldAddress(R0, Mint::value_offset())); | 854 __ str(R1, FieldAddress(R0, Mint::value_offset())); |
853 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); | 855 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); |
854 __ Ret(); | 856 __ Ret(); |
855 __ Bind(&fall_through); | 857 __ Bind(&fall_through); |
856 } | 858 } |
857 | 859 |
858 | 860 |
859 static void Get64SmiOrMint(Assembler* assembler, | 861 static void Get64SmiOrMint(Assembler* assembler, |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1143 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1142 switch (kind) { | 1144 switch (kind) { |
1143 case Token::kADD: __ vaddd(D0, D0, D1); break; | 1145 case Token::kADD: __ vaddd(D0, D0, D1); break; |
1144 case Token::kSUB: __ vsubd(D0, D0, D1); break; | 1146 case Token::kSUB: __ vsubd(D0, D0, D1); break; |
1145 case Token::kMUL: __ vmuld(D0, D0, D1); break; | 1147 case Token::kMUL: __ vmuld(D0, D0, D1); break; |
1146 case Token::kDIV: __ vdivd(D0, D0, D1); break; | 1148 case Token::kDIV: __ vdivd(D0, D0, D1); break; |
1147 default: UNREACHABLE(); | 1149 default: UNREACHABLE(); |
1148 } | 1150 } |
1149 const Class& double_class = Class::Handle( | 1151 const Class& double_class = Class::Handle( |
1150 Isolate::Current()->object_store()->double_class()); | 1152 Isolate::Current()->object_store()->double_class()); |
1151 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1153 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1152 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1154 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1153 __ Ret(); | 1155 __ Ret(); |
1154 __ Bind(&fall_through); | 1156 __ Bind(&fall_through); |
1155 } | 1157 } |
1156 | 1158 |
1157 | 1159 |
1158 void Intrinsifier::Double_add(Assembler* assembler) { | 1160 void Intrinsifier::Double_add(Assembler* assembler) { |
1159 return DoubleArithmeticOperations(assembler, Token::kADD); | 1161 return DoubleArithmeticOperations(assembler, Token::kADD); |
1160 } | 1162 } |
1161 | 1163 |
(...skipping 22 matching lines...) Expand all Loading... |
1184 __ b(&fall_through, NE); | 1186 __ b(&fall_through, NE); |
1185 // Is Smi. | 1187 // Is Smi. |
1186 __ SmiUntag(R0); | 1188 __ SmiUntag(R0); |
1187 __ vmovsr(S0, R0); | 1189 __ vmovsr(S0, R0); |
1188 __ vcvtdi(D1, S0); | 1190 __ vcvtdi(D1, S0); |
1189 __ ldr(R0, Address(SP, 1 * kWordSize)); | 1191 __ ldr(R0, Address(SP, 1 * kWordSize)); |
1190 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1192 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1191 __ vmuld(D0, D0, D1); | 1193 __ vmuld(D0, D0, D1); |
1192 const Class& double_class = Class::Handle( | 1194 const Class& double_class = Class::Handle( |
1193 Isolate::Current()->object_store()->double_class()); | 1195 Isolate::Current()->object_store()->double_class()); |
1194 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1196 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1195 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1197 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1196 __ Ret(); | 1198 __ Ret(); |
1197 __ Bind(&fall_through); | 1199 __ Bind(&fall_through); |
1198 } | 1200 } |
1199 | 1201 |
1200 | 1202 |
1201 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1203 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |
1202 Label fall_through; | 1204 Label fall_through; |
1203 | 1205 |
1204 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1206 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1205 __ tst(R0, ShifterOperand(kSmiTagMask)); | 1207 __ tst(R0, ShifterOperand(kSmiTagMask)); |
1206 __ b(&fall_through, NE); | 1208 __ b(&fall_through, NE); |
1207 // Is Smi. | 1209 // Is Smi. |
1208 __ SmiUntag(R0); | 1210 __ SmiUntag(R0); |
1209 __ vmovsr(S0, R0); | 1211 __ vmovsr(S0, R0); |
1210 __ vcvtdi(D0, S0); | 1212 __ vcvtdi(D0, S0); |
1211 const Class& double_class = Class::Handle( | 1213 const Class& double_class = Class::Handle( |
1212 Isolate::Current()->object_store()->double_class()); | 1214 Isolate::Current()->object_store()->double_class()); |
1213 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1215 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1214 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1216 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1215 __ Ret(); | 1217 __ Ret(); |
1216 __ Bind(&fall_through); | 1218 __ Bind(&fall_through); |
1217 } | 1219 } |
1218 | 1220 |
1219 | 1221 |
1220 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1222 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
1221 Label is_true; | 1223 Label is_true; |
1222 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1224 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1223 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1225 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 | 1286 |
1285 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1287 void Intrinsifier::Math_sqrt(Assembler* assembler) { |
1286 Label fall_through, is_smi, double_op; | 1288 Label fall_through, is_smi, double_op; |
1287 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1289 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1288 // Argument is double and is in R0. | 1290 // Argument is double and is in R0. |
1289 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag); | 1291 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag); |
1290 __ Bind(&double_op); | 1292 __ Bind(&double_op); |
1291 __ vsqrtd(D0, D1); | 1293 __ vsqrtd(D0, D1); |
1292 const Class& double_class = Class::Handle( | 1294 const Class& double_class = Class::Handle( |
1293 Isolate::Current()->object_store()->double_class()); | 1295 Isolate::Current()->object_store()->double_class()); |
1294 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1296 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1295 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1297 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1296 __ Ret(); | 1298 __ Ret(); |
1297 __ Bind(&is_smi); | 1299 __ Bind(&is_smi); |
1298 __ SmiUntag(R0); | 1300 __ SmiUntag(R0); |
1299 __ vmovsr(S0, R0); | 1301 __ vmovsr(S0, R0); |
1300 __ vcvtdi(D1, S0); | 1302 __ vcvtdi(D1, S0); |
1301 __ b(&double_op); | 1303 __ b(&double_op); |
1302 __ Bind(&fall_through); | 1304 __ Bind(&fall_through); |
1303 } | 1305 } |
1304 | 1306 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 // R3: heap->Top->Address(). | 1509 // R3: heap->Top->Address(). |
1508 __ LoadImmediate(R7, heap->EndAddress()); | 1510 __ LoadImmediate(R7, heap->EndAddress()); |
1509 __ ldr(R7, Address(R7, 0)); | 1511 __ ldr(R7, Address(R7, 0)); |
1510 __ cmp(R1, ShifterOperand(R7)); | 1512 __ cmp(R1, ShifterOperand(R7)); |
1511 __ b(&fail, CS); | 1513 __ b(&fail, CS); |
1512 | 1514 |
1513 // Successfully allocated the object(s), now update top to point to | 1515 // Successfully allocated the object(s), now update top to point to |
1514 // next object start and initialize the object. | 1516 // next object start and initialize the object. |
1515 __ str(R1, Address(R3, 0)); | 1517 __ str(R1, Address(R3, 0)); |
1516 __ AddImmediate(R0, kHeapObjectTag); | 1518 __ AddImmediate(R0, kHeapObjectTag); |
| 1519 __ UpdateAllocationStatsWithSize(kOneByteStringCid, R2, R3); |
1517 | 1520 |
1518 // Initialize the tags. | 1521 // Initialize the tags. |
1519 // R0: new object start as a tagged pointer. | 1522 // R0: new object start as a tagged pointer. |
1520 // R1: new object end address. | 1523 // R1: new object end address. |
1521 // R2: allocation size. | 1524 // R2: allocation size. |
1522 { | 1525 { |
1523 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 1526 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
1524 const Class& cls = | 1527 const Class& cls = |
1525 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1528 Class::Handle(isolate->object_store()->one_byte_string_class()); |
1526 | 1529 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1703 | 1706 |
1704 | 1707 |
1705 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 1708 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |
1706 StringEquality(assembler, kTwoByteStringCid); | 1709 StringEquality(assembler, kTwoByteStringCid); |
1707 } | 1710 } |
1708 | 1711 |
1709 | 1712 |
1710 } // namespace dart | 1713 } // namespace dart |
1711 | 1714 |
1712 #endif // defined TARGET_ARCH_ARM | 1715 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |