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

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

Issue 2452453002: Support unaligned integer loads on ARM and MIPS. (Closed)
Patch Set: review 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
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698