Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 2452453002: Support unaligned integer loads on ARM and MIPS. (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 return true; 1201 return true;
1202 } 1202 }
1203 1203
1204 return false; 1204 return false;
1205 } 1205 }
1206 1206
1207 1207
1208 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, 1208 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
1209 bool opt) const { 1209 bool opt) const {
1210 const intptr_t kNumInputs = 2; 1210 const intptr_t kNumInputs = 2;
1211 const intptr_t kNumTemps = 0; 1211 const intptr_t kNumTemps = aligned() ? 0 : 1;
1212 LocationSummary* locs = new(zone) LocationSummary( 1212 LocationSummary* locs = new(zone) LocationSummary(
1213 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1213 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1214 locs->set_in(0, Location::RequiresRegister()); 1214 locs->set_in(0, Location::RequiresRegister());
1215 bool needs_base = false; 1215 bool needs_base = false;
1216 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), 1216 if (CanBeImmediateIndex(index(), class_id(), IsExternal(),
1217 true, // Load. 1217 true, // Load.
1218 &needs_base)) { 1218 &needs_base)) {
1219 // CanBeImmediateIndex must return false for unsafe smis. 1219 // CanBeImmediateIndex must return false for unsafe smis.
1220 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 1220 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
1221 } else { 1221 } else {
(...skipping 14 matching lines...) Expand all
1236 } else if (representation() == kUnboxedUint32) { 1236 } else if (representation() == kUnboxedUint32) {
1237 ASSERT(class_id() == kTypedDataUint32ArrayCid); 1237 ASSERT(class_id() == kTypedDataUint32ArrayCid);
1238 locs->set_out(0, Location::RequiresRegister()); 1238 locs->set_out(0, Location::RequiresRegister());
1239 } else if (representation() == kUnboxedInt32) { 1239 } else if (representation() == kUnboxedInt32) {
1240 ASSERT(class_id() == kTypedDataInt32ArrayCid); 1240 ASSERT(class_id() == kTypedDataInt32ArrayCid);
1241 locs->set_out(0, Location::RequiresRegister()); 1241 locs->set_out(0, Location::RequiresRegister());
1242 } else { 1242 } else {
1243 ASSERT(representation() == kTagged); 1243 ASSERT(representation() == kTagged);
1244 locs->set_out(0, Location::RequiresRegister()); 1244 locs->set_out(0, Location::RequiresRegister());
1245 } 1245 }
1246 if (!aligned()) {
1247 locs->set_temp(0, Location::RequiresRegister());
1248 }
1246 return locs; 1249 return locs;
1247 } 1250 }
1248 1251
1249 1252
1250 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1253 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1251 // The array register points to the backing store for external arrays. 1254 // The array register points to the backing store for external arrays.
1252 const Register array = locs()->in(0).reg(); 1255 const Register array = locs()->in(0).reg();
1253 const Location index = locs()->in(1); 1256 const Location index = locs()->in(1);
1257 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg();
1254 1258
1255 Address element_address = index.IsRegister() 1259 Address element_address(IP);
zra 2016/10/26 06:59:41 Can IP be kNoRegister instead, or maybe pass a bog
rmacnak 2016/10/31 22:57:26 Using kNoRegister.
1260 if (aligned()) {
1261 element_address = index.IsRegister()
1256 ? __ ElementAddressForRegIndex(true, // Load. 1262 ? __ ElementAddressForRegIndex(true, // Load.
1257 IsExternal(), class_id(), index_scale(), 1263 IsExternal(), class_id(), index_scale(),
1258 array, 1264 array,
1259 index.reg()) 1265 index.reg())
1260 : __ ElementAddressForIntIndex(true, // Load. 1266 : __ ElementAddressForIntIndex(true, // Load.
1261 IsExternal(), class_id(), index_scale(), 1267 IsExternal(), class_id(), index_scale(),
1262 array, Smi::Cast(index.constant()).Value(), 1268 array, Smi::Cast(index.constant()).Value(),
1263 IP); // Temp register. 1269 IP); // Temp register.
1264 // Warning: element_address may use register IP as base. 1270 // Warning: element_address may use register IP as base.
1271 } else {
1272 if (index.IsRegister()) {
1273 __ LoadElementAddressForRegIndex(address,
1274 true, // Load.
1275 IsExternal(), class_id(), index_scale(),
1276 array,
1277 index.reg());
1278 } else {
1279 __ LoadElementAddressForIntIndex(address,
1280 true, // Load.
1281 IsExternal(), class_id(), index_scale(),
1282 array,
1283 Smi::Cast(index.constant()).Value());
1284 }
1285 }
1265 1286
1266 if ((representation() == kUnboxedDouble) || 1287 if ((representation() == kUnboxedDouble) ||
1267 (representation() == kUnboxedFloat32x4) || 1288 (representation() == kUnboxedFloat32x4) ||
1268 (representation() == kUnboxedInt32x4) || 1289 (representation() == kUnboxedInt32x4) ||
1269 (representation() == kUnboxedFloat64x2)) { 1290 (representation() == kUnboxedFloat64x2)) {
1270 const QRegister result = locs()->out(0).fpu_reg(); 1291 const QRegister result = locs()->out(0).fpu_reg();
1271 const DRegister dresult0 = EvenDRegisterOf(result); 1292 const DRegister dresult0 = EvenDRegisterOf(result);
1272 switch (class_id()) { 1293 switch (class_id()) {
1273 case kTypedDataFloat32ArrayCid: 1294 case kTypedDataFloat32ArrayCid:
1274 // Load single precision float. 1295 // Load single precision float.
(...skipping 15 matching lines...) Expand all
1290 } 1311 }
1291 return; 1312 return;
1292 } 1313 }
1293 1314
1294 if ((representation() == kUnboxedUint32) || 1315 if ((representation() == kUnboxedUint32) ||
1295 (representation() == kUnboxedInt32)) { 1316 (representation() == kUnboxedInt32)) {
1296 Register result = locs()->out(0).reg(); 1317 Register result = locs()->out(0).reg();
1297 switch (class_id()) { 1318 switch (class_id()) {
1298 case kTypedDataInt32ArrayCid: 1319 case kTypedDataInt32ArrayCid:
1299 ASSERT(representation() == kUnboxedInt32); 1320 ASSERT(representation() == kUnboxedInt32);
1300 __ ldr(result, element_address); 1321 if (aligned()) {
1322 __ ldr(result, element_address);
zra 2016/10/26 06:59:41 Likewise, maybe assert here that address == kNoReg
1323 } else {
1324 __ LoadWordUnaligned(result, address, TMP);
1325 }
1301 break; 1326 break;
1302 case kTypedDataUint32ArrayCid: 1327 case kTypedDataUint32ArrayCid:
1303 ASSERT(representation() == kUnboxedUint32); 1328 ASSERT(representation() == kUnboxedUint32);
1304 __ ldr(result, element_address); 1329 if (aligned()) {
1330 __ ldr(result, element_address);
1331 } else {
1332 __ LoadWordUnaligned(result, address, TMP);
1333 }
1305 break; 1334 break;
1306 default: 1335 default:
1307 UNREACHABLE(); 1336 UNREACHABLE();
1308 } 1337 }
1309 return; 1338 return;
1310 } 1339 }
1311 1340
1312 ASSERT(representation() == kTagged); 1341 ASSERT(representation() == kTagged);
1313 1342
1314 const Register result = locs()->out(0).reg(); 1343 const Register result = locs()->out(0).reg();
1315 switch (class_id()) { 1344 switch (class_id()) {
1316 case kTypedDataInt8ArrayCid: 1345 case kTypedDataInt8ArrayCid:
1317 ASSERT(index_scale() == 1); 1346 ASSERT(index_scale() == 1);
1347 ASSERT(aligned());
1318 __ ldrsb(result, element_address); 1348 __ ldrsb(result, element_address);
1319 __ SmiTag(result); 1349 __ SmiTag(result);
1320 break; 1350 break;
1321 case kTypedDataUint8ArrayCid: 1351 case kTypedDataUint8ArrayCid:
1322 case kTypedDataUint8ClampedArrayCid: 1352 case kTypedDataUint8ClampedArrayCid:
1323 case kExternalTypedDataUint8ArrayCid: 1353 case kExternalTypedDataUint8ArrayCid:
1324 case kExternalTypedDataUint8ClampedArrayCid: 1354 case kExternalTypedDataUint8ClampedArrayCid:
1325 case kOneByteStringCid: 1355 case kOneByteStringCid:
1326 case kExternalOneByteStringCid: 1356 case kExternalOneByteStringCid:
1327 ASSERT(index_scale() == 1); 1357 ASSERT(index_scale() == 1);
1358 ASSERT(aligned());
1328 __ ldrb(result, element_address); 1359 __ ldrb(result, element_address);
1329 __ SmiTag(result); 1360 __ SmiTag(result);
1330 break; 1361 break;
1331 case kTypedDataInt16ArrayCid: 1362 case kTypedDataInt16ArrayCid:
1332 __ ldrsh(result, element_address); 1363 if (aligned()) {
1364 __ ldrsh(result, element_address);
1365 } else {
1366 __ LoadHalfWordUnaligned(result, address, TMP);
1367 }
1333 __ SmiTag(result); 1368 __ SmiTag(result);
1334 break; 1369 break;
1335 case kTypedDataUint16ArrayCid: 1370 case kTypedDataUint16ArrayCid:
1336 case kTwoByteStringCid: 1371 case kTwoByteStringCid:
1337 case kExternalTwoByteStringCid: 1372 case kExternalTwoByteStringCid:
1338 __ ldrh(result, element_address); 1373 if (aligned()) {
1374 __ ldrh(result, element_address);
1375 } else {
1376 __ LoadHalfWordUnsignedUnaligned(result, address, TMP);
1377 }
1339 __ SmiTag(result); 1378 __ SmiTag(result);
1340 break; 1379 break;
1341 default: 1380 default:
1342 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); 1381 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1343 __ ldr(result, element_address); 1382 __ ldr(result, element_address);
1344 break; 1383 break;
1345 } 1384 }
1346 } 1385 }
1347 1386
1348 1387
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 1424
1386 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, 1425 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
1387 bool opt) const { 1426 bool opt) const {
1388 const intptr_t kNumInputs = 3; 1427 const intptr_t kNumInputs = 3;
1389 LocationSummary* locs; 1428 LocationSummary* locs;
1390 1429
1391 bool needs_base = false; 1430 bool needs_base = false;
1392 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), 1431 if (CanBeImmediateIndex(index(), class_id(), IsExternal(),
1393 false, // Store. 1432 false, // Store.
1394 &needs_base)) { 1433 &needs_base)) {
1395 const intptr_t kNumTemps = needs_base ? 1 : 0; 1434 intptr_t kNumTemps = needs_base ? 1 : 0;
zra 2016/10/26 06:59:41 Maybe: const intptr_t kNumTemps = aligned() ? (ne
Cutch 2016/10/26 09:00:29 +1
rmacnak 2016/10/31 22:57:26 Done.
1435 if (!aligned()) {
1436 kNumTemps = 2;
1437 }
1396 locs = new(zone) LocationSummary( 1438 locs = new(zone) LocationSummary(
1397 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1439 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1398 1440
1399 // CanBeImmediateIndex must return false for unsafe smis. 1441 // CanBeImmediateIndex must return false for unsafe smis.
1400 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); 1442 locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
1401 if (needs_base) { 1443 if (needs_base) {
1402 locs->set_temp(0, Location::RequiresRegister()); 1444 locs->set_temp(0, Location::RequiresRegister());
1403 } 1445 }
1446 if (!aligned()) {
1447 locs->set_temp(0, Location::RequiresRegister());
1448 locs->set_temp(1, Location::RequiresRegister());
1449 }
1404 } else { 1450 } else {
1405 const intptr_t kNumTemps = 0; 1451 const intptr_t kNumTemps = aligned() ? 0 : 2;
1406 locs = new(zone) LocationSummary( 1452 locs = new(zone) LocationSummary(
1407 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 1453 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
1408 1454
1409 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 }
1410 } 1460 }
1411 locs->set_in(0, Location::RequiresRegister()); 1461 locs->set_in(0, Location::RequiresRegister());
1412 1462
1413 switch (class_id()) { 1463 switch (class_id()) {
1414 case kArrayCid: 1464 case kArrayCid:
1415 locs->set_in(2, ShouldEmitStoreBarrier() 1465 locs->set_in(2, ShouldEmitStoreBarrier()
1416 ? Location::WritableRegister() 1466 ? Location::WritableRegister()
1417 : Location::RegisterOrConstant(value())); 1467 : Location::RegisterOrConstant(value()));
1418 break; 1468 break;
1419 case kExternalTypedDataUint8ArrayCid: 1469 case kExternalTypedDataUint8ArrayCid:
(...skipping 25 matching lines...) Expand all
1445 return locs; 1495 return locs;
1446 } 1496 }
1447 1497
1448 1498
1449 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1499 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1450 // The array register points to the backing store for external arrays. 1500 // The array register points to the backing store for external arrays.
1451 const Register array = locs()->in(0).reg(); 1501 const Register array = locs()->in(0).reg();
1452 const Location index = locs()->in(1); 1502 const Location index = locs()->in(1);
1453 const Register temp = 1503 const Register temp =
1454 (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;
1455 1507
1456 Address element_address = index.IsRegister() 1508 Address element_address(IP);
zra 2016/10/26 06:59:41 Same comments here about asserts as above.
1509 if (aligned()) {
1510 element_address = index.IsRegister()
1457 ? __ ElementAddressForRegIndex(false, // Store. 1511 ? __ ElementAddressForRegIndex(false, // Store.
1458 IsExternal(), class_id(), index_scale(), 1512 IsExternal(), class_id(), index_scale(),
1459 array, 1513 array,
1460 index.reg()) 1514 index.reg())
1461 : __ ElementAddressForIntIndex(false, // Store. 1515 : __ ElementAddressForIntIndex(false, // Store.
1462 IsExternal(), class_id(), index_scale(), 1516 IsExternal(), class_id(), index_scale(),
1463 array, Smi::Cast(index.constant()).Value(), 1517 array, Smi::Cast(index.constant()).Value(),
1464 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 }
1465 1534
1466 switch (class_id()) { 1535 switch (class_id()) {
1467 case kArrayCid: 1536 case kArrayCid:
1468 if (ShouldEmitStoreBarrier()) { 1537 if (ShouldEmitStoreBarrier()) {
1469 const Register value = locs()->in(2).reg(); 1538 const Register value = locs()->in(2).reg();
1470 __ StoreIntoObject(array, element_address, value); 1539 __ StoreIntoObject(array, element_address, value);
1471 } else if (locs()->in(2).IsConstant()) { 1540 } else if (locs()->in(2).IsConstant()) {
1472 const Object& constant = locs()->in(2).constant(); 1541 const Object& constant = locs()->in(2).constant();
1473 __ StoreIntoObjectNoBarrier(array, element_address, constant); 1542 __ StoreIntoObjectNoBarrier(array, element_address, constant);
1474 } else { 1543 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. 1582 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP.
1514 __ SmiUntag(IP); 1583 __ SmiUntag(IP);
1515 __ strb(IP, element_address); 1584 __ strb(IP, element_address);
1516 } 1585 }
1517 break; 1586 break;
1518 } 1587 }
1519 case kTypedDataInt16ArrayCid: 1588 case kTypedDataInt16ArrayCid:
1520 case kTypedDataUint16ArrayCid: { 1589 case kTypedDataUint16ArrayCid: {
1521 const Register value = locs()->in(2).reg(); 1590 const Register value = locs()->in(2).reg();
1522 __ SmiUntag(IP, value); 1591 __ SmiUntag(IP, value);
1523 __ strh(IP, element_address); 1592 if (aligned()) {
1593 __ strh(IP, element_address);
1594 } else {
1595 __ StoreHalfWordUnaligned(IP, temp, temp2);
1596 }
1524 break; 1597 break;
1525 } 1598 }
1526 case kTypedDataInt32ArrayCid: 1599 case kTypedDataInt32ArrayCid:
1527 case kTypedDataUint32ArrayCid: { 1600 case kTypedDataUint32ArrayCid: {
1528 const Register value = locs()->in(2).reg(); 1601 const Register value = locs()->in(2).reg();
1529 __ str(value, element_address); 1602 if (aligned()) {
1603 __ str(value, element_address);
1604 } else {
1605 __ StoreWordUnaligned(value, temp, temp2);
1606 }
1530 break; 1607 break;
1531 } 1608 }
1532 case kTypedDataFloat32ArrayCid: { 1609 case kTypedDataFloat32ArrayCid: {
1533 const SRegister value_reg = 1610 const SRegister value_reg =
1534 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); 1611 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
1535 __ vstrs(value_reg, element_address); 1612 __ vstrs(value_reg, element_address);
1536 break; 1613 break;
1537 } 1614 }
1538 case kTypedDataFloat64ArrayCid: { 1615 case kTypedDataFloat64ArrayCid: {
1539 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); 1616 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg());
(...skipping 5520 matching lines...) Expand 10 before | Expand all | Expand 10 after
7060 1, 7137 1,
7061 locs()); 7138 locs());
7062 __ Drop(1); 7139 __ Drop(1);
7063 __ Pop(result); 7140 __ Pop(result);
7064 } 7141 }
7065 7142
7066 7143
7067 } // namespace dart 7144 } // namespace dart
7068 7145
7069 #endif // defined TARGET_ARCH_ARM 7146 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698