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 __ BumpAllocationCount(Heap::kNew, 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 29 matching lines...) Expand all Loading... |
113 // R3: null | 114 // R3: null |
114 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 115 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
115 __ AddImmediate(R2, R0, sizeof(RawArray) - kHeapObjectTag); | 116 __ AddImmediate(R2, R0, sizeof(RawArray) - kHeapObjectTag); |
116 | 117 |
117 Label init_loop; | 118 Label init_loop; |
118 __ Bind(&init_loop); | 119 __ Bind(&init_loop); |
119 __ cmp(R2, ShifterOperand(R1)); | 120 __ cmp(R2, ShifterOperand(R1)); |
120 __ str(R3, Address(R2, 0), CC); | 121 __ str(R3, Address(R2, 0), CC); |
121 __ AddImmediate(R2, kWordSize, CC); | 122 __ AddImmediate(R2, kWordSize, CC); |
122 __ b(&init_loop, CC); | 123 __ b(&init_loop, CC); |
123 | |
124 __ Ret(); // Returns the newly allocated object in R0. | 124 __ Ret(); // Returns the newly allocated object in R0. |
125 __ Bind(&fall_through); | 125 __ Bind(&fall_through); |
126 } | 126 } |
127 | 127 |
128 | 128 |
129 void Intrinsifier::Array_getLength(Assembler* assembler) { | 129 void Intrinsifier::Array_getLength(Assembler* assembler) { |
130 __ ldr(R0, Address(SP, 0 * kWordSize)); | 130 __ ldr(R0, Address(SP, 0 * kWordSize)); |
131 __ ldr(R0, FieldAddress(R0, Array::length_offset())); | 131 __ ldr(R0, FieldAddress(R0, Array::length_offset())); |
132 __ Ret(); | 132 __ Ret(); |
133 } | 133 } |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 // Store the type argument field in the growable array object. | 299 // Store the type argument field in the growable array object. |
300 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. | 300 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. |
301 __ StoreIntoObjectNoBarrier( | 301 __ StoreIntoObjectNoBarrier( |
302 R0, | 302 R0, |
303 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), | 303 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), |
304 R1); | 304 R1); |
305 | 305 |
306 // Set the length field in the growable array object to 0. | 306 // Set the length field in the growable array object to 0. |
307 __ LoadImmediate(R1, 0); | 307 __ LoadImmediate(R1, 0); |
308 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); | 308 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); |
| 309 __ BumpAllocationCount(Heap::kNew, kGrowableObjectArrayCid, R1); |
309 __ Ret(); // Returns the newly allocated object in R0. | 310 __ Ret(); // Returns the newly allocated object in R0. |
310 | 311 |
311 __ Bind(&fall_through); | 312 __ Bind(&fall_through); |
312 } | 313 } |
313 | 314 |
314 | 315 |
315 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 316 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { |
316 __ ldr(R0, Address(SP, 0 * kWordSize)); | 317 __ ldr(R0, Address(SP, 0 * kWordSize)); |
317 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); | 318 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); |
318 __ Ret(); | 319 __ Ret(); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 __ LoadImmediate(R3, heap->EndAddress()); \ | 485 __ LoadImmediate(R3, heap->EndAddress()); \ |
485 __ ldr(R3, Address(R3, 0)); \ | 486 __ ldr(R3, Address(R3, 0)); \ |
486 __ cmp(R1, ShifterOperand(R3)); \ | 487 __ cmp(R1, ShifterOperand(R3)); \ |
487 __ b(&fall_through, CS); \ | 488 __ b(&fall_through, CS); \ |
488 \ | 489 \ |
489 /* Successfully allocated the object(s), now update top to point to */ \ | 490 /* Successfully allocated the object(s), now update top to point to */ \ |
490 /* next object start and initialize the object. */ \ | 491 /* next object start and initialize the object. */ \ |
491 __ LoadImmediate(R3, heap->TopAddress()); \ | 492 __ LoadImmediate(R3, heap->TopAddress()); \ |
492 __ str(R1, Address(R3, 0)); \ | 493 __ str(R1, Address(R3, 0)); \ |
493 __ AddImmediate(R0, kHeapObjectTag); \ | 494 __ AddImmediate(R0, kHeapObjectTag); \ |
494 \ | 495 __ BumpAllocationCount(Heap::kNew, cid, R2, R4); \ |
495 /* Initialize the tags. */ \ | 496 /* Initialize the tags. */ \ |
496 /* R0: new object start as a tagged pointer. */ \ | 497 /* R0: new object start as a tagged pointer. */ \ |
497 /* R1: new object end address. */ \ | 498 /* R1: new object end address. */ \ |
498 /* R2: allocation size. */ \ | 499 /* R2: allocation size. */ \ |
499 { \ | 500 { \ |
500 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ | 501 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ |
501 __ mov(R2, ShifterOperand(R2, LSL, \ | 502 __ mov(R2, ShifterOperand(R2, LSL, \ |
502 RawObject::kSizeTagBit - kObjectAlignmentLog2), LS); \ | 503 RawObject::kSizeTagBit - kObjectAlignmentLog2), LS); \ |
503 __ mov(R2, ShifterOperand(0), HI); \ | 504 __ mov(R2, ShifterOperand(0), HI); \ |
504 \ | 505 \ |
(...skipping 16 matching lines...) Expand all Loading... |
521 /* R3: scratch register. */ \ | 522 /* R3: scratch register. */ \ |
522 /* data area to be initialized. */ \ | 523 /* data area to be initialized. */ \ |
523 __ LoadImmediate(R3, 0); \ | 524 __ LoadImmediate(R3, 0); \ |
524 __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1); \ | 525 __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1); \ |
525 Label init_loop; \ | 526 Label init_loop; \ |
526 __ Bind(&init_loop); \ | 527 __ Bind(&init_loop); \ |
527 __ cmp(R2, ShifterOperand(R1)); \ | 528 __ cmp(R2, ShifterOperand(R1)); \ |
528 __ str(R3, Address(R2, 0), CC); \ | 529 __ str(R3, Address(R2, 0), CC); \ |
529 __ add(R2, R2, ShifterOperand(kWordSize), CC); \ | 530 __ add(R2, R2, ShifterOperand(kWordSize), CC); \ |
530 __ b(&init_loop, CC); \ | 531 __ b(&init_loop, CC); \ |
531 \ | |
532 __ Ret(); \ | 532 __ Ret(); \ |
533 __ Bind(&fall_through); \ | 533 __ Bind(&fall_through); \ |
534 | 534 |
535 | 535 |
536 // Gets the length of a TypedData. | 536 // Gets the length of a TypedData. |
537 void Intrinsifier::TypedData_getLength(Assembler* assembler) { | 537 void Intrinsifier::TypedData_getLength(Assembler* assembler) { |
538 __ ldr(R0, Address(SP, 0 * kWordSize)); | 538 __ ldr(R0, Address(SP, 0 * kWordSize)); |
539 __ ldr(R0, FieldAddress(R0, TypedData::length_offset())); | 539 __ ldr(R0, FieldAddress(R0, TypedData::length_offset())); |
540 __ Ret(); | 540 __ Ret(); |
541 } | 541 } |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
839 __ sub(R7, R7, ShifterOperand(1)); // R7 <- R7 - 1 | 839 __ sub(R7, R7, ShifterOperand(1)); // R7 <- R7 - 1 |
840 __ rsb(R8, R0, ShifterOperand(32)); // R8 <- 32 - R0 | 840 __ rsb(R8, R0, ShifterOperand(32)); // R8 <- 32 - R0 |
841 __ mov(R7, ShifterOperand(R7, LSL, R8)); // R7 <- R7 << R8 | 841 __ mov(R7, ShifterOperand(R7, LSL, R8)); // R7 <- R7 << R8 |
842 __ and_(R7, R1, ShifterOperand(R7)); // R7 <- R7 & R1 | 842 __ and_(R7, R1, ShifterOperand(R7)); // R7 <- R7 & R1 |
843 __ mov(R7, ShifterOperand(R7, LSR, R8)); // R7 <- R7 >> R8 | 843 __ mov(R7, ShifterOperand(R7, LSR, R8)); // R7 <- R7 >> R8 |
844 // Now R7 has the bits that fall off of R1 on a left shift. | 844 // 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. | 845 __ mov(R1, ShifterOperand(R1, LSL, R0)); // R1 gets the low bits. |
846 | 846 |
847 const Class& mint_class = Class::Handle( | 847 const Class& mint_class = Class::Handle( |
848 Isolate::Current()->object_store()->mint_class()); | 848 Isolate::Current()->object_store()->mint_class()); |
849 __ TryAllocate(mint_class, &fall_through, R0); | 849 __ TryAllocate(mint_class, &fall_through, R0, R2); |
850 | 850 |
851 | 851 |
852 __ str(R1, FieldAddress(R0, Mint::value_offset())); | 852 __ str(R1, FieldAddress(R0, Mint::value_offset())); |
853 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); | 853 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); |
854 __ Ret(); | 854 __ Ret(); |
855 __ Bind(&fall_through); | 855 __ Bind(&fall_through); |
856 } | 856 } |
857 | 857 |
858 | 858 |
859 static void Get64SmiOrMint(Assembler* assembler, | 859 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); | 1141 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1142 switch (kind) { | 1142 switch (kind) { |
1143 case Token::kADD: __ vaddd(D0, D0, D1); break; | 1143 case Token::kADD: __ vaddd(D0, D0, D1); break; |
1144 case Token::kSUB: __ vsubd(D0, D0, D1); break; | 1144 case Token::kSUB: __ vsubd(D0, D0, D1); break; |
1145 case Token::kMUL: __ vmuld(D0, D0, D1); break; | 1145 case Token::kMUL: __ vmuld(D0, D0, D1); break; |
1146 case Token::kDIV: __ vdivd(D0, D0, D1); break; | 1146 case Token::kDIV: __ vdivd(D0, D0, D1); break; |
1147 default: UNREACHABLE(); | 1147 default: UNREACHABLE(); |
1148 } | 1148 } |
1149 const Class& double_class = Class::Handle( | 1149 const Class& double_class = Class::Handle( |
1150 Isolate::Current()->object_store()->double_class()); | 1150 Isolate::Current()->object_store()->double_class()); |
1151 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1151 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1152 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1152 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1153 __ Ret(); | 1153 __ Ret(); |
1154 __ Bind(&fall_through); | 1154 __ Bind(&fall_through); |
1155 } | 1155 } |
1156 | 1156 |
1157 | 1157 |
1158 void Intrinsifier::Double_add(Assembler* assembler) { | 1158 void Intrinsifier::Double_add(Assembler* assembler) { |
1159 return DoubleArithmeticOperations(assembler, Token::kADD); | 1159 return DoubleArithmeticOperations(assembler, Token::kADD); |
1160 } | 1160 } |
1161 | 1161 |
(...skipping 22 matching lines...) Expand all Loading... |
1184 __ b(&fall_through, NE); | 1184 __ b(&fall_through, NE); |
1185 // Is Smi. | 1185 // Is Smi. |
1186 __ SmiUntag(R0); | 1186 __ SmiUntag(R0); |
1187 __ vmovsr(S0, R0); | 1187 __ vmovsr(S0, R0); |
1188 __ vcvtdi(D1, S0); | 1188 __ vcvtdi(D1, S0); |
1189 __ ldr(R0, Address(SP, 1 * kWordSize)); | 1189 __ ldr(R0, Address(SP, 1 * kWordSize)); |
1190 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1190 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1191 __ vmuld(D0, D0, D1); | 1191 __ vmuld(D0, D0, D1); |
1192 const Class& double_class = Class::Handle( | 1192 const Class& double_class = Class::Handle( |
1193 Isolate::Current()->object_store()->double_class()); | 1193 Isolate::Current()->object_store()->double_class()); |
1194 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1194 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1195 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1195 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1196 __ Ret(); | 1196 __ Ret(); |
1197 __ Bind(&fall_through); | 1197 __ Bind(&fall_through); |
1198 } | 1198 } |
1199 | 1199 |
1200 | 1200 |
1201 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1201 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |
1202 Label fall_through; | 1202 Label fall_through; |
1203 | 1203 |
1204 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1204 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1205 __ tst(R0, ShifterOperand(kSmiTagMask)); | 1205 __ tst(R0, ShifterOperand(kSmiTagMask)); |
1206 __ b(&fall_through, NE); | 1206 __ b(&fall_through, NE); |
1207 // Is Smi. | 1207 // Is Smi. |
1208 __ SmiUntag(R0); | 1208 __ SmiUntag(R0); |
1209 __ vmovsr(S0, R0); | 1209 __ vmovsr(S0, R0); |
1210 __ vcvtdi(D0, S0); | 1210 __ vcvtdi(D0, S0); |
1211 const Class& double_class = Class::Handle( | 1211 const Class& double_class = Class::Handle( |
1212 Isolate::Current()->object_store()->double_class()); | 1212 Isolate::Current()->object_store()->double_class()); |
1213 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1213 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1214 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1214 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1215 __ Ret(); | 1215 __ Ret(); |
1216 __ Bind(&fall_through); | 1216 __ Bind(&fall_through); |
1217 } | 1217 } |
1218 | 1218 |
1219 | 1219 |
1220 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1220 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
1221 Label is_true; | 1221 Label is_true; |
1222 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1222 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1223 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1223 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 | 1284 |
1285 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1285 void Intrinsifier::Math_sqrt(Assembler* assembler) { |
1286 Label fall_through, is_smi, double_op; | 1286 Label fall_through, is_smi, double_op; |
1287 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1287 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1288 // Argument is double and is in R0. | 1288 // Argument is double and is in R0. |
1289 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag); | 1289 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag); |
1290 __ Bind(&double_op); | 1290 __ Bind(&double_op); |
1291 __ vsqrtd(D0, D1); | 1291 __ vsqrtd(D0, D1); |
1292 const Class& double_class = Class::Handle( | 1292 const Class& double_class = Class::Handle( |
1293 Isolate::Current()->object_store()->double_class()); | 1293 Isolate::Current()->object_store()->double_class()); |
1294 __ TryAllocate(double_class, &fall_through, R0); // Result register. | 1294 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. |
1295 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); | 1295 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); |
1296 __ Ret(); | 1296 __ Ret(); |
1297 __ Bind(&is_smi); | 1297 __ Bind(&is_smi); |
1298 __ SmiUntag(R0); | 1298 __ SmiUntag(R0); |
1299 __ vmovsr(S0, R0); | 1299 __ vmovsr(S0, R0); |
1300 __ vcvtdi(D1, S0); | 1300 __ vcvtdi(D1, S0); |
1301 __ b(&double_op); | 1301 __ b(&double_op); |
1302 __ Bind(&fall_through); | 1302 __ Bind(&fall_through); |
1303 } | 1303 } |
1304 | 1304 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 // R3: heap->Top->Address(). | 1515 // R3: heap->Top->Address(). |
1516 __ LoadImmediate(R7, heap->EndAddress()); | 1516 __ LoadImmediate(R7, heap->EndAddress()); |
1517 __ ldr(R7, Address(R7, 0)); | 1517 __ ldr(R7, Address(R7, 0)); |
1518 __ cmp(R1, ShifterOperand(R7)); | 1518 __ cmp(R1, ShifterOperand(R7)); |
1519 __ b(&fail, CS); | 1519 __ b(&fail, CS); |
1520 | 1520 |
1521 // Successfully allocated the object(s), now update top to point to | 1521 // Successfully allocated the object(s), now update top to point to |
1522 // next object start and initialize the object. | 1522 // next object start and initialize the object. |
1523 __ str(R1, Address(R3, 0)); | 1523 __ str(R1, Address(R3, 0)); |
1524 __ AddImmediate(R0, kHeapObjectTag); | 1524 __ AddImmediate(R0, kHeapObjectTag); |
| 1525 __ BumpAllocationCount(Heap::kNew, kOneByteStringCid, R2, R3); |
1525 | 1526 |
1526 // Initialize the tags. | 1527 // Initialize the tags. |
1527 // R0: new object start as a tagged pointer. | 1528 // R0: new object start as a tagged pointer. |
1528 // R1: new object end address. | 1529 // R1: new object end address. |
1529 // R2: allocation size. | 1530 // R2: allocation size. |
1530 { | 1531 { |
1531 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 1532 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
1532 const Class& cls = | 1533 const Class& cls = |
1533 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1534 Class::Handle(isolate->object_store()->one_byte_string_class()); |
1534 | 1535 |
1535 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); | 1536 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
1536 __ mov(R2, ShifterOperand(R2, LSL, shift), LS); | 1537 __ mov(R2, ShifterOperand(R2, LSL, shift), LS); |
1537 __ mov(R2, ShifterOperand(0), HI); | 1538 __ mov(R2, ShifterOperand(0), HI); |
1538 | 1539 |
1539 // Get the class index and insert it into the tags. | 1540 // Get the class index and insert it into the tags. |
1540 // R2: size and bit tags. | 1541 // R2: size and bit tags. |
1541 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); | 1542 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); |
1542 __ orr(R2, R2, ShifterOperand(TMP)); | 1543 __ orr(R2, R2, ShifterOperand(TMP)); |
1543 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. | 1544 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. |
1544 } | 1545 } |
1545 | 1546 |
1546 // Set the length field using the saved length (R6). | 1547 // Set the length field using the saved length (R6). |
1547 __ StoreIntoObjectNoBarrier(R0, | 1548 __ StoreIntoObjectNoBarrier(R0, |
1548 FieldAddress(R0, String::length_offset()), | 1549 FieldAddress(R0, String::length_offset()), |
1549 R6); | 1550 R6); |
1550 // Clear hash. | 1551 // Clear hash. |
1551 __ LoadImmediate(TMP, 0); | 1552 __ LoadImmediate(TMP, 0); |
1552 __ str(TMP, FieldAddress(R0, String::hash_offset())); | 1553 __ str(TMP, FieldAddress(R0, String::hash_offset())); |
1553 __ b(ok); | 1554 __ b(ok); |
1554 | |
1555 __ Bind(&fail); | 1555 __ Bind(&fail); |
1556 __ b(failure); | 1556 __ b(failure); |
1557 } | 1557 } |
1558 | 1558 |
1559 | 1559 |
1560 // Arg0: OneByteString (receiver). | 1560 // Arg0: OneByteString (receiver). |
1561 // Arg1: Start index as Smi. | 1561 // Arg1: Start index as Smi. |
1562 // Arg2: End index as Smi. | 1562 // Arg2: End index as Smi. |
1563 // The indexes must be valid. | 1563 // The indexes must be valid. |
1564 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { | 1564 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1711 | 1711 |
1712 | 1712 |
1713 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 1713 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |
1714 StringEquality(assembler, kTwoByteStringCid); | 1714 StringEquality(assembler, kTwoByteStringCid); |
1715 } | 1715 } |
1716 | 1716 |
1717 | 1717 |
1718 } // namespace dart | 1718 } // namespace dart |
1719 | 1719 |
1720 #endif // defined TARGET_ARCH_ARM | 1720 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |