Chromium Code Reviews| 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 |