| 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 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 return kUnboxedFloat32x4; | 1133 return kUnboxedFloat32x4; |
| 1134 case kTypedDataFloat64x2ArrayCid: | 1134 case kTypedDataFloat64x2ArrayCid: |
| 1135 return kUnboxedFloat64x2; | 1135 return kUnboxedFloat64x2; |
| 1136 default: | 1136 default: |
| 1137 UNREACHABLE(); | 1137 UNREACHABLE(); |
| 1138 return kTagged; | 1138 return kTagged; |
| 1139 } | 1139 } |
| 1140 } | 1140 } |
| 1141 | 1141 |
| 1142 | 1142 |
| 1143 static bool CanHoldImmediateOffset(bool is_load, intptr_t cid, int64_t offset) { | |
| 1144 int32_t offset_mask = 0; | |
| 1145 if (is_load) { | |
| 1146 return Address::CanHoldLoadOffset(Address::OperandSizeFor(cid), | |
| 1147 offset, | |
| 1148 &offset_mask); | |
| 1149 } else { | |
| 1150 return Address::CanHoldStoreOffset(Address::OperandSizeFor(cid), | |
| 1151 offset, | |
| 1152 &offset_mask); | |
| 1153 } | |
| 1154 } | |
| 1155 | |
| 1156 static bool CanBeImmediateIndex(Value* value, | 1143 static bool CanBeImmediateIndex(Value* value, |
| 1157 intptr_t cid, | 1144 intptr_t cid, |
| 1158 bool is_external, | 1145 bool is_external, |
| 1159 bool is_load, | 1146 bool is_load, |
| 1160 bool* needs_base) { | 1147 bool* needs_base) { |
| 1161 if ((cid == kTypedDataInt32x4ArrayCid) || | 1148 if ((cid == kTypedDataInt32x4ArrayCid) || |
| 1162 (cid == kTypedDataFloat32x4ArrayCid) || | 1149 (cid == kTypedDataFloat32x4ArrayCid) || |
| 1163 (cid == kTypedDataFloat64x2ArrayCid)) { | 1150 (cid == kTypedDataFloat64x2ArrayCid)) { |
| 1164 // We are using vldmd/vstmd which do not support offset. | 1151 // We are using vldmd/vstmd which do not support offset. |
| 1165 return false; | 1152 return false; |
| 1166 } | 1153 } |
| 1167 | 1154 |
| 1168 ConstantInstr* constant = value->definition()->AsConstant(); | 1155 ConstantInstr* constant = value->definition()->AsConstant(); |
| 1169 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 1156 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
| 1170 return false; | 1157 return false; |
| 1171 } | 1158 } |
| 1172 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 1159 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 1173 const intptr_t scale = Instance::ElementSizeFor(cid); | 1160 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 1174 const intptr_t base_offset = | 1161 const intptr_t base_offset = |
| 1175 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 1162 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 1176 const int64_t offset = index * scale + base_offset; | 1163 const int64_t offset = index * scale + base_offset; |
| 1177 if (!Utils::IsAbsoluteUint(12, offset)) { | 1164 if (!Utils::IsAbsoluteUint(12, offset)) { |
| 1178 return false; | 1165 return false; |
| 1179 } | 1166 } |
| 1180 if (CanHoldImmediateOffset(is_load, cid, offset)) { | 1167 if (Address::CanHoldImmediateOffset(is_load, cid, offset)) { |
| 1181 *needs_base = false; | 1168 *needs_base = false; |
| 1182 return true; | 1169 return true; |
| 1183 } | 1170 } |
| 1184 | 1171 |
| 1185 if (CanHoldImmediateOffset(is_load, cid, offset - base_offset)) { | 1172 if (Address::CanHoldImmediateOffset(is_load, cid, offset - base_offset)) { |
| 1186 *needs_base = true; | 1173 *needs_base = true; |
| 1187 return true; | 1174 return true; |
| 1188 } | 1175 } |
| 1189 | 1176 |
| 1190 return false; | 1177 return false; |
| 1191 } | 1178 } |
| 1192 | 1179 |
| 1193 | 1180 |
| 1194 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1181 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, |
| 1195 bool opt) const { | 1182 bool opt) const { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1223 locs->set_out(0, Location::Pair(Location::RequiresRegister(), | 1210 locs->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 1224 Location::RequiresRegister())); | 1211 Location::RequiresRegister())); |
| 1225 } else { | 1212 } else { |
| 1226 ASSERT(representation() == kTagged); | 1213 ASSERT(representation() == kTagged); |
| 1227 locs->set_out(0, Location::RequiresRegister()); | 1214 locs->set_out(0, Location::RequiresRegister()); |
| 1228 } | 1215 } |
| 1229 return locs; | 1216 return locs; |
| 1230 } | 1217 } |
| 1231 | 1218 |
| 1232 | 1219 |
| 1233 static Address ElementAddressForIntIndex(Assembler* assembler, | |
| 1234 bool is_load, | |
| 1235 bool is_external, | |
| 1236 intptr_t cid, | |
| 1237 intptr_t index_scale, | |
| 1238 Register array, | |
| 1239 intptr_t index, | |
| 1240 Register temp) { | |
| 1241 const int64_t offset_base = | |
| 1242 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | |
| 1243 const int64_t offset = offset_base + | |
| 1244 static_cast<int64_t>(index) * index_scale; | |
| 1245 ASSERT(Utils::IsInt(32, offset)); | |
| 1246 | |
| 1247 if (CanHoldImmediateOffset(is_load, cid, offset)) { | |
| 1248 return Address(array, static_cast<int32_t>(offset)); | |
| 1249 } else { | |
| 1250 ASSERT(CanHoldImmediateOffset(is_load, cid, offset - offset_base)); | |
| 1251 assembler->AddImmediate( | |
| 1252 temp, array, static_cast<int32_t>(offset_base)); | |
| 1253 return Address(temp, static_cast<int32_t>(offset - offset_base)); | |
| 1254 } | |
| 1255 } | |
| 1256 | |
| 1257 | |
| 1258 static Address ElementAddressForRegIndex(Assembler* assembler, | |
| 1259 bool is_load, | |
| 1260 bool is_external, | |
| 1261 intptr_t cid, | |
| 1262 intptr_t index_scale, | |
| 1263 Register array, | |
| 1264 Register index) { | |
| 1265 // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays. | |
| 1266 const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift; | |
| 1267 int32_t offset = | |
| 1268 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag); | |
| 1269 const OperandSize size = Address::OperandSizeFor(cid); | |
| 1270 ASSERT(array != IP); | |
| 1271 ASSERT(index != IP); | |
| 1272 const Register base = is_load ? IP : index; | |
| 1273 if ((offset != 0) || | |
| 1274 (size == kSWord) || (size == kDWord) || (size == kRegList)) { | |
| 1275 if (shift < 0) { | |
| 1276 ASSERT(shift == -1); | |
| 1277 assembler->add(base, array, Operand(index, ASR, 1)); | |
| 1278 } else { | |
| 1279 assembler->add(base, array, Operand(index, LSL, shift)); | |
| 1280 } | |
| 1281 } else { | |
| 1282 if (shift < 0) { | |
| 1283 ASSERT(shift == -1); | |
| 1284 return Address(array, index, ASR, 1); | |
| 1285 } else { | |
| 1286 return Address(array, index, LSL, shift); | |
| 1287 } | |
| 1288 } | |
| 1289 int32_t offset_mask = 0; | |
| 1290 if ((is_load && !Address::CanHoldLoadOffset(size, | |
| 1291 offset, | |
| 1292 &offset_mask)) || | |
| 1293 (!is_load && !Address::CanHoldStoreOffset(size, | |
| 1294 offset, | |
| 1295 &offset_mask))) { | |
| 1296 assembler->AddImmediate(base, offset & ~offset_mask); | |
| 1297 offset = offset & offset_mask; | |
| 1298 } | |
| 1299 return Address(base, offset); | |
| 1300 } | |
| 1301 | |
| 1302 | |
| 1303 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1220 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1304 // The array register points to the backing store for external arrays. | 1221 // The array register points to the backing store for external arrays. |
| 1305 const Register array = locs()->in(0).reg(); | 1222 const Register array = locs()->in(0).reg(); |
| 1306 const Location index = locs()->in(1); | 1223 const Location index = locs()->in(1); |
| 1307 | 1224 |
| 1308 Address element_address = index.IsRegister() | 1225 Address element_address = index.IsRegister() |
| 1309 ? ElementAddressForRegIndex(compiler->assembler(), | 1226 ? __ ElementAddressForRegIndex(true, // Load. |
| 1310 true, // Load. | 1227 IsExternal(), class_id(), index_scale(), |
| 1311 IsExternal(), class_id(), index_scale(), | 1228 array, |
| 1312 array, index.reg()) | 1229 index.reg()) |
| 1313 : ElementAddressForIntIndex(compiler->assembler(), | 1230 : __ ElementAddressForIntIndex(true, // Load. |
| 1314 true, // Load. | 1231 IsExternal(), class_id(), index_scale(), |
| 1315 IsExternal(), class_id(), index_scale(), | 1232 array, Smi::Cast(index.constant()).Value(), |
| 1316 array, Smi::Cast(index.constant()).Value(), | 1233 IP); // Temp register. |
| 1317 IP); // Temp register. | |
| 1318 // Warning: element_address may use register IP as base. | 1234 // Warning: element_address may use register IP as base. |
| 1319 | 1235 |
| 1320 if ((representation() == kUnboxedDouble) || | 1236 if ((representation() == kUnboxedDouble) || |
| 1321 (representation() == kUnboxedFloat32x4) || | 1237 (representation() == kUnboxedFloat32x4) || |
| 1322 (representation() == kUnboxedInt32x4) || | 1238 (representation() == kUnboxedInt32x4) || |
| 1323 (representation() == kUnboxedFloat64x2)) { | 1239 (representation() == kUnboxedFloat64x2)) { |
| 1324 const QRegister result = locs()->out(0).fpu_reg(); | 1240 const QRegister result = locs()->out(0).fpu_reg(); |
| 1325 const DRegister dresult0 = EvenDRegisterOf(result); | 1241 const DRegister dresult0 = EvenDRegisterOf(result); |
| 1326 switch (class_id()) { | 1242 switch (class_id()) { |
| 1327 case kTypedDataFloat32ArrayCid: | 1243 case kTypedDataFloat32ArrayCid: |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 | 1451 |
| 1536 | 1452 |
| 1537 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1453 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1538 // The array register points to the backing store for external arrays. | 1454 // The array register points to the backing store for external arrays. |
| 1539 const Register array = locs()->in(0).reg(); | 1455 const Register array = locs()->in(0).reg(); |
| 1540 const Location index = locs()->in(1); | 1456 const Location index = locs()->in(1); |
| 1541 const Register temp = | 1457 const Register temp = |
| 1542 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; | 1458 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; |
| 1543 | 1459 |
| 1544 Address element_address = index.IsRegister() | 1460 Address element_address = index.IsRegister() |
| 1545 ? ElementAddressForRegIndex(compiler->assembler(), | 1461 ? __ ElementAddressForRegIndex(false, // Store. |
| 1546 false, // Store. | 1462 IsExternal(), class_id(), index_scale(), |
| 1547 IsExternal(), class_id(), index_scale(), | 1463 array, |
| 1548 array, index.reg()) | 1464 index.reg()) |
| 1549 : ElementAddressForIntIndex(compiler->assembler(), | 1465 : __ ElementAddressForIntIndex(false, // Store. |
| 1550 false, // Store. | 1466 IsExternal(), class_id(), index_scale(), |
| 1551 IsExternal(), class_id(), index_scale(), | 1467 array, Smi::Cast(index.constant()).Value(), |
| 1552 array, Smi::Cast(index.constant()).Value(), | 1468 temp); |
| 1553 temp); | |
| 1554 | 1469 |
| 1555 switch (class_id()) { | 1470 switch (class_id()) { |
| 1556 case kArrayCid: | 1471 case kArrayCid: |
| 1557 if (ShouldEmitStoreBarrier()) { | 1472 if (ShouldEmitStoreBarrier()) { |
| 1558 const Register value = locs()->in(2).reg(); | 1473 const Register value = locs()->in(2).reg(); |
| 1559 __ StoreIntoObject(array, element_address, value); | 1474 __ StoreIntoObject(array, element_address, value); |
| 1560 } else if (locs()->in(2).IsConstant()) { | 1475 } else if (locs()->in(2).IsConstant()) { |
| 1561 const Object& constant = locs()->in(2).constant(); | 1476 const Object& constant = locs()->in(2).constant(); |
| 1562 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1477 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1563 } else { | 1478 } else { |
| (...skipping 5325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6889 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6804 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 6890 #if defined(DEBUG) | 6805 #if defined(DEBUG) |
| 6891 __ LoadImmediate(R4, kInvalidObjectPointer); | 6806 __ LoadImmediate(R4, kInvalidObjectPointer); |
| 6892 __ LoadImmediate(R5, kInvalidObjectPointer); | 6807 __ LoadImmediate(R5, kInvalidObjectPointer); |
| 6893 #endif | 6808 #endif |
| 6894 } | 6809 } |
| 6895 | 6810 |
| 6896 } // namespace dart | 6811 } // namespace dart |
| 6897 | 6812 |
| 6898 #endif // defined TARGET_ARCH_ARM | 6813 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |