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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 Register result = locs()->out().reg(); | 1087 Register result = locs()->out().reg(); |
1088 __ movl(result, | 1088 __ movl(result, |
1089 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); | 1089 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
1090 __ movl(result, Address(result, | 1090 __ movl(result, Address(result, |
1091 char_code, | 1091 char_code, |
1092 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 1092 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
1093 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 1093 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
1094 } | 1094 } |
1095 | 1095 |
1096 | 1096 |
| 1097 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { |
| 1098 const intptr_t kNumInputs = 1; |
| 1099 const intptr_t kNumTemps = 0; |
| 1100 LocationSummary* locs = |
| 1101 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1102 locs->set_in(0, Location::RequiresRegister()); |
| 1103 locs->set_out(Location::RequiresRegister()); |
| 1104 return locs; |
| 1105 } |
| 1106 |
| 1107 |
| 1108 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1109 Register object = locs()->in(0).reg(); |
| 1110 Register result = locs()->out().reg(); |
| 1111 __ movl(result, FieldAddress(object, offset())); |
| 1112 } |
| 1113 |
| 1114 |
1097 CompileType LoadIndexedInstr::ComputeType() const { | 1115 CompileType LoadIndexedInstr::ComputeType() const { |
1098 switch (class_id_) { | 1116 switch (class_id_) { |
1099 case kArrayCid: | 1117 case kArrayCid: |
1100 case kImmutableArrayCid: | 1118 case kImmutableArrayCid: |
1101 return CompileType::Dynamic(); | 1119 return CompileType::Dynamic(); |
1102 | 1120 |
1103 case kFloat32ArrayCid : | |
1104 case kFloat64ArrayCid : | |
1105 case kTypedDataFloat32ArrayCid: | 1121 case kTypedDataFloat32ArrayCid: |
1106 case kTypedDataFloat64ArrayCid: | 1122 case kTypedDataFloat64ArrayCid: |
1107 return CompileType::FromCid(kDoubleCid); | 1123 return CompileType::FromCid(kDoubleCid); |
1108 | 1124 |
1109 case kInt8ArrayCid: | |
1110 case kUint8ArrayCid: | |
1111 case kUint8ClampedArrayCid: | |
1112 case kExternalUint8ArrayCid: | |
1113 case kExternalUint8ClampedArrayCid: | |
1114 case kInt16ArrayCid: | |
1115 case kUint16ArrayCid: | |
1116 case kTypedDataInt8ArrayCid: | 1125 case kTypedDataInt8ArrayCid: |
1117 case kTypedDataUint8ArrayCid: | 1126 case kTypedDataUint8ArrayCid: |
1118 case kTypedDataUint8ClampedArrayCid: | 1127 case kTypedDataUint8ClampedArrayCid: |
1119 case kExternalTypedDataUint8ArrayCid: | 1128 case kExternalTypedDataUint8ArrayCid: |
1120 case kExternalTypedDataUint8ClampedArrayCid: | 1129 case kExternalTypedDataUint8ClampedArrayCid: |
1121 case kTypedDataInt16ArrayCid: | 1130 case kTypedDataInt16ArrayCid: |
1122 case kTypedDataUint16ArrayCid: | 1131 case kTypedDataUint16ArrayCid: |
1123 case kOneByteStringCid: | 1132 case kOneByteStringCid: |
1124 case kTwoByteStringCid: | 1133 case kTwoByteStringCid: |
1125 return CompileType::FromCid(kSmiCid); | 1134 return CompileType::FromCid(kSmiCid); |
1126 | 1135 |
1127 case kInt32ArrayCid: | |
1128 case kUint32ArrayCid: | |
1129 case kTypedDataInt32ArrayCid: | 1136 case kTypedDataInt32ArrayCid: |
1130 case kTypedDataUint32ArrayCid: | 1137 case kTypedDataUint32ArrayCid: |
1131 // Result can be Smi or Mint when boxed. | 1138 // Result can be Smi or Mint when boxed. |
1132 // Instruction can deoptimize if we optimistically assumed that the result | 1139 // Instruction can deoptimize if we optimistically assumed that the result |
1133 // fits into Smi. | 1140 // fits into Smi. |
1134 return CanDeoptimize() ? CompileType::FromCid(kSmiCid) | 1141 return CanDeoptimize() ? CompileType::FromCid(kSmiCid) |
1135 : CompileType::Int(); | 1142 : CompileType::Int(); |
1136 | 1143 |
1137 default: | 1144 default: |
1138 UNIMPLEMENTED(); | 1145 UNIMPLEMENTED(); |
1139 return CompileType::Dynamic(); | 1146 return CompileType::Dynamic(); |
1140 } | 1147 } |
1141 } | 1148 } |
1142 | 1149 |
1143 | 1150 |
1144 Representation LoadIndexedInstr::representation() const { | 1151 Representation LoadIndexedInstr::representation() const { |
1145 switch (class_id_) { | 1152 switch (class_id_) { |
1146 case kArrayCid: | 1153 case kArrayCid: |
1147 case kImmutableArrayCid: | 1154 case kImmutableArrayCid: |
1148 case kInt8ArrayCid: | |
1149 case kUint8ArrayCid: | |
1150 case kUint8ClampedArrayCid: | |
1151 case kExternalUint8ArrayCid: | |
1152 case kExternalUint8ClampedArrayCid: | |
1153 case kInt16ArrayCid: | |
1154 case kUint16ArrayCid: | |
1155 case kTypedDataInt8ArrayCid: | 1155 case kTypedDataInt8ArrayCid: |
1156 case kTypedDataUint8ArrayCid: | 1156 case kTypedDataUint8ArrayCid: |
1157 case kTypedDataUint8ClampedArrayCid: | 1157 case kTypedDataUint8ClampedArrayCid: |
1158 case kExternalTypedDataUint8ArrayCid: | 1158 case kExternalTypedDataUint8ArrayCid: |
1159 case kExternalTypedDataUint8ClampedArrayCid: | 1159 case kExternalTypedDataUint8ClampedArrayCid: |
1160 case kTypedDataInt16ArrayCid: | 1160 case kTypedDataInt16ArrayCid: |
1161 case kTypedDataUint16ArrayCid: | 1161 case kTypedDataUint16ArrayCid: |
1162 case kOneByteStringCid: | 1162 case kOneByteStringCid: |
1163 case kTwoByteStringCid: | 1163 case kTwoByteStringCid: |
1164 return kTagged; | 1164 return kTagged; |
1165 case kInt32ArrayCid: | |
1166 case kUint32ArrayCid: | |
1167 case kTypedDataInt32ArrayCid: | 1165 case kTypedDataInt32ArrayCid: |
1168 case kTypedDataUint32ArrayCid: | 1166 case kTypedDataUint32ArrayCid: |
1169 // Instruction can deoptimize if we optimistically assumed that the result | 1167 // Instruction can deoptimize if we optimistically assumed that the result |
1170 // fits into Smi. | 1168 // fits into Smi. |
1171 return CanDeoptimize() ? kTagged : kUnboxedMint; | 1169 return CanDeoptimize() ? kTagged : kUnboxedMint; |
1172 case kFloat32ArrayCid : | |
1173 case kFloat64ArrayCid : | |
1174 case kTypedDataFloat32ArrayCid: | 1170 case kTypedDataFloat32ArrayCid: |
1175 case kTypedDataFloat64ArrayCid: | 1171 case kTypedDataFloat64ArrayCid: |
1176 return kUnboxedDouble; | 1172 return kUnboxedDouble; |
1177 default: | 1173 default: |
1178 UNIMPLEMENTED(); | 1174 UNIMPLEMENTED(); |
1179 return kTagged; | 1175 return kTagged; |
1180 } | 1176 } |
1181 } | 1177 } |
1182 | 1178 |
1183 | 1179 |
(...skipping 22 matching lines...) Expand all Loading... |
1206 locs->set_out(Location::RequiresRegister()); | 1202 locs->set_out(Location::RequiresRegister()); |
1207 } | 1203 } |
1208 return locs; | 1204 return locs; |
1209 } | 1205 } |
1210 | 1206 |
1211 | 1207 |
1212 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1208 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1213 Register array = locs()->in(0).reg(); | 1209 Register array = locs()->in(0).reg(); |
1214 Location index = locs()->in(1); | 1210 Location index = locs()->in(1); |
1215 | 1211 |
1216 if ((class_id() == kExternalUint8ArrayCid) || | 1212 Address element_address(kNoRegister, 0); |
1217 (class_id() == kExternalUint8ClampedArrayCid) || | 1213 if (IsExternal()) { |
1218 (class_id() == kExternalTypedDataUint8ArrayCid) || | 1214 element_address = index.IsRegister() |
1219 (class_id() == kExternalTypedDataUint8ClampedArrayCid)) { | |
1220 Register result = locs()->out().reg(); | |
1221 const Address& element_address = index.IsRegister() | |
1222 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1215 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1223 index_scale(), result, index.reg()) | 1216 index_scale(), array, index.reg()) |
1224 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1217 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1225 index_scale(), result, Smi::Cast(index.constant()).Value()); | 1218 index_scale(), array, Smi::Cast(index.constant()).Value()); |
1226 ASSERT(index_scale() == 1); | 1219 } else { |
1227 if (index.IsRegister()) { | 1220 ASSERT(this->array()->definition()->representation() == kTagged); |
1228 __ SmiUntag(index.reg()); | 1221 element_address = index.IsRegister() |
1229 } | 1222 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1230 __ movl(result, | 1223 class_id(), index_scale(), array, index.reg()) |
1231 FieldAddress(array, ExternalUint8Array::data_offset())); | 1224 : FlowGraphCompiler::ElementAddressForIntIndex( |
1232 __ movzxb(result, element_address); | 1225 class_id(), index_scale(), array, |
1233 __ SmiTag(result); | 1226 Smi::Cast(index.constant()).Value()); |
1234 return; | |
1235 } | 1227 } |
1236 | 1228 |
1237 FieldAddress element_address = index.IsRegister() | |
1238 ? FlowGraphCompiler::ElementAddressForRegIndex( | |
1239 class_id(), index_scale(), array, index.reg()) | |
1240 : FlowGraphCompiler::ElementAddressForIntIndex( | |
1241 class_id(), index_scale(), array, | |
1242 Smi::Cast(index.constant()).Value()); | |
1243 | |
1244 if ((representation() == kUnboxedDouble) || | 1229 if ((representation() == kUnboxedDouble) || |
1245 (representation() == kUnboxedMint)) { | 1230 (representation() == kUnboxedMint)) { |
1246 XmmRegister result = locs()->out().fpu_reg(); | 1231 XmmRegister result = locs()->out().fpu_reg(); |
1247 if ((index_scale() == 1) && index.IsRegister()) { | 1232 if ((index_scale() == 1) && index.IsRegister()) { |
1248 __ SmiUntag(index.reg()); | 1233 __ SmiUntag(index.reg()); |
1249 } | 1234 } |
1250 switch (class_id()) { | 1235 switch (class_id()) { |
1251 case kInt32ArrayCid: | |
1252 case kTypedDataInt32ArrayCid: | 1236 case kTypedDataInt32ArrayCid: |
1253 __ movss(result, element_address); | 1237 __ movss(result, element_address); |
1254 __ pmovsxdq(result, result); | 1238 __ pmovsxdq(result, result); |
1255 break; | 1239 break; |
1256 case kUint32ArrayCid: | |
1257 case kTypedDataUint32ArrayCid: | 1240 case kTypedDataUint32ArrayCid: |
1258 __ xorpd(result, result); | 1241 __ xorpd(result, result); |
1259 __ movss(result, element_address); | 1242 __ movss(result, element_address); |
1260 break; | 1243 break; |
1261 case kFloat32ArrayCid: | |
1262 case kTypedDataFloat32ArrayCid: | 1244 case kTypedDataFloat32ArrayCid: |
1263 // Load single precision float and promote to double. | 1245 // Load single precision float and promote to double. |
1264 __ movss(result, element_address); | 1246 __ movss(result, element_address); |
1265 __ cvtss2sd(result, locs()->out().fpu_reg()); | 1247 __ cvtss2sd(result, locs()->out().fpu_reg()); |
1266 break; | 1248 break; |
1267 case kFloat64ArrayCid: | |
1268 case kTypedDataFloat64ArrayCid: | 1249 case kTypedDataFloat64ArrayCid: |
1269 __ movsd(result, element_address); | 1250 __ movsd(result, element_address); |
1270 break; | 1251 break; |
1271 } | 1252 } |
1272 return; | 1253 return; |
1273 } | 1254 } |
1274 | 1255 |
1275 Register result = locs()->out().reg(); | 1256 Register result = locs()->out().reg(); |
1276 if ((index_scale() == 1) && index.IsRegister()) { | 1257 if ((index_scale() == 1) && index.IsRegister()) { |
1277 __ SmiUntag(index.reg()); | 1258 __ SmiUntag(index.reg()); |
1278 } | 1259 } |
1279 switch (class_id()) { | 1260 switch (class_id()) { |
1280 case kInt8ArrayCid: | |
1281 case kTypedDataInt8ArrayCid: | 1261 case kTypedDataInt8ArrayCid: |
1282 ASSERT(index_scale() == 1); | 1262 ASSERT(index_scale() == 1); |
1283 __ movsxb(result, element_address); | 1263 __ movsxb(result, element_address); |
1284 __ SmiTag(result); | 1264 __ SmiTag(result); |
1285 break; | 1265 break; |
1286 case kUint8ArrayCid: | |
1287 case kUint8ClampedArrayCid: | |
1288 case kTypedDataUint8ArrayCid: | 1266 case kTypedDataUint8ArrayCid: |
1289 case kTypedDataUint8ClampedArrayCid: | 1267 case kTypedDataUint8ClampedArrayCid: |
| 1268 case kExternalTypedDataUint8ArrayCid: |
| 1269 case kExternalTypedDataUint8ClampedArrayCid: |
1290 case kOneByteStringCid: | 1270 case kOneByteStringCid: |
1291 ASSERT(index_scale() == 1); | 1271 ASSERT(index_scale() == 1); |
1292 __ movzxb(result, element_address); | 1272 __ movzxb(result, element_address); |
1293 __ SmiTag(result); | 1273 __ SmiTag(result); |
1294 break; | 1274 break; |
1295 case kInt16ArrayCid: | |
1296 case kTypedDataInt16ArrayCid: | 1275 case kTypedDataInt16ArrayCid: |
1297 __ movsxw(result, element_address); | 1276 __ movsxw(result, element_address); |
1298 __ SmiTag(result); | 1277 __ SmiTag(result); |
1299 break; | 1278 break; |
1300 case kUint16ArrayCid: | |
1301 case kTypedDataUint16ArrayCid: | 1279 case kTypedDataUint16ArrayCid: |
1302 case kTwoByteStringCid: | 1280 case kTwoByteStringCid: |
1303 __ movzxw(result, element_address); | 1281 __ movzxw(result, element_address); |
1304 __ SmiTag(result); | 1282 __ SmiTag(result); |
1305 break; | 1283 break; |
1306 case kInt32ArrayCid: | |
1307 case kTypedDataInt32ArrayCid: { | 1284 case kTypedDataInt32ArrayCid: { |
1308 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load); | 1285 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load); |
1309 __ movl(result, element_address); | 1286 __ movl(result, element_address); |
1310 // Verify that the signed value in 'result' can fit inside a Smi. | 1287 // Verify that the signed value in 'result' can fit inside a Smi. |
1311 __ cmpl(result, Immediate(0xC0000000)); | 1288 __ cmpl(result, Immediate(0xC0000000)); |
1312 __ j(NEGATIVE, deopt); | 1289 __ j(NEGATIVE, deopt); |
1313 __ SmiTag(result); | 1290 __ SmiTag(result); |
1314 } | 1291 } |
1315 break; | 1292 break; |
1316 case kUint32ArrayCid: | |
1317 case kTypedDataUint32ArrayCid: { | 1293 case kTypedDataUint32ArrayCid: { |
1318 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); | 1294 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); |
1319 __ movl(result, element_address); | 1295 __ movl(result, element_address); |
1320 // Verify that the unsigned value in 'result' can fit inside a Smi. | 1296 // Verify that the unsigned value in 'result' can fit inside a Smi. |
1321 __ testl(result, Immediate(0xC0000000)); | 1297 __ testl(result, Immediate(0xC0000000)); |
1322 __ j(NOT_ZERO, deopt); | 1298 __ j(NOT_ZERO, deopt); |
1323 __ SmiTag(result); | 1299 __ SmiTag(result); |
1324 } | 1300 } |
1325 break; | 1301 break; |
1326 default: | 1302 default: |
1327 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1303 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
1328 __ movl(result, element_address); | 1304 __ movl(result, element_address); |
1329 break; | 1305 break; |
1330 } | 1306 } |
1331 } | 1307 } |
1332 | 1308 |
1333 | 1309 |
1334 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1310 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1335 intptr_t idx) const { | 1311 intptr_t idx) const { |
1336 if ((idx == 0) || (idx == 1)) return kTagged; | 1312 // Array can be a Dart object or a pointer to external data. |
| 1313 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1314 if (idx == 1) return kTagged; // Index is a smi. |
1337 ASSERT(idx == 2); | 1315 ASSERT(idx == 2); |
1338 switch (class_id_) { | 1316 switch (class_id_) { |
1339 case kArrayCid: | 1317 case kArrayCid: |
1340 case kInt8ArrayCid: | |
1341 case kUint8ArrayCid: | |
1342 case kExternalUint8ArrayCid: | |
1343 case kUint8ClampedArrayCid: | |
1344 case kExternalUint8ClampedArrayCid: | |
1345 case kInt16ArrayCid: | |
1346 case kUint16ArrayCid: | |
1347 case kTypedDataInt8ArrayCid: | 1318 case kTypedDataInt8ArrayCid: |
1348 case kTypedDataUint8ArrayCid: | 1319 case kTypedDataUint8ArrayCid: |
1349 case kExternalTypedDataUint8ArrayCid: | 1320 case kExternalTypedDataUint8ArrayCid: |
1350 case kTypedDataUint8ClampedArrayCid: | 1321 case kTypedDataUint8ClampedArrayCid: |
1351 case kExternalTypedDataUint8ClampedArrayCid: | 1322 case kExternalTypedDataUint8ClampedArrayCid: |
1352 case kTypedDataInt16ArrayCid: | 1323 case kTypedDataInt16ArrayCid: |
1353 case kTypedDataUint16ArrayCid: | 1324 case kTypedDataUint16ArrayCid: |
1354 return kTagged; | 1325 return kTagged; |
1355 case kInt32ArrayCid: | |
1356 case kUint32ArrayCid: | |
1357 case kTypedDataInt32ArrayCid: | 1326 case kTypedDataInt32ArrayCid: |
1358 case kTypedDataUint32ArrayCid: | 1327 case kTypedDataUint32ArrayCid: |
1359 return value()->IsSmiValue() ? kTagged : kUnboxedMint; | 1328 return value()->IsSmiValue() ? kTagged : kUnboxedMint; |
1360 case kFloat32ArrayCid : | 1329 case kTypedDataFloat32ArrayCid: |
1361 case kFloat64ArrayCid : | 1330 case kTypedDataFloat64ArrayCid: |
1362 case kTypedDataFloat32ArrayCid : | |
1363 case kTypedDataFloat64ArrayCid : | |
1364 return kUnboxedDouble; | 1331 return kUnboxedDouble; |
1365 default: | 1332 default: |
1366 UNIMPLEMENTED(); | 1333 UNIMPLEMENTED(); |
1367 return kTagged; | 1334 return kTagged; |
1368 } | 1335 } |
1369 } | 1336 } |
1370 | 1337 |
1371 | 1338 |
1372 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1339 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
1373 const intptr_t kNumInputs = 3; | 1340 const intptr_t kNumInputs = 3; |
(...skipping 13 matching lines...) Expand all Loading... |
1387 ? Location::Constant( | 1354 ? Location::Constant( |
1388 index()->definition()->AsConstant()->value()) | 1355 index()->definition()->AsConstant()->value()) |
1389 : Location::RequiresRegister()); | 1356 : Location::RequiresRegister()); |
1390 } | 1357 } |
1391 switch (class_id()) { | 1358 switch (class_id()) { |
1392 case kArrayCid: | 1359 case kArrayCid: |
1393 locs->set_in(2, ShouldEmitStoreBarrier() | 1360 locs->set_in(2, ShouldEmitStoreBarrier() |
1394 ? Location::WritableRegister() | 1361 ? Location::WritableRegister() |
1395 : Location::RegisterOrConstant(value())); | 1362 : Location::RegisterOrConstant(value())); |
1396 break; | 1363 break; |
1397 case kExternalUint8ArrayCid: | |
1398 case kExternalUint8ClampedArrayCid: | |
1399 case kExternalTypedDataUint8ArrayCid: | 1364 case kExternalTypedDataUint8ArrayCid: |
1400 case kExternalTypedDataUint8ClampedArrayCid: | 1365 case kExternalTypedDataUint8ClampedArrayCid: |
1401 // Need temp register to load the external array's data array. | |
1402 locs->AddTemp(Location::RequiresRegister()); | |
1403 // Fall through. | |
1404 case kInt8ArrayCid: | |
1405 case kUint8ArrayCid: | |
1406 case kUint8ClampedArrayCid: | |
1407 case kTypedDataInt8ArrayCid: | 1366 case kTypedDataInt8ArrayCid: |
1408 case kTypedDataUint8ArrayCid: | 1367 case kTypedDataUint8ArrayCid: |
1409 case kTypedDataUint8ClampedArrayCid: | 1368 case kTypedDataUint8ClampedArrayCid: |
1410 // TODO(fschneider): Add location constraint for byte registers (EAX, | 1369 // TODO(fschneider): Add location constraint for byte registers (EAX, |
1411 // EBX, ECX, EDX) instead of using a fixed register. | 1370 // EBX, ECX, EDX) instead of using a fixed register. |
1412 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1371 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
1413 break; | 1372 break; |
1414 case kInt16ArrayCid: | |
1415 case kUint16ArrayCid: | |
1416 case kTypedDataInt16ArrayCid: | 1373 case kTypedDataInt16ArrayCid: |
1417 case kTypedDataUint16ArrayCid: | 1374 case kTypedDataUint16ArrayCid: |
1418 // Writable register because the value must be untagged before storing. | 1375 // Writable register because the value must be untagged before storing. |
1419 locs->set_in(2, Location::WritableRegister()); | 1376 locs->set_in(2, Location::WritableRegister()); |
1420 break; | 1377 break; |
1421 case kInt32ArrayCid: | |
1422 case kUint32ArrayCid: | |
1423 case kTypedDataInt32ArrayCid: | 1378 case kTypedDataInt32ArrayCid: |
1424 case kTypedDataUint32ArrayCid: | 1379 case kTypedDataUint32ArrayCid: |
1425 // Mints are stored in XMM registers. For smis, use a writable register | 1380 // Mints are stored in XMM registers. For smis, use a writable register |
1426 // because the value must be untagged before storing. | 1381 // because the value must be untagged before storing. |
1427 locs->set_in(2, value()->IsSmiValue() | 1382 locs->set_in(2, value()->IsSmiValue() |
1428 ? Location::WritableRegister() | 1383 ? Location::WritableRegister() |
1429 : Location::RequiresFpuRegister()); | 1384 : Location::RequiresFpuRegister()); |
1430 break; | 1385 break; |
1431 case kFloat32ArrayCid: | |
1432 case kTypedDataFloat32ArrayCid: | 1386 case kTypedDataFloat32ArrayCid: |
1433 // Need temp register for float-to-double conversion. | 1387 // Need temp register for float-to-double conversion. |
1434 locs->AddTemp(Location::RequiresFpuRegister()); | 1388 locs->AddTemp(Location::RequiresFpuRegister()); |
1435 // Fall through. | 1389 // Fall through. |
1436 case kFloat64ArrayCid: | |
1437 case kTypedDataFloat64ArrayCid: | 1390 case kTypedDataFloat64ArrayCid: |
1438 // TODO(srdjan): Support Float64 constants. | 1391 // TODO(srdjan): Support Float64 constants. |
1439 locs->set_in(2, Location::RequiresFpuRegister()); | 1392 locs->set_in(2, Location::RequiresFpuRegister()); |
1440 break; | 1393 break; |
1441 default: | 1394 default: |
1442 UNREACHABLE(); | 1395 UNREACHABLE(); |
1443 return NULL; | 1396 return NULL; |
1444 } | 1397 } |
1445 return locs; | 1398 return locs; |
1446 } | 1399 } |
1447 | 1400 |
1448 | 1401 |
1449 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1402 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1450 Register array = locs()->in(0).reg(); | 1403 Register array = locs()->in(0).reg(); |
1451 Location index = locs()->in(1); | 1404 Location index = locs()->in(1); |
1452 | 1405 |
1453 Address element_address(kNoRegister, 0); | 1406 Address element_address(kNoRegister, 0); |
1454 if ((class_id() == kExternalUint8ArrayCid) || | 1407 if (IsExternal()) { |
1455 (class_id() == kExternalUint8ClampedArrayCid) || | |
1456 (class_id() == kExternalTypedDataUint8ArrayCid) || | |
1457 (class_id() == kExternalTypedDataUint8ClampedArrayCid)) { | |
1458 Register temp = locs()->temp(0).reg(); | |
1459 element_address = index.IsRegister() | 1408 element_address = index.IsRegister() |
1460 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1409 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1461 index_scale(), temp, index.reg()) | 1410 index_scale(), array, index.reg()) |
1462 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1411 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1463 index_scale(), temp, Smi::Cast(index.constant()).Value()); | 1412 index_scale(), array, Smi::Cast(index.constant()).Value()); |
1464 __ movl(temp, | |
1465 FieldAddress(array, ExternalUint8Array::data_offset())); | |
1466 } else { | 1413 } else { |
| 1414 ASSERT(this->array()->definition()->representation() == kTagged); |
1467 element_address = index.IsRegister() | 1415 element_address = index.IsRegister() |
1468 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1416 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1469 class_id(), index_scale(), array, index.reg()) | 1417 class_id(), index_scale(), array, index.reg()) |
1470 : FlowGraphCompiler::ElementAddressForIntIndex( | 1418 : FlowGraphCompiler::ElementAddressForIntIndex( |
1471 class_id(), index_scale(), array, | 1419 class_id(), index_scale(), array, |
1472 Smi::Cast(index.constant()).Value()); | 1420 Smi::Cast(index.constant()).Value()); |
1473 } | 1421 } |
1474 | 1422 |
1475 if ((index_scale() == 1) && index.IsRegister()) { | 1423 if ((index_scale() == 1) && index.IsRegister()) { |
1476 __ SmiUntag(index.reg()); | 1424 __ SmiUntag(index.reg()); |
1477 } | 1425 } |
1478 switch (class_id()) { | 1426 switch (class_id()) { |
1479 case kArrayCid: | 1427 case kArrayCid: |
1480 if (ShouldEmitStoreBarrier()) { | 1428 if (ShouldEmitStoreBarrier()) { |
1481 Register value = locs()->in(2).reg(); | 1429 Register value = locs()->in(2).reg(); |
1482 __ StoreIntoObject(array, element_address, value); | 1430 __ StoreIntoObject(array, element_address, value); |
1483 } else if (locs()->in(2).IsConstant()) { | 1431 } else if (locs()->in(2).IsConstant()) { |
1484 const Object& constant = locs()->in(2).constant(); | 1432 const Object& constant = locs()->in(2).constant(); |
1485 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1433 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
1486 } else { | 1434 } else { |
1487 Register value = locs()->in(2).reg(); | 1435 Register value = locs()->in(2).reg(); |
1488 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1436 __ StoreIntoObjectNoBarrier(array, element_address, value); |
1489 } | 1437 } |
1490 break; | 1438 break; |
1491 case kInt8ArrayCid: | |
1492 case kUint8ArrayCid: | |
1493 case kExternalUint8ArrayCid: | |
1494 case kTypedDataInt8ArrayCid: | 1439 case kTypedDataInt8ArrayCid: |
1495 case kTypedDataUint8ArrayCid: | 1440 case kTypedDataUint8ArrayCid: |
1496 case kExternalTypedDataUint8ArrayCid: | 1441 case kExternalTypedDataUint8ArrayCid: |
1497 if (locs()->in(2).IsConstant()) { | 1442 if (locs()->in(2).IsConstant()) { |
1498 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1443 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1499 __ movb(element_address, | 1444 __ movb(element_address, |
1500 Immediate(static_cast<int8_t>(constant.Value()))); | 1445 Immediate(static_cast<int8_t>(constant.Value()))); |
1501 } else { | 1446 } else { |
1502 ASSERT(locs()->in(2).reg() == EAX); | 1447 ASSERT(locs()->in(2).reg() == EAX); |
1503 __ SmiUntag(EAX); | 1448 __ SmiUntag(EAX); |
1504 __ movb(element_address, AL); | 1449 __ movb(element_address, AL); |
1505 } | 1450 } |
1506 break; | 1451 break; |
1507 case kUint8ClampedArrayCid: | |
1508 case kExternalUint8ClampedArrayCid: | |
1509 case kTypedDataUint8ClampedArrayCid: | 1452 case kTypedDataUint8ClampedArrayCid: |
1510 case kExternalTypedDataUint8ClampedArrayCid: { | 1453 case kExternalTypedDataUint8ClampedArrayCid: { |
1511 if (locs()->in(2).IsConstant()) { | 1454 if (locs()->in(2).IsConstant()) { |
1512 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1455 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1513 intptr_t value = constant.Value(); | 1456 intptr_t value = constant.Value(); |
1514 // Clamp to 0x0 or 0xFF respectively. | 1457 // Clamp to 0x0 or 0xFF respectively. |
1515 if (value > 0xFF) { | 1458 if (value > 0xFF) { |
1516 value = 0xFF; | 1459 value = 0xFF; |
1517 } else if (value < 0) { | 1460 } else if (value < 0) { |
1518 value = 0; | 1461 value = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
1529 __ j(GREATER, &store_0xff); | 1472 __ j(GREATER, &store_0xff); |
1530 __ xorl(EAX, EAX); | 1473 __ xorl(EAX, EAX); |
1531 __ jmp(&store_value, Assembler::kNearJump); | 1474 __ jmp(&store_value, Assembler::kNearJump); |
1532 __ Bind(&store_0xff); | 1475 __ Bind(&store_0xff); |
1533 __ movl(EAX, Immediate(0xFF)); | 1476 __ movl(EAX, Immediate(0xFF)); |
1534 __ Bind(&store_value); | 1477 __ Bind(&store_value); |
1535 __ movb(element_address, AL); | 1478 __ movb(element_address, AL); |
1536 } | 1479 } |
1537 break; | 1480 break; |
1538 } | 1481 } |
1539 case kInt16ArrayCid: | |
1540 case kUint16ArrayCid: | |
1541 case kTypedDataInt16ArrayCid: | 1482 case kTypedDataInt16ArrayCid: |
1542 case kTypedDataUint16ArrayCid: { | 1483 case kTypedDataUint16ArrayCid: { |
1543 Register value = locs()->in(2).reg(); | 1484 Register value = locs()->in(2).reg(); |
1544 __ SmiUntag(value); | 1485 __ SmiUntag(value); |
1545 __ movw(element_address, value); | 1486 __ movw(element_address, value); |
1546 break; | 1487 break; |
1547 } | 1488 } |
1548 case kInt32ArrayCid: | |
1549 case kUint32ArrayCid: | |
1550 case kTypedDataInt32ArrayCid: | 1489 case kTypedDataInt32ArrayCid: |
1551 case kTypedDataUint32ArrayCid: | 1490 case kTypedDataUint32ArrayCid: |
1552 if (value()->IsSmiValue()) { | 1491 if (value()->IsSmiValue()) { |
1553 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1492 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1554 Register value = locs()->in(2).reg(); | 1493 Register value = locs()->in(2).reg(); |
1555 __ SmiUntag(value); | 1494 __ SmiUntag(value); |
1556 __ movl(element_address, value); | 1495 __ movl(element_address, value); |
1557 } else { | 1496 } else { |
1558 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1497 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1559 __ movss(element_address, locs()->in(2).fpu_reg()); | 1498 __ movss(element_address, locs()->in(2).fpu_reg()); |
1560 } | 1499 } |
1561 break; | 1500 break; |
1562 case kFloat32ArrayCid: | |
1563 case kTypedDataFloat32ArrayCid: | 1501 case kTypedDataFloat32ArrayCid: |
1564 // Convert to single precision. | 1502 // Convert to single precision. |
1565 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); | 1503 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
1566 // Store. | 1504 // Store. |
1567 __ movss(element_address, locs()->temp(0).fpu_reg()); | 1505 __ movss(element_address, locs()->temp(0).fpu_reg()); |
1568 break; | 1506 break; |
1569 case kFloat64ArrayCid: | |
1570 case kTypedDataFloat64ArrayCid: | 1507 case kTypedDataFloat64ArrayCid: |
1571 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1508 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1572 break; | 1509 break; |
1573 default: | 1510 default: |
1574 UNREACHABLE(); | 1511 UNREACHABLE(); |
1575 } | 1512 } |
1576 } | 1513 } |
1577 | 1514 |
1578 | 1515 |
1579 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1516 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 UNREACHABLE(); | 2739 UNREACHABLE(); |
2803 } | 2740 } |
2804 } | 2741 } |
2805 | 2742 |
2806 | 2743 |
2807 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { | 2744 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { |
2808 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 2745 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
2809 const intptr_t kNumTemps = 0; | 2746 const intptr_t kNumTemps = 0; |
2810 LocationSummary* result = | 2747 LocationSummary* result = |
2811 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 2748 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
2812 result->set_in(0, Location::FpuRegisterLocation(XMM1, Location::kDouble)); | 2749 result->set_in(0, Location::FpuRegisterLocation(XMM1, kUnboxedDouble)); |
2813 if (InputCount() == 2) { | 2750 if (InputCount() == 2) { |
2814 result->set_in(1, Location::FpuRegisterLocation(XMM2, Location::kDouble)); | 2751 result->set_in(1, Location::FpuRegisterLocation(XMM2, kUnboxedDouble)); |
2815 } | 2752 } |
2816 result->set_out(Location::FpuRegisterLocation(XMM1, Location::kDouble)); | 2753 result->set_out(Location::FpuRegisterLocation(XMM1, kUnboxedDouble)); |
2817 return result; | 2754 return result; |
2818 } | 2755 } |
2819 | 2756 |
2820 | 2757 |
2821 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2758 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2822 __ EnterFrame(0); | 2759 __ EnterFrame(0); |
2823 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 2760 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
2824 for (intptr_t i = 0; i < InputCount(); i++) { | 2761 for (intptr_t i = 0; i < InputCount(); i++) { |
2825 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 2762 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
2826 } | 2763 } |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3622 PcDescriptors::kOther, | 3559 PcDescriptors::kOther, |
3623 locs()); | 3560 locs()); |
3624 __ Drop(2); // Discard type arguments and receiver. | 3561 __ Drop(2); // Discard type arguments and receiver. |
3625 } | 3562 } |
3626 | 3563 |
3627 } // namespace dart | 3564 } // namespace dart |
3628 | 3565 |
3629 #undef __ | 3566 #undef __ |
3630 | 3567 |
3631 #endif // defined TARGET_ARCH_IA32 | 3568 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |