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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 return kUnboxedFloat32x4; | 1131 return kUnboxedFloat32x4; |
1132 case kTypedDataFloat64x2ArrayCid: | 1132 case kTypedDataFloat64x2ArrayCid: |
1133 return kUnboxedFloat64x2; | 1133 return kUnboxedFloat64x2; |
1134 default: | 1134 default: |
1135 UNREACHABLE(); | 1135 UNREACHABLE(); |
1136 return kTagged; | 1136 return kTagged; |
1137 } | 1137 } |
1138 } | 1138 } |
1139 | 1139 |
1140 | 1140 |
1141 static bool CanBeImmediateIndex(Value* value, | |
1142 intptr_t cid, | |
1143 bool is_external, | |
1144 bool is_load) { | |
1145 ConstantInstr* constant = value->definition()->AsConstant(); | |
1146 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | |
1147 return false; | |
1148 } | |
1149 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | |
1150 const intptr_t scale = Instance::ElementSizeFor(cid); | |
1151 const int64_t offset = index * scale + | |
1152 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | |
1153 if (!Utils::IsAbsoluteUint(12, offset)) { | |
1154 return false; | |
1155 } | |
1156 int32_t offset_mask = 0; | |
1157 if (is_load) { | |
1158 return Address::CanHoldLoadOffset(Address::OperandSizeFor(cid), | |
1159 offset, | |
1160 &offset_mask); | |
1161 } else { | |
1162 return Address::CanHoldStoreOffset(Address::OperandSizeFor(cid), | |
1163 offset, | |
1164 &offset_mask); | |
1165 } | |
1166 } | |
1167 | |
1168 | |
1141 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1169 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, |
1142 bool opt) const { | 1170 bool opt) const { |
1143 const intptr_t kNumInputs = 2; | 1171 const intptr_t kNumInputs = 2; |
1144 const intptr_t kNumTemps = 0; | 1172 const intptr_t kNumTemps = 0; |
1145 LocationSummary* locs = new(isolate) LocationSummary( | 1173 LocationSummary* locs = new(isolate) LocationSummary( |
1146 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1174 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1147 locs->set_in(0, Location::RequiresRegister()); | 1175 locs->set_in(0, Location::RequiresRegister()); |
1148 // The smi index is either untagged (element size == 1), or it is left smi | 1176 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), true /*load*/)) { |
1149 // tagged (for all element sizes > 1). | 1177 // CanBeImmediateIndex must return false for unsafe smis. |
1150 // TODO(regis): Revisit and see if the index can be immediate. | 1178 locs->set_in(1, Location::Constant(index()->BoundConstant())); |
1151 if (index_scale() == 2 && IsExternal()) { | 1179 } else { |
1152 locs->set_in(1, Location::RequiresRegister()); | 1180 locs->set_in(1, Location::RequiresRegister()); |
1153 } else { | |
1154 locs->set_in(1, Location::WritableRegister()); | |
1155 } | 1181 } |
1156 if ((representation() == kUnboxedDouble) || | 1182 if ((representation() == kUnboxedDouble) || |
1157 (representation() == kUnboxedFloat32x4) || | 1183 (representation() == kUnboxedFloat32x4) || |
1158 (representation() == kUnboxedInt32x4) || | 1184 (representation() == kUnboxedInt32x4) || |
1159 (representation() == kUnboxedFloat64x2)) { | 1185 (representation() == kUnboxedFloat64x2)) { |
1160 if (class_id() == kTypedDataFloat32ArrayCid) { | 1186 if (class_id() == kTypedDataFloat32ArrayCid) { |
1161 // Need register <= Q7 for float operations. | 1187 // Need register <= Q7 for float operations. |
1162 // TODO(fschneider): Add a register policy to specify a subset of | 1188 // TODO(fschneider): Add a register policy to specify a subset of |
1163 // registers. | 1189 // registers. |
1164 locs->set_out(0, Location::FpuRegisterLocation(Q7)); | 1190 locs->set_out(0, Location::FpuRegisterLocation(Q7)); |
1165 } else { | 1191 } else { |
1166 locs->set_out(0, Location::RequiresFpuRegister()); | 1192 locs->set_out(0, Location::RequiresFpuRegister()); |
1167 } | 1193 } |
1168 } else if (representation() == kUnboxedMint) { | 1194 } else if (representation() == kUnboxedMint) { |
1169 locs->set_out(0, Location::Pair(Location::RequiresRegister(), | 1195 locs->set_out(0, Location::Pair(Location::RequiresRegister(), |
1170 Location::RequiresRegister())); | 1196 Location::RequiresRegister())); |
1171 } else { | 1197 } else { |
1172 ASSERT(representation() == kTagged); | 1198 ASSERT(representation() == kTagged); |
1173 locs->set_out(0, Location::RequiresRegister()); | 1199 locs->set_out(0, Location::RequiresRegister()); |
1174 } | 1200 } |
1175 return locs; | 1201 return locs; |
1176 } | 1202 } |
1177 | 1203 |
1178 | 1204 |
1205 static Address ElementAddressForIntIndex(bool is_external, | |
1206 intptr_t cid, | |
1207 intptr_t index_scale, | |
1208 Register array, | |
1209 intptr_t index) { | |
1210 const int64_t offset = static_cast<int64_t>(index) * index_scale + | |
1211 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | |
1212 ASSERT(Utils::IsInt(32, offset)); | |
1213 return Address(array, static_cast<int32_t>(offset)); | |
1214 } | |
1215 | |
1216 | |
1217 static Address ElementAddressForRegIndex(Assembler* assembler, | |
1218 bool is_load, | |
1219 bool is_external, | |
1220 intptr_t cid, | |
1221 intptr_t index_scale, | |
1222 Register array, | |
1223 Register index) { | |
1224 // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays. | |
1225 const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift; | |
1226 int32_t offset = | |
1227 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag); | |
1228 const OperandSize size = Address::OperandSizeFor(cid); | |
1229 const Register base = is_load ? IP : index; | |
zra
2014/05/23 20:03:24
Maybe assert that array and index can't be IP.
regis
2014/05/23 20:21:35
Registers array and index are defined by the regis
| |
1230 if ((offset != 0) || | |
1231 (size == kSWord) || (size == kDWord) || (size == kRegList)) { | |
1232 if (shift < 0) { | |
1233 ASSERT(shift == -1); | |
1234 assembler->add(base, array, ShifterOperand(index, ASR, 1)); | |
1235 } else { | |
1236 assembler->add(base, array, ShifterOperand(index, LSL, shift)); | |
1237 } | |
1238 } else { | |
1239 if (shift < 0) { | |
1240 ASSERT(shift == -1); | |
1241 return Address(array, index, ASR, 1); | |
1242 } else { | |
1243 return Address(array, index, LSL, shift); | |
1244 } | |
1245 } | |
1246 int32_t offset_mask = 0; | |
1247 if ((is_load && !Address::CanHoldLoadOffset(size, | |
1248 offset, | |
1249 &offset_mask)) || | |
1250 (!is_load && !Address::CanHoldStoreOffset(size, | |
1251 offset, | |
1252 &offset_mask))) { | |
1253 assembler->AddImmediate(base, offset & ~offset_mask); | |
1254 offset = offset & offset_mask; | |
1255 } | |
1256 return Address(base, offset); | |
1257 } | |
1258 | |
1259 | |
1179 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1260 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1261 Register array = locs()->in(0).reg(); | |
zra
2014/05/23 20:03:24
const
regis
2014/05/23 20:21:35
Done.
| |
1262 Location index = locs()->in(1); | |
1263 | |
1264 Address element_address(kNoRegister, 0); | |
1265 element_address = index.IsRegister() | |
1266 ? ElementAddressForRegIndex(compiler->assembler(), | |
1267 true, // Load. | |
1268 IsExternal(), class_id(), index_scale(), | |
1269 array, index.reg()) | |
1270 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), | |
1271 array, Smi::Cast(index.constant()).Value()); | |
1272 // Warning: element_address may use register IP as base. | |
1273 | |
1180 if ((representation() == kUnboxedDouble) || | 1274 if ((representation() == kUnboxedDouble) || |
1181 (representation() == kUnboxedFloat32x4) || | 1275 (representation() == kUnboxedFloat32x4) || |
1182 (representation() == kUnboxedInt32x4) || | 1276 (representation() == kUnboxedInt32x4) || |
1183 (representation() == kUnboxedFloat64x2)) { | 1277 (representation() == kUnboxedFloat64x2)) { |
1184 const Register array = locs()->in(0).reg(); | |
1185 const Register idx = locs()->in(1).reg(); | |
1186 switch (index_scale()) { | |
1187 case 1: | |
1188 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); | |
1189 break; | |
1190 case 4: | |
1191 __ add(idx, array, ShifterOperand(idx, LSL, 1)); | |
1192 break; | |
1193 case 8: | |
1194 __ add(idx, array, ShifterOperand(idx, LSL, 2)); | |
1195 break; | |
1196 case 16: | |
1197 __ add(idx, array, ShifterOperand(idx, LSL, 3)); | |
1198 break; | |
1199 default: | |
1200 // Case 2 is not reachable: We don't have unboxed 16-bit sized loads. | |
1201 UNREACHABLE(); | |
1202 } | |
1203 if (!IsExternal()) { | |
1204 ASSERT(this->array()->definition()->representation() == kTagged); | |
1205 __ AddImmediate(idx, | |
1206 Instance::DataOffsetFor(class_id()) - kHeapObjectTag); | |
1207 } | |
1208 Address element_address(idx); | |
1209 const QRegister result = locs()->out(0).fpu_reg(); | 1278 const QRegister result = locs()->out(0).fpu_reg(); |
1210 const DRegister dresult0 = EvenDRegisterOf(result); | 1279 const DRegister dresult0 = EvenDRegisterOf(result); |
1211 switch (class_id()) { | 1280 switch (class_id()) { |
1212 case kTypedDataFloat32ArrayCid: | 1281 case kTypedDataFloat32ArrayCid: |
1213 // Load single precision float. | 1282 // Load single precision float. |
1214 // vldrs does not support indexed addressing. | 1283 // vldrs does not support indexed addressing. |
1215 __ vldrs(EvenSRegisterOf(dresult0), element_address); | 1284 __ vldrs(EvenSRegisterOf(dresult0), element_address); |
1216 break; | 1285 break; |
1217 case kTypedDataFloat64ArrayCid: | 1286 case kTypedDataFloat64ArrayCid: |
1218 // vldrd does not support indexed addressing. | 1287 // vldrd does not support indexed addressing. |
1219 __ vldrd(dresult0, element_address); | 1288 __ vldrd(dresult0, element_address); |
1220 break; | 1289 break; |
1221 case kTypedDataFloat64x2ArrayCid: | 1290 case kTypedDataFloat64x2ArrayCid: |
1222 case kTypedDataInt32x4ArrayCid: | 1291 case kTypedDataInt32x4ArrayCid: |
1223 case kTypedDataFloat32x4ArrayCid: | 1292 case kTypedDataFloat32x4ArrayCid: |
1224 __ vldmd(IA, idx, dresult0, 2); | 1293 ASSERT(element_address.Equals(Address(IP))); |
1294 __ vldmd(IA, IP, dresult0, 2); | |
1225 break; | 1295 break; |
1226 default: | 1296 default: |
1227 UNREACHABLE(); | 1297 UNREACHABLE(); |
1228 } | 1298 } |
1229 return; | 1299 return; |
1230 } | 1300 } |
1231 | 1301 |
1232 const Register array = locs()->in(0).reg(); | |
1233 Location index = locs()->in(1); | |
1234 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | |
1235 Address element_address(kNoRegister, 0); | |
1236 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | |
1237 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | |
1238 // index is expected to be untagged before accessing. | |
1239 ASSERT(kSmiTagShift == 1); | |
1240 const intptr_t offset = IsExternal() | |
1241 ? 0 | |
1242 : Instance::DataOffsetFor(class_id()) - kHeapObjectTag; | |
1243 switch (index_scale()) { | |
1244 case 1: { | |
1245 __ add(index.reg(), array, ShifterOperand(index.reg(), ASR, kSmiTagSize)); | |
1246 element_address = Address(index.reg(), offset); | |
1247 break; | |
1248 } | |
1249 case 2: { | |
1250 // No scaling needed, since index is a smi. | |
1251 if (!IsExternal()) { | |
1252 __ AddImmediate(index.reg(), index.reg(), | |
1253 Instance::DataOffsetFor(class_id()) - kHeapObjectTag); | |
1254 element_address = Address(array, index.reg(), LSL, 0); | |
1255 } else { | |
1256 element_address = Address(array, index.reg(), LSL, 0); | |
1257 } | |
1258 break; | |
1259 } | |
1260 case 4: { | |
1261 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); | |
1262 element_address = Address(index.reg(), offset); | |
1263 break; | |
1264 } | |
1265 // Cases 8 and 16 are only for unboxed values and are handled above. | |
1266 default: | |
1267 UNREACHABLE(); | |
1268 } | |
1269 | |
1270 if (representation() == kUnboxedMint) { | 1302 if (representation() == kUnboxedMint) { |
1271 ASSERT(locs()->out(0).IsPairLocation()); | 1303 ASSERT(locs()->out(0).IsPairLocation()); |
1272 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 1304 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
1273 Register result1 = result_pair->At(0).reg(); | 1305 Register result1 = result_pair->At(0).reg(); |
zra
2014/05/23 20:03:24
const
regis
2014/05/23 20:21:35
Done.
| |
1274 Register result2 = result_pair->At(1).reg(); | 1306 Register result2 = result_pair->At(1).reg(); |
zra
2014/05/23 20:03:24
const
regis
2014/05/23 20:21:35
Done.
| |
1275 switch (class_id()) { | 1307 switch (class_id()) { |
1276 case kTypedDataInt32ArrayCid: | 1308 case kTypedDataInt32ArrayCid: |
1277 // Load low word. | 1309 // Load low word. |
1278 __ ldr(result1, element_address); | 1310 __ ldr(result1, element_address); |
1279 // Sign extend into high word. | 1311 // Sign extend into high word. |
1280 __ SignFill(result2, result1); | 1312 __ SignFill(result2, result1); |
1281 break; | 1313 break; |
1282 case kTypedDataUint32ArrayCid: | 1314 case kTypedDataUint32ArrayCid: |
1283 // Load low word. | 1315 // Load low word. |
1284 __ ldr(result1, element_address); | 1316 __ ldr(result1, element_address); |
1285 // Zero high word. | 1317 // Zero high word. |
1286 __ eor(result2, result2, ShifterOperand(result2)); | 1318 __ eor(result2, result2, ShifterOperand(result2)); |
1287 break; | 1319 break; |
1288 default: | 1320 default: |
1289 UNREACHABLE(); | 1321 UNREACHABLE(); |
1290 break; | 1322 break; |
1291 } | 1323 } |
1292 return; | 1324 return; |
1293 } | 1325 } |
1294 | 1326 |
1295 ASSERT(representation() == kTagged); | 1327 ASSERT(representation() == kTagged); |
1296 | 1328 |
1297 Register result = locs()->out(0).reg(); | 1329 Register result = locs()->out(0).reg(); |
1298 switch (class_id()) { | 1330 switch (class_id()) { |
1299 case kTypedDataInt8ArrayCid: | 1331 case kTypedDataInt8ArrayCid: |
1300 ASSERT(index_scale() == 1); | 1332 ASSERT(index_scale() == 1); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1383 } | 1415 } |
1384 | 1416 |
1385 | 1417 |
1386 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1418 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, |
1387 bool opt) const { | 1419 bool opt) const { |
1388 const intptr_t kNumInputs = 3; | 1420 const intptr_t kNumInputs = 3; |
1389 const intptr_t kNumTemps = 0; | 1421 const intptr_t kNumTemps = 0; |
1390 LocationSummary* locs = new(isolate) LocationSummary( | 1422 LocationSummary* locs = new(isolate) LocationSummary( |
1391 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1423 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1392 locs->set_in(0, Location::RequiresRegister()); | 1424 locs->set_in(0, Location::RequiresRegister()); |
1393 // The smi index is either untagged (element size == 1), or it is left smi | 1425 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), false /*store*/)) { |
1394 // tagged (for all element sizes > 1). | 1426 // CanBeImmediateIndex must return false for unsafe smis. |
1395 // TODO(regis): Revisit and see if the index can be immediate. | 1427 locs->set_in(1, Location::Constant(index()->BoundConstant())); |
1396 locs->set_in(1, Location::WritableRegister()); | 1428 } else { |
1429 locs->set_in(1, Location::WritableRegister()); | |
1430 } | |
1397 switch (class_id()) { | 1431 switch (class_id()) { |
1398 case kArrayCid: | 1432 case kArrayCid: |
1399 locs->set_in(2, ShouldEmitStoreBarrier() | 1433 locs->set_in(2, ShouldEmitStoreBarrier() |
1400 ? Location::WritableRegister() | 1434 ? Location::WritableRegister() |
1401 : Location::RegisterOrConstant(value())); | 1435 : Location::RegisterOrConstant(value())); |
1402 break; | 1436 break; |
1403 case kExternalTypedDataUint8ArrayCid: | 1437 case kExternalTypedDataUint8ArrayCid: |
1404 case kExternalTypedDataUint8ClampedArrayCid: | 1438 case kExternalTypedDataUint8ClampedArrayCid: |
1405 case kTypedDataInt8ArrayCid: | 1439 case kTypedDataInt8ArrayCid: |
1406 case kTypedDataUint8ArrayCid: | 1440 case kTypedDataUint8ArrayCid: |
(...skipping 28 matching lines...) Expand all Loading... | |
1435 break; | 1469 break; |
1436 default: | 1470 default: |
1437 UNREACHABLE(); | 1471 UNREACHABLE(); |
1438 return NULL; | 1472 return NULL; |
1439 } | 1473 } |
1440 return locs; | 1474 return locs; |
1441 } | 1475 } |
1442 | 1476 |
1443 | 1477 |
1444 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1478 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1445 if ((class_id() == kTypedDataFloat32ArrayCid) || | 1479 Register array = locs()->in(0).reg(); |
zra
2014/05/23 20:03:24
const
regis
2014/05/23 20:21:35
Done.
| |
1446 (class_id() == kTypedDataFloat64ArrayCid) || | |
1447 (class_id() == kTypedDataFloat32x4ArrayCid) || | |
1448 (class_id() == kTypedDataFloat64x2ArrayCid) || | |
1449 (class_id() == kTypedDataInt32x4ArrayCid)) { | |
1450 const Register array = locs()->in(0).reg(); | |
1451 const Register idx = locs()->in(1).reg(); | |
1452 Location value = locs()->in(2); | |
1453 switch (index_scale()) { | |
1454 case 1: | |
1455 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); | |
1456 break; | |
1457 case 4: | |
1458 __ add(idx, array, ShifterOperand(idx, LSL, 1)); | |
1459 break; | |
1460 case 8: | |
1461 __ add(idx, array, ShifterOperand(idx, LSL, 2)); | |
1462 break; | |
1463 case 16: | |
1464 __ add(idx, array, ShifterOperand(idx, LSL, 3)); | |
1465 break; | |
1466 default: | |
1467 // Case 2 is not reachable: We don't have unboxed 16-bit sized loads. | |
1468 UNREACHABLE(); | |
1469 } | |
1470 if (!IsExternal()) { | |
1471 ASSERT(this->array()->definition()->representation() == kTagged); | |
1472 __ AddImmediate(idx, | |
1473 Instance::DataOffsetFor(class_id()) - kHeapObjectTag); | |
1474 } | |
1475 switch (class_id()) { | |
1476 case kTypedDataFloat32ArrayCid: { | |
1477 const SRegister value_reg = | |
1478 EvenSRegisterOf(EvenDRegisterOf(value.fpu_reg())); | |
1479 __ StoreSToOffset(value_reg, idx, 0); | |
1480 break; | |
1481 } | |
1482 case kTypedDataFloat64ArrayCid: { | |
1483 const DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); | |
1484 __ StoreDToOffset(value_reg, idx, 0); | |
1485 break; | |
1486 } | |
1487 case kTypedDataFloat64x2ArrayCid: | |
1488 case kTypedDataInt32x4ArrayCid: | |
1489 case kTypedDataFloat32x4ArrayCid: { | |
1490 const DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); | |
1491 __ vstmd(IA, idx, value_reg, 2); | |
1492 break; | |
1493 } | |
1494 default: | |
1495 UNREACHABLE(); | |
1496 } | |
1497 return; | |
1498 } | |
1499 | |
1500 const Register array = locs()->in(0).reg(); | |
1501 Location index = locs()->in(1); | 1480 Location index = locs()->in(1); |
1502 | 1481 |
1503 Address element_address(kNoRegister, 0); | 1482 Address element_address(kNoRegister, 0); |
1504 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | 1483 element_address = index.IsRegister() |
1505 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | 1484 ? ElementAddressForRegIndex(compiler->assembler(), |
1506 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | 1485 false, // Store. |
1507 // index is expected to be untagged before accessing. | 1486 IsExternal(), class_id(), index_scale(), |
1508 ASSERT(kSmiTagShift == 1); | 1487 array, index.reg()) |
1509 const intptr_t offset = IsExternal() | 1488 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), |
1510 ? 0 | 1489 array, Smi::Cast(index.constant()).Value()); |
1511 : Instance::DataOffsetFor(class_id()) - kHeapObjectTag; | |
1512 switch (index_scale()) { | |
1513 case 1: { | |
1514 __ add(index.reg(), array, ShifterOperand(index.reg(), ASR, kSmiTagSize)); | |
1515 element_address = Address(index.reg(), offset); | |
1516 break; | |
1517 } | |
1518 case 2: { | |
1519 // No scaling needed, since index is a smi. | |
1520 if (!IsExternal()) { | |
1521 __ AddImmediate(index.reg(), index.reg(), offset); | |
1522 element_address = Address(array, index.reg(), LSL, 0); | |
1523 } else { | |
1524 element_address = Address(array, index.reg(), LSL, 0); | |
1525 } | |
1526 break; | |
1527 } | |
1528 case 4: { | |
1529 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); | |
1530 element_address = Address(index.reg(), offset); | |
1531 break; | |
1532 } | |
1533 // Cases 8 and 16 are only for unboxed values and are handled above. | |
1534 default: | |
1535 UNREACHABLE(); | |
1536 } | |
1537 | 1490 |
1538 switch (class_id()) { | 1491 switch (class_id()) { |
1539 case kArrayCid: | 1492 case kArrayCid: |
1540 if (ShouldEmitStoreBarrier()) { | 1493 if (ShouldEmitStoreBarrier()) { |
1541 const Register value = locs()->in(2).reg(); | 1494 const Register value = locs()->in(2).reg(); |
1542 __ StoreIntoObject(array, element_address, value); | 1495 __ StoreIntoObject(array, element_address, value); |
1543 } else if (locs()->in(2).IsConstant()) { | 1496 } else if (locs()->in(2).IsConstant()) { |
1544 const Object& constant = locs()->in(2).constant(); | 1497 const Object& constant = locs()->in(2).constant(); |
1545 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1498 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
1546 } else { | 1499 } else { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1605 __ SmiUntag(value); | 1558 __ SmiUntag(value); |
1606 __ str(value, element_address); | 1559 __ str(value, element_address); |
1607 } else { | 1560 } else { |
1608 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1561 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1609 PairLocation* value_pair = locs()->in(2).AsPairLocation(); | 1562 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
1610 Register value1 = value_pair->At(0).reg(); | 1563 Register value1 = value_pair->At(0).reg(); |
1611 __ str(value1, element_address); | 1564 __ str(value1, element_address); |
1612 } | 1565 } |
1613 break; | 1566 break; |
1614 } | 1567 } |
1568 case kTypedDataFloat32ArrayCid: { | |
1569 const SRegister value_reg = | |
1570 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); | |
1571 __ vstrs(value_reg, element_address); | |
1572 break; | |
1573 } | |
1574 case kTypedDataFloat64ArrayCid: { | |
1575 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); | |
1576 __ vstrd(value_reg, element_address); | |
1577 break; | |
1578 } | |
1579 case kTypedDataFloat64x2ArrayCid: | |
1580 case kTypedDataInt32x4ArrayCid: | |
1581 case kTypedDataFloat32x4ArrayCid: { | |
1582 ASSERT(element_address.Equals(Address(index.reg()))); | |
1583 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); | |
1584 __ vstmd(IA, index.reg(), value_reg, 2); | |
1585 break; | |
1586 } | |
1615 default: | 1587 default: |
1616 UNREACHABLE(); | 1588 UNREACHABLE(); |
1617 } | 1589 } |
1618 } | 1590 } |
1619 | 1591 |
1620 | 1592 |
1621 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, | 1593 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, |
1622 bool opt) const { | 1594 bool opt) const { |
1623 const intptr_t kNumInputs = 1; | 1595 const intptr_t kNumInputs = 1; |
1624 LocationSummary* summary = new(isolate) LocationSummary( | 1596 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 4813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6438 compiler->GenerateCall(token_pos(), | 6410 compiler->GenerateCall(token_pos(), |
6439 &label, | 6411 &label, |
6440 PcDescriptors::kOther, | 6412 PcDescriptors::kOther, |
6441 locs()); | 6413 locs()); |
6442 __ Drop(ArgumentCount()); // Discard arguments. | 6414 __ Drop(ArgumentCount()); // Discard arguments. |
6443 } | 6415 } |
6444 | 6416 |
6445 } // namespace dart | 6417 } // namespace dart |
6446 | 6418 |
6447 #endif // defined TARGET_ARCH_ARM | 6419 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |