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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/simulator.h" | 9 #include "vm/simulator.h" |
10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
(...skipping 1278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1289 } | 1289 } |
1290 | 1290 |
1291 | 1291 |
1292 void Assembler::CompareObject(Register rn, const Object& object) { | 1292 void Assembler::CompareObject(Register rn, const Object& object) { |
1293 ASSERT(rn != IP); | 1293 ASSERT(rn != IP); |
1294 LoadObject(IP, object); | 1294 LoadObject(IP, object); |
1295 cmp(rn, ShifterOperand(IP)); | 1295 cmp(rn, ShifterOperand(IP)); |
1296 } | 1296 } |
1297 | 1297 |
1298 | 1298 |
| 1299 // Preserves object and value registers. |
| 1300 void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| 1301 Register value, |
| 1302 Label* no_update) { |
| 1303 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| 1304 (kOldObjectAlignmentOffset == 0), young_alignment); |
| 1305 |
| 1306 // Write-barrier triggers if the value is in the new space (has bit set) and |
| 1307 // the object is in the old space (has bit cleared). |
| 1308 // To check that, we compute value & ~object and skip the write barrier |
| 1309 // if the bit is not set. We can't destroy the object. |
| 1310 bic(IP, value, ShifterOperand(object)); |
| 1311 tst(IP, ShifterOperand(kNewObjectAlignmentOffset)); |
| 1312 b(no_update, EQ); |
| 1313 } |
| 1314 |
| 1315 |
| 1316 // Preserves object and value registers. |
| 1317 void Assembler::StoreIntoObjectFilter(Register object, |
| 1318 Register value, |
| 1319 Label* no_update) { |
| 1320 // For the value we are only interested in the new/old bit and the tag bit. |
| 1321 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. |
| 1322 and_(IP, value, ShifterOperand(value, LSL, kObjectAlignmentLog2 - 1)); |
| 1323 // And the result with the negated space bit of the object. |
| 1324 bic(IP, IP, ShifterOperand(object)); |
| 1325 tst(IP, ShifterOperand(kNewObjectAlignmentOffset)); |
| 1326 b(no_update, EQ); |
| 1327 } |
| 1328 |
| 1329 |
| 1330 void Assembler::StoreIntoObject(Register object, |
| 1331 const Address& dest, |
| 1332 Register value, |
| 1333 bool can_value_be_smi) { |
| 1334 ASSERT(object != value); |
| 1335 str(value, dest); |
| 1336 Label done; |
| 1337 if (can_value_be_smi) { |
| 1338 StoreIntoObjectFilter(object, value, &done); |
| 1339 } else { |
| 1340 StoreIntoObjectFilterNoSmi(object, value, &done); |
| 1341 } |
| 1342 // A store buffer update is required. |
| 1343 if (value != R0) Push(R0); // Preserve R0. |
| 1344 if (object != R0) { |
| 1345 mov(R0, ShifterOperand(object)); |
| 1346 } |
| 1347 BranchLink(&StubCode::UpdateStoreBufferLabel()); |
| 1348 if (value != R0) Pop(R0); // Restore R0. |
| 1349 Bind(&done); |
| 1350 } |
| 1351 |
| 1352 |
| 1353 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 1354 const Address& dest, |
| 1355 Register value) { |
| 1356 str(value, dest); |
| 1357 #if defined(DEBUG) |
| 1358 Label done; |
| 1359 StoreIntoObjectFilter(object, value, &done); |
| 1360 Stop("Store buffer update is required"); |
| 1361 Bind(&done); |
| 1362 #endif // defined(DEBUG) |
| 1363 // No store buffer update. |
| 1364 } |
| 1365 |
| 1366 |
| 1367 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 1368 const Address& dest, |
| 1369 const Object& value) { |
| 1370 ASSERT(value.IsSmi() || value.InVMHeap() || |
| 1371 (value.IsOld() && value.IsNotTemporaryScopedHandle())); |
| 1372 // No store buffer update. |
| 1373 LoadObject(IP, value); |
| 1374 str(IP, dest); |
| 1375 } |
| 1376 |
| 1377 |
1299 void Assembler::LoadClassId(Register result, Register object) { | 1378 void Assembler::LoadClassId(Register result, Register object) { |
1300 ASSERT(RawObject::kClassIdTagBit == 16); | 1379 ASSERT(RawObject::kClassIdTagBit == 16); |
1301 ASSERT(RawObject::kClassIdTagSize == 16); | 1380 ASSERT(RawObject::kClassIdTagSize == 16); |
1302 const intptr_t class_id_offset = Object::tags_offset() + | 1381 const intptr_t class_id_offset = Object::tags_offset() + |
1303 RawObject::kClassIdTagBit / kBitsPerByte; | 1382 RawObject::kClassIdTagBit / kBitsPerByte; |
1304 ldrh(result, FieldAddress(object, class_id_offset)); | 1383 ldrh(result, FieldAddress(object, class_id_offset)); |
1305 } | 1384 } |
1306 | 1385 |
1307 | 1386 |
1308 void Assembler::LoadClassById(Register result, Register class_id) { | 1387 void Assembler::LoadClassById(Register result, Register class_id) { |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2045 | 2124 |
2046 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2125 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
2047 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 2126 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
2048 return fpu_reg_names[reg]; | 2127 return fpu_reg_names[reg]; |
2049 } | 2128 } |
2050 | 2129 |
2051 } // namespace dart | 2130 } // namespace dart |
2052 | 2131 |
2053 #endif // defined TARGET_ARCH_ARM | 2132 #endif // defined TARGET_ARCH_ARM |
2054 | 2133 |
OLD | NEW |