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