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 ASSERT(array != IP); |
| 1230 ASSERT(index != IP); |
| 1231 const Register base = is_load ? IP : index; |
| 1232 if ((offset != 0) || |
| 1233 (size == kSWord) || (size == kDWord) || (size == kRegList)) { |
| 1234 if (shift < 0) { |
| 1235 ASSERT(shift == -1); |
| 1236 assembler->add(base, array, ShifterOperand(index, ASR, 1)); |
| 1237 } else { |
| 1238 assembler->add(base, array, ShifterOperand(index, LSL, shift)); |
| 1239 } |
| 1240 } else { |
| 1241 if (shift < 0) { |
| 1242 ASSERT(shift == -1); |
| 1243 return Address(array, index, ASR, 1); |
| 1244 } else { |
| 1245 return Address(array, index, LSL, shift); |
| 1246 } |
| 1247 } |
| 1248 int32_t offset_mask = 0; |
| 1249 if ((is_load && !Address::CanHoldLoadOffset(size, |
| 1250 offset, |
| 1251 &offset_mask)) || |
| 1252 (!is_load && !Address::CanHoldStoreOffset(size, |
| 1253 offset, |
| 1254 &offset_mask))) { |
| 1255 assembler->AddImmediate(base, offset & ~offset_mask); |
| 1256 offset = offset & offset_mask; |
| 1257 } |
| 1258 return Address(base, offset); |
| 1259 } |
| 1260 |
| 1261 |
1179 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1262 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1263 const Register array = locs()->in(0).reg(); |
| 1264 const Location index = locs()->in(1); |
| 1265 |
| 1266 Address element_address(kNoRegister, 0); |
| 1267 element_address = index.IsRegister() |
| 1268 ? ElementAddressForRegIndex(compiler->assembler(), |
| 1269 true, // Load. |
| 1270 IsExternal(), class_id(), index_scale(), |
| 1271 array, index.reg()) |
| 1272 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), |
| 1273 array, Smi::Cast(index.constant()).Value()); |
| 1274 // Warning: element_address may use register IP as base. |
| 1275 |
1180 if ((representation() == kUnboxedDouble) || | 1276 if ((representation() == kUnboxedDouble) || |
1181 (representation() == kUnboxedFloat32x4) || | 1277 (representation() == kUnboxedFloat32x4) || |
1182 (representation() == kUnboxedInt32x4) || | 1278 (representation() == kUnboxedInt32x4) || |
1183 (representation() == kUnboxedFloat64x2)) { | 1279 (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(); | 1280 const QRegister result = locs()->out(0).fpu_reg(); |
1210 const DRegister dresult0 = EvenDRegisterOf(result); | 1281 const DRegister dresult0 = EvenDRegisterOf(result); |
1211 switch (class_id()) { | 1282 switch (class_id()) { |
1212 case kTypedDataFloat32ArrayCid: | 1283 case kTypedDataFloat32ArrayCid: |
1213 // Load single precision float. | 1284 // Load single precision float. |
1214 // vldrs does not support indexed addressing. | 1285 // vldrs does not support indexed addressing. |
1215 __ vldrs(EvenSRegisterOf(dresult0), element_address); | 1286 __ vldrs(EvenSRegisterOf(dresult0), element_address); |
1216 break; | 1287 break; |
1217 case kTypedDataFloat64ArrayCid: | 1288 case kTypedDataFloat64ArrayCid: |
1218 // vldrd does not support indexed addressing. | 1289 // vldrd does not support indexed addressing. |
1219 __ vldrd(dresult0, element_address); | 1290 __ vldrd(dresult0, element_address); |
1220 break; | 1291 break; |
1221 case kTypedDataFloat64x2ArrayCid: | 1292 case kTypedDataFloat64x2ArrayCid: |
1222 case kTypedDataInt32x4ArrayCid: | 1293 case kTypedDataInt32x4ArrayCid: |
1223 case kTypedDataFloat32x4ArrayCid: | 1294 case kTypedDataFloat32x4ArrayCid: |
1224 __ vldmd(IA, idx, dresult0, 2); | 1295 ASSERT(element_address.Equals(Address(IP))); |
| 1296 __ vldmd(IA, IP, dresult0, 2); |
1225 break; | 1297 break; |
1226 default: | 1298 default: |
1227 UNREACHABLE(); | 1299 UNREACHABLE(); |
1228 } | 1300 } |
1229 return; | 1301 return; |
1230 } | 1302 } |
1231 | 1303 |
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) { | 1304 if (representation() == kUnboxedMint) { |
1271 ASSERT(locs()->out(0).IsPairLocation()); | 1305 ASSERT(locs()->out(0).IsPairLocation()); |
1272 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 1306 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
1273 Register result1 = result_pair->At(0).reg(); | 1307 const Register result1 = result_pair->At(0).reg(); |
1274 Register result2 = result_pair->At(1).reg(); | 1308 const Register result2 = result_pair->At(1).reg(); |
1275 switch (class_id()) { | 1309 switch (class_id()) { |
1276 case kTypedDataInt32ArrayCid: | 1310 case kTypedDataInt32ArrayCid: |
1277 // Load low word. | 1311 // Load low word. |
1278 __ ldr(result1, element_address); | 1312 __ ldr(result1, element_address); |
1279 // Sign extend into high word. | 1313 // Sign extend into high word. |
1280 __ SignFill(result2, result1); | 1314 __ SignFill(result2, result1); |
1281 break; | 1315 break; |
1282 case kTypedDataUint32ArrayCid: | 1316 case kTypedDataUint32ArrayCid: |
1283 // Load low word. | 1317 // Load low word. |
1284 __ ldr(result1, element_address); | 1318 __ ldr(result1, element_address); |
1285 // Zero high word. | 1319 // Zero high word. |
1286 __ eor(result2, result2, ShifterOperand(result2)); | 1320 __ eor(result2, result2, ShifterOperand(result2)); |
1287 break; | 1321 break; |
1288 default: | 1322 default: |
1289 UNREACHABLE(); | 1323 UNREACHABLE(); |
1290 break; | 1324 break; |
1291 } | 1325 } |
1292 return; | 1326 return; |
1293 } | 1327 } |
1294 | 1328 |
1295 ASSERT(representation() == kTagged); | 1329 ASSERT(representation() == kTagged); |
1296 | 1330 |
1297 Register result = locs()->out(0).reg(); | 1331 Register result = locs()->out(0).reg(); |
1298 switch (class_id()) { | 1332 switch (class_id()) { |
1299 case kTypedDataInt8ArrayCid: | 1333 case kTypedDataInt8ArrayCid: |
1300 ASSERT(index_scale() == 1); | 1334 ASSERT(index_scale() == 1); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 } | 1417 } |
1384 | 1418 |
1385 | 1419 |
1386 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1420 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, |
1387 bool opt) const { | 1421 bool opt) const { |
1388 const intptr_t kNumInputs = 3; | 1422 const intptr_t kNumInputs = 3; |
1389 const intptr_t kNumTemps = 0; | 1423 const intptr_t kNumTemps = 0; |
1390 LocationSummary* locs = new(isolate) LocationSummary( | 1424 LocationSummary* locs = new(isolate) LocationSummary( |
1391 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1425 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1392 locs->set_in(0, Location::RequiresRegister()); | 1426 locs->set_in(0, Location::RequiresRegister()); |
1393 // The smi index is either untagged (element size == 1), or it is left smi | 1427 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), false /*store*/)) { |
1394 // tagged (for all element sizes > 1). | 1428 // CanBeImmediateIndex must return false for unsafe smis. |
1395 // TODO(regis): Revisit and see if the index can be immediate. | 1429 locs->set_in(1, Location::Constant(index()->BoundConstant())); |
1396 locs->set_in(1, Location::WritableRegister()); | 1430 } else { |
| 1431 locs->set_in(1, Location::WritableRegister()); |
| 1432 } |
1397 switch (class_id()) { | 1433 switch (class_id()) { |
1398 case kArrayCid: | 1434 case kArrayCid: |
1399 locs->set_in(2, ShouldEmitStoreBarrier() | 1435 locs->set_in(2, ShouldEmitStoreBarrier() |
1400 ? Location::WritableRegister() | 1436 ? Location::WritableRegister() |
1401 : Location::RegisterOrConstant(value())); | 1437 : Location::RegisterOrConstant(value())); |
1402 break; | 1438 break; |
1403 case kExternalTypedDataUint8ArrayCid: | 1439 case kExternalTypedDataUint8ArrayCid: |
1404 case kExternalTypedDataUint8ClampedArrayCid: | 1440 case kExternalTypedDataUint8ClampedArrayCid: |
1405 case kTypedDataInt8ArrayCid: | 1441 case kTypedDataInt8ArrayCid: |
1406 case kTypedDataUint8ArrayCid: | 1442 case kTypedDataUint8ArrayCid: |
(...skipping 28 matching lines...) Expand all Loading... |
1435 break; | 1471 break; |
1436 default: | 1472 default: |
1437 UNREACHABLE(); | 1473 UNREACHABLE(); |
1438 return NULL; | 1474 return NULL; |
1439 } | 1475 } |
1440 return locs; | 1476 return locs; |
1441 } | 1477 } |
1442 | 1478 |
1443 | 1479 |
1444 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1480 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1445 if ((class_id() == kTypedDataFloat32ArrayCid) || | |
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(); | 1481 const Register array = locs()->in(0).reg(); |
1501 Location index = locs()->in(1); | 1482 Location index = locs()->in(1); |
1502 | 1483 |
1503 Address element_address(kNoRegister, 0); | 1484 Address element_address(kNoRegister, 0); |
1504 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | 1485 element_address = index.IsRegister() |
1505 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | 1486 ? ElementAddressForRegIndex(compiler->assembler(), |
1506 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | 1487 false, // Store. |
1507 // index is expected to be untagged before accessing. | 1488 IsExternal(), class_id(), index_scale(), |
1508 ASSERT(kSmiTagShift == 1); | 1489 array, index.reg()) |
1509 const intptr_t offset = IsExternal() | 1490 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), |
1510 ? 0 | 1491 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 | 1492 |
1538 switch (class_id()) { | 1493 switch (class_id()) { |
1539 case kArrayCid: | 1494 case kArrayCid: |
1540 if (ShouldEmitStoreBarrier()) { | 1495 if (ShouldEmitStoreBarrier()) { |
1541 const Register value = locs()->in(2).reg(); | 1496 const Register value = locs()->in(2).reg(); |
1542 __ StoreIntoObject(array, element_address, value); | 1497 __ StoreIntoObject(array, element_address, value); |
1543 } else if (locs()->in(2).IsConstant()) { | 1498 } else if (locs()->in(2).IsConstant()) { |
1544 const Object& constant = locs()->in(2).constant(); | 1499 const Object& constant = locs()->in(2).constant(); |
1545 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1500 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
1546 } else { | 1501 } else { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 __ SmiUntag(value); | 1560 __ SmiUntag(value); |
1606 __ str(value, element_address); | 1561 __ str(value, element_address); |
1607 } else { | 1562 } else { |
1608 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1563 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1609 PairLocation* value_pair = locs()->in(2).AsPairLocation(); | 1564 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
1610 Register value1 = value_pair->At(0).reg(); | 1565 Register value1 = value_pair->At(0).reg(); |
1611 __ str(value1, element_address); | 1566 __ str(value1, element_address); |
1612 } | 1567 } |
1613 break; | 1568 break; |
1614 } | 1569 } |
| 1570 case kTypedDataFloat32ArrayCid: { |
| 1571 const SRegister value_reg = |
| 1572 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); |
| 1573 __ vstrs(value_reg, element_address); |
| 1574 break; |
| 1575 } |
| 1576 case kTypedDataFloat64ArrayCid: { |
| 1577 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
| 1578 __ vstrd(value_reg, element_address); |
| 1579 break; |
| 1580 } |
| 1581 case kTypedDataFloat64x2ArrayCid: |
| 1582 case kTypedDataInt32x4ArrayCid: |
| 1583 case kTypedDataFloat32x4ArrayCid: { |
| 1584 ASSERT(element_address.Equals(Address(index.reg()))); |
| 1585 const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
| 1586 __ vstmd(IA, index.reg(), value_reg, 2); |
| 1587 break; |
| 1588 } |
1615 default: | 1589 default: |
1616 UNREACHABLE(); | 1590 UNREACHABLE(); |
1617 } | 1591 } |
1618 } | 1592 } |
1619 | 1593 |
1620 | 1594 |
1621 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, | 1595 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, |
1622 bool opt) const { | 1596 bool opt) const { |
1623 const intptr_t kNumInputs = 1; | 1597 const intptr_t kNumInputs = 1; |
1624 LocationSummary* summary = new(isolate) LocationSummary( | 1598 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 4813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6438 compiler->GenerateCall(token_pos(), | 6412 compiler->GenerateCall(token_pos(), |
6439 &label, | 6413 &label, |
6440 PcDescriptors::kOther, | 6414 PcDescriptors::kOther, |
6441 locs()); | 6415 locs()); |
6442 __ Drop(ArgumentCount()); // Discard arguments. | 6416 __ Drop(ArgumentCount()); // Discard arguments. |
6443 } | 6417 } |
6444 | 6418 |
6445 } // namespace dart | 6419 } // namespace dart |
6446 | 6420 |
6447 #endif // defined TARGET_ARCH_ARM | 6421 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |