| OLD | NEW |
| 1 |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // 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 | 3 // 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. | 4 // BSD-style license that can be found in the LICENSE file. |
| 4 | 5 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 7 #if defined(TARGET_ARCH_ARM) |
| 7 | 8 |
| 8 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 9 | 10 |
| 10 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
| (...skipping 1192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 return true; | 1204 return true; |
| 1204 } | 1205 } |
| 1205 | 1206 |
| 1206 return false; | 1207 return false; |
| 1207 } | 1208 } |
| 1208 | 1209 |
| 1209 | 1210 |
| 1210 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1211 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1211 bool opt) const { | 1212 bool opt) const { |
| 1212 const intptr_t kNumInputs = 2; | 1213 const intptr_t kNumInputs = 2; |
| 1213 const intptr_t kNumTemps = 0; | 1214 const intptr_t kNumTemps = aligned() ? 0 : 1; |
| 1214 LocationSummary* locs = new(zone) LocationSummary( | 1215 LocationSummary* locs = new(zone) LocationSummary( |
| 1215 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1216 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1216 locs->set_in(0, Location::RequiresRegister()); | 1217 locs->set_in(0, Location::RequiresRegister()); |
| 1217 bool needs_base = false; | 1218 bool needs_base = false; |
| 1218 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1219 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
| 1219 true, // Load. | 1220 true, // Load. |
| 1220 &needs_base)) { | 1221 &needs_base)) { |
| 1221 // CanBeImmediateIndex must return false for unsafe smis. | 1222 // CanBeImmediateIndex must return false for unsafe smis. |
| 1222 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1223 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1223 } else { | 1224 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1238 } else if (representation() == kUnboxedUint32) { | 1239 } else if (representation() == kUnboxedUint32) { |
| 1239 ASSERT(class_id() == kTypedDataUint32ArrayCid); | 1240 ASSERT(class_id() == kTypedDataUint32ArrayCid); |
| 1240 locs->set_out(0, Location::RequiresRegister()); | 1241 locs->set_out(0, Location::RequiresRegister()); |
| 1241 } else if (representation() == kUnboxedInt32) { | 1242 } else if (representation() == kUnboxedInt32) { |
| 1242 ASSERT(class_id() == kTypedDataInt32ArrayCid); | 1243 ASSERT(class_id() == kTypedDataInt32ArrayCid); |
| 1243 locs->set_out(0, Location::RequiresRegister()); | 1244 locs->set_out(0, Location::RequiresRegister()); |
| 1244 } else { | 1245 } else { |
| 1245 ASSERT(representation() == kTagged); | 1246 ASSERT(representation() == kTagged); |
| 1246 locs->set_out(0, Location::RequiresRegister()); | 1247 locs->set_out(0, Location::RequiresRegister()); |
| 1247 } | 1248 } |
| 1249 if (!aligned()) { |
| 1250 locs->set_temp(0, Location::RequiresRegister()); |
| 1251 } |
| 1248 return locs; | 1252 return locs; |
| 1249 } | 1253 } |
| 1250 | 1254 |
| 1251 | 1255 |
| 1252 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1256 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1253 // The array register points to the backing store for external arrays. | 1257 // The array register points to the backing store for external arrays. |
| 1254 const Register array = locs()->in(0).reg(); | 1258 const Register array = locs()->in(0).reg(); |
| 1255 const Location index = locs()->in(1); | 1259 const Location index = locs()->in(1); |
| 1260 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1256 | 1261 |
| 1257 Address element_address = index.IsRegister() | 1262 Address element_address(kNoRegister); |
| 1263 if (aligned()) { |
| 1264 element_address = index.IsRegister() |
| 1258 ? __ ElementAddressForRegIndex(true, // Load. | 1265 ? __ ElementAddressForRegIndex(true, // Load. |
| 1259 IsExternal(), class_id(), index_scale(), | 1266 IsExternal(), class_id(), index_scale(), |
| 1260 array, | 1267 array, |
| 1261 index.reg()) | 1268 index.reg()) |
| 1262 : __ ElementAddressForIntIndex(true, // Load. | 1269 : __ ElementAddressForIntIndex(true, // Load. |
| 1263 IsExternal(), class_id(), index_scale(), | 1270 IsExternal(), class_id(), index_scale(), |
| 1264 array, Smi::Cast(index.constant()).Value(), | 1271 array, Smi::Cast(index.constant()).Value(), |
| 1265 IP); // Temp register. | 1272 IP); // Temp register. |
| 1266 // Warning: element_address may use register IP as base. | 1273 // Warning: element_address may use register IP as base. |
| 1274 } else { |
| 1275 if (index.IsRegister()) { |
| 1276 __ LoadElementAddressForRegIndex(address, |
| 1277 true, // Load. |
| 1278 IsExternal(), class_id(), index_scale(), |
| 1279 array, |
| 1280 index.reg()); |
| 1281 } else { |
| 1282 __ LoadElementAddressForIntIndex(address, |
| 1283 true, // Load. |
| 1284 IsExternal(), class_id(), index_scale(), |
| 1285 array, |
| 1286 Smi::Cast(index.constant()).Value()); |
| 1287 } |
| 1288 } |
| 1267 | 1289 |
| 1268 if ((representation() == kUnboxedDouble) || | 1290 if ((representation() == kUnboxedDouble) || |
| 1269 (representation() == kUnboxedFloat32x4) || | 1291 (representation() == kUnboxedFloat32x4) || |
| 1270 (representation() == kUnboxedInt32x4) || | 1292 (representation() == kUnboxedInt32x4) || |
| 1271 (representation() == kUnboxedFloat64x2)) { | 1293 (representation() == kUnboxedFloat64x2)) { |
| 1272 const QRegister result = locs()->out(0).fpu_reg(); | 1294 const QRegister result = locs()->out(0).fpu_reg(); |
| 1273 const DRegister dresult0 = EvenDRegisterOf(result); | 1295 const DRegister dresult0 = EvenDRegisterOf(result); |
| 1274 switch (class_id()) { | 1296 switch (class_id()) { |
| 1275 case kTypedDataFloat32ArrayCid: | 1297 case kTypedDataFloat32ArrayCid: |
| 1276 // Load single precision float. | 1298 // Load single precision float. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1292 } | 1314 } |
| 1293 return; | 1315 return; |
| 1294 } | 1316 } |
| 1295 | 1317 |
| 1296 if ((representation() == kUnboxedUint32) || | 1318 if ((representation() == kUnboxedUint32) || |
| 1297 (representation() == kUnboxedInt32)) { | 1319 (representation() == kUnboxedInt32)) { |
| 1298 Register result = locs()->out(0).reg(); | 1320 Register result = locs()->out(0).reg(); |
| 1299 switch (class_id()) { | 1321 switch (class_id()) { |
| 1300 case kTypedDataInt32ArrayCid: | 1322 case kTypedDataInt32ArrayCid: |
| 1301 ASSERT(representation() == kUnboxedInt32); | 1323 ASSERT(representation() == kUnboxedInt32); |
| 1302 __ ldr(result, element_address); | 1324 if (aligned()) { |
| 1325 __ ldr(result, element_address); |
| 1326 } else { |
| 1327 __ LoadWordUnaligned(result, address, TMP); |
| 1328 } |
| 1303 break; | 1329 break; |
| 1304 case kTypedDataUint32ArrayCid: | 1330 case kTypedDataUint32ArrayCid: |
| 1305 ASSERT(representation() == kUnboxedUint32); | 1331 ASSERT(representation() == kUnboxedUint32); |
| 1306 __ ldr(result, element_address); | 1332 if (aligned()) { |
| 1333 __ ldr(result, element_address); |
| 1334 } else { |
| 1335 __ LoadWordUnaligned(result, address, TMP); |
| 1336 } |
| 1307 break; | 1337 break; |
| 1308 default: | 1338 default: |
| 1309 UNREACHABLE(); | 1339 UNREACHABLE(); |
| 1310 } | 1340 } |
| 1311 return; | 1341 return; |
| 1312 } | 1342 } |
| 1313 | 1343 |
| 1314 ASSERT(representation() == kTagged); | 1344 ASSERT(representation() == kTagged); |
| 1315 | 1345 |
| 1316 const Register result = locs()->out(0).reg(); | 1346 const Register result = locs()->out(0).reg(); |
| 1317 switch (class_id()) { | 1347 switch (class_id()) { |
| 1318 case kTypedDataInt8ArrayCid: | 1348 case kTypedDataInt8ArrayCid: |
| 1319 ASSERT(index_scale() == 1); | 1349 ASSERT(index_scale() == 1); |
| 1350 ASSERT(aligned()); |
| 1320 __ ldrsb(result, element_address); | 1351 __ ldrsb(result, element_address); |
| 1321 __ SmiTag(result); | 1352 __ SmiTag(result); |
| 1322 break; | 1353 break; |
| 1323 case kTypedDataUint8ArrayCid: | 1354 case kTypedDataUint8ArrayCid: |
| 1324 case kTypedDataUint8ClampedArrayCid: | 1355 case kTypedDataUint8ClampedArrayCid: |
| 1325 case kExternalTypedDataUint8ArrayCid: | 1356 case kExternalTypedDataUint8ArrayCid: |
| 1326 case kExternalTypedDataUint8ClampedArrayCid: | 1357 case kExternalTypedDataUint8ClampedArrayCid: |
| 1327 case kOneByteStringCid: | 1358 case kOneByteStringCid: |
| 1328 case kExternalOneByteStringCid: | 1359 case kExternalOneByteStringCid: |
| 1329 ASSERT(index_scale() == 1); | 1360 ASSERT(index_scale() == 1); |
| 1361 ASSERT(aligned()); |
| 1330 __ ldrb(result, element_address); | 1362 __ ldrb(result, element_address); |
| 1331 __ SmiTag(result); | 1363 __ SmiTag(result); |
| 1332 break; | 1364 break; |
| 1333 case kTypedDataInt16ArrayCid: | 1365 case kTypedDataInt16ArrayCid: |
| 1334 __ ldrsh(result, element_address); | 1366 if (aligned()) { |
| 1367 __ ldrsh(result, element_address); |
| 1368 } else { |
| 1369 __ LoadHalfWordUnaligned(result, address, TMP); |
| 1370 } |
| 1335 __ SmiTag(result); | 1371 __ SmiTag(result); |
| 1336 break; | 1372 break; |
| 1337 case kTypedDataUint16ArrayCid: | 1373 case kTypedDataUint16ArrayCid: |
| 1338 case kTwoByteStringCid: | 1374 case kTwoByteStringCid: |
| 1339 case kExternalTwoByteStringCid: | 1375 case kExternalTwoByteStringCid: |
| 1340 __ ldrh(result, element_address); | 1376 if (aligned()) { |
| 1377 __ ldrh(result, element_address); |
| 1378 } else { |
| 1379 __ LoadHalfWordUnsignedUnaligned(result, address, TMP); |
| 1380 } |
| 1341 __ SmiTag(result); | 1381 __ SmiTag(result); |
| 1342 break; | 1382 break; |
| 1343 default: | 1383 default: |
| 1344 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1384 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1345 __ ldr(result, element_address); | 1385 __ ldr(result, element_address); |
| 1346 break; | 1386 break; |
| 1347 } | 1387 } |
| 1348 } | 1388 } |
| 1349 | 1389 |
| 1350 | 1390 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 | 1427 |
| 1388 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1428 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1389 bool opt) const { | 1429 bool opt) const { |
| 1390 const intptr_t kNumInputs = 3; | 1430 const intptr_t kNumInputs = 3; |
| 1391 LocationSummary* locs; | 1431 LocationSummary* locs; |
| 1392 | 1432 |
| 1393 bool needs_base = false; | 1433 bool needs_base = false; |
| 1394 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1434 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
| 1395 false, // Store. | 1435 false, // Store. |
| 1396 &needs_base)) { | 1436 &needs_base)) { |
| 1397 const intptr_t kNumTemps = needs_base ? 1 : 0; | 1437 const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; |
| 1398 locs = new(zone) LocationSummary( | 1438 locs = new(zone) LocationSummary( |
| 1399 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1439 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1400 | 1440 |
| 1401 // CanBeImmediateIndex must return false for unsafe smis. | 1441 // CanBeImmediateIndex must return false for unsafe smis. |
| 1402 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1442 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1403 if (needs_base) { | 1443 if (needs_base) { |
| 1404 locs->set_temp(0, Location::RequiresRegister()); | 1444 locs->set_temp(0, Location::RequiresRegister()); |
| 1405 } | 1445 } |
| 1446 if (!aligned()) { |
| 1447 locs->set_temp(0, Location::RequiresRegister()); |
| 1448 locs->set_temp(1, Location::RequiresRegister()); |
| 1449 } |
| 1406 } else { | 1450 } else { |
| 1407 const intptr_t kNumTemps = 0; | 1451 const intptr_t kNumTemps = aligned() ? 0 : 2; |
| 1408 locs = new(zone) LocationSummary( | 1452 locs = new(zone) LocationSummary( |
| 1409 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1453 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1410 | 1454 |
| 1411 locs->set_in(1, Location::WritableRegister()); | 1455 locs->set_in(1, Location::WritableRegister()); |
| 1456 if (!aligned()) { |
| 1457 locs->set_temp(0, Location::RequiresRegister()); |
| 1458 locs->set_temp(1, Location::RequiresRegister()); |
| 1459 } |
| 1412 } | 1460 } |
| 1413 locs->set_in(0, Location::RequiresRegister()); | 1461 locs->set_in(0, Location::RequiresRegister()); |
| 1414 | 1462 |
| 1415 switch (class_id()) { | 1463 switch (class_id()) { |
| 1416 case kArrayCid: | 1464 case kArrayCid: |
| 1417 locs->set_in(2, ShouldEmitStoreBarrier() | 1465 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1418 ? Location::WritableRegister() | 1466 ? Location::WritableRegister() |
| 1419 : Location::RegisterOrConstant(value())); | 1467 : Location::RegisterOrConstant(value())); |
| 1420 break; | 1468 break; |
| 1421 case kExternalTypedDataUint8ArrayCid: | 1469 case kExternalTypedDataUint8ArrayCid: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1447 return locs; | 1495 return locs; |
| 1448 } | 1496 } |
| 1449 | 1497 |
| 1450 | 1498 |
| 1451 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1499 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1452 // The array register points to the backing store for external arrays. | 1500 // The array register points to the backing store for external arrays. |
| 1453 const Register array = locs()->in(0).reg(); | 1501 const Register array = locs()->in(0).reg(); |
| 1454 const Location index = locs()->in(1); | 1502 const Location index = locs()->in(1); |
| 1455 const Register temp = | 1503 const Register temp = |
| 1456 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; | 1504 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; |
| 1505 const Register temp2 = |
| 1506 (locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; |
| 1457 | 1507 |
| 1458 Address element_address = index.IsRegister() | 1508 Address element_address(kNoRegister); |
| 1509 if (aligned()) { |
| 1510 element_address = index.IsRegister() |
| 1459 ? __ ElementAddressForRegIndex(false, // Store. | 1511 ? __ ElementAddressForRegIndex(false, // Store. |
| 1460 IsExternal(), class_id(), index_scale(), | 1512 IsExternal(), class_id(), index_scale(), |
| 1461 array, | 1513 array, |
| 1462 index.reg()) | 1514 index.reg()) |
| 1463 : __ ElementAddressForIntIndex(false, // Store. | 1515 : __ ElementAddressForIntIndex(false, // Store. |
| 1464 IsExternal(), class_id(), index_scale(), | 1516 IsExternal(), class_id(), index_scale(), |
| 1465 array, Smi::Cast(index.constant()).Value(), | 1517 array, Smi::Cast(index.constant()).Value(), |
| 1466 temp); | 1518 temp); |
| 1519 } else { |
| 1520 if (index.IsRegister()) { |
| 1521 __ LoadElementAddressForRegIndex(temp, |
| 1522 false, // Store. |
| 1523 IsExternal(), class_id(), index_scale(), |
| 1524 array, |
| 1525 index.reg()); |
| 1526 } else { |
| 1527 __ LoadElementAddressForIntIndex(temp, |
| 1528 false, // Store. |
| 1529 IsExternal(), class_id(), index_scale(), |
| 1530 array, |
| 1531 Smi::Cast(index.constant()).Value()); |
| 1532 } |
| 1533 } |
| 1467 | 1534 |
| 1468 switch (class_id()) { | 1535 switch (class_id()) { |
| 1469 case kArrayCid: | 1536 case kArrayCid: |
| 1470 if (ShouldEmitStoreBarrier()) { | 1537 if (ShouldEmitStoreBarrier()) { |
| 1471 const Register value = locs()->in(2).reg(); | 1538 const Register value = locs()->in(2).reg(); |
| 1472 __ StoreIntoObject(array, element_address, value); | 1539 __ StoreIntoObject(array, element_address, value); |
| 1473 } else if (locs()->in(2).IsConstant()) { | 1540 } else if (locs()->in(2).IsConstant()) { |
| 1474 const Object& constant = locs()->in(2).constant(); | 1541 const Object& constant = locs()->in(2).constant(); |
| 1475 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1542 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1476 } else { | 1543 } else { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. | 1582 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. |
| 1516 __ SmiUntag(IP); | 1583 __ SmiUntag(IP); |
| 1517 __ strb(IP, element_address); | 1584 __ strb(IP, element_address); |
| 1518 } | 1585 } |
| 1519 break; | 1586 break; |
| 1520 } | 1587 } |
| 1521 case kTypedDataInt16ArrayCid: | 1588 case kTypedDataInt16ArrayCid: |
| 1522 case kTypedDataUint16ArrayCid: { | 1589 case kTypedDataUint16ArrayCid: { |
| 1523 const Register value = locs()->in(2).reg(); | 1590 const Register value = locs()->in(2).reg(); |
| 1524 __ SmiUntag(IP, value); | 1591 __ SmiUntag(IP, value); |
| 1525 __ strh(IP, element_address); | 1592 if (aligned()) { |
| 1593 __ strh(IP, element_address); |
| 1594 } else { |
| 1595 __ StoreHalfWordUnaligned(IP, temp, temp2); |
| 1596 } |
| 1526 break; | 1597 break; |
| 1527 } | 1598 } |
| 1528 case kTypedDataInt32ArrayCid: | 1599 case kTypedDataInt32ArrayCid: |
| 1529 case kTypedDataUint32ArrayCid: { | 1600 case kTypedDataUint32ArrayCid: { |
| 1530 const Register value = locs()->in(2).reg(); | 1601 const Register value = locs()->in(2).reg(); |
| 1531 __ str(value, element_address); | 1602 if (aligned()) { |
| 1603 __ str(value, element_address); |
| 1604 } else { |
| 1605 __ StoreWordUnaligned(value, temp, temp2); |
| 1606 } |
| 1532 break; | 1607 break; |
| 1533 } | 1608 } |
| 1534 case kTypedDataFloat32ArrayCid: { | 1609 case kTypedDataFloat32ArrayCid: { |
| 1535 const SRegister value_reg = | 1610 const SRegister value_reg = |
| 1536 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); | 1611 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); |
| 1537 __ vstrs(value_reg, element_address); | 1612 __ vstrs(value_reg, element_address); |
| 1538 break; | 1613 break; |
| 1539 } | 1614 } |
| 1540 case kTypedDataFloat64ArrayCid: { | 1615 case kTypedDataFloat64ArrayCid: { |
| 1541 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); | 1616 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
| (...skipping 5546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7088 1, | 7163 1, |
| 7089 locs()); | 7164 locs()); |
| 7090 __ Drop(1); | 7165 __ Drop(1); |
| 7091 __ Pop(result); | 7166 __ Pop(result); |
| 7092 } | 7167 } |
| 7093 | 7168 |
| 7094 | 7169 |
| 7095 } // namespace dart | 7170 } // namespace dart |
| 7096 | 7171 |
| 7097 #endif // defined TARGET_ARCH_ARM | 7172 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |