| 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 |