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_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::SameAsFirstInput()); | |
| 1104 return locs; | |
| 1105 } | |
| 1106 | |
| 1107 | |
| 1108 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1109 Register object = locs()->in(0).reg(); | |
| 1110 ASSERT(locs()->out().reg() == object); | |
| 1111 __ movl(object, 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 const bool is_external = |
| 1217 (class_id() == kExternalUint8ClampedArrayCid) || | 1213 (this->array()->definition()->representation() == kUntagged); |
| 1218 (class_id() == kExternalTypedDataUint8ArrayCid) || | 1214 Address element_address(kNoRegister, 0); |
| 1219 (class_id() == kExternalTypedDataUint8ClampedArrayCid)) { | 1215 if (is_external) { |
| 1220 Register result = locs()->out().reg(); | 1216 element_address = index.IsRegister() |
| 1221 const Address& element_address = index.IsRegister() | |
| 1222 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1217 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
| 1223 index_scale(), result, index.reg()) | 1218 index_scale(), array, index.reg()) |
| 1224 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1219 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
| 1225 index_scale(), result, Smi::Cast(index.constant()).Value()); | 1220 index_scale(), array, Smi::Cast(index.constant()).Value()); |
| 1226 ASSERT(index_scale() == 1); | 1221 } else { |
| 1227 if (index.IsRegister()) { | 1222 ASSERT(this->array()->definition()->representation() == kTagged); |
| 1228 __ SmiUntag(index.reg()); | 1223 element_address = index.IsRegister() |
| 1229 } | 1224 ? FlowGraphCompiler::ElementAddressForRegIndex( |
| 1230 __ movl(result, | 1225 class_id(), index_scale(), array, index.reg()) |
| 1231 FieldAddress(array, ExternalUint8Array::data_offset())); | 1226 : FlowGraphCompiler::ElementAddressForIntIndex( |
| 1232 __ movzxb(result, element_address); | 1227 class_id(), index_scale(), array, |
| 1233 __ SmiTag(result); | 1228 Smi::Cast(index.constant()).Value()); |
| 1234 return; | |
| 1235 } | 1229 } |
| 1236 | 1230 |
| 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) || | 1231 if ((representation() == kUnboxedDouble) || |
| 1245 (representation() == kUnboxedMint)) { | 1232 (representation() == kUnboxedMint)) { |
| 1246 XmmRegister result = locs()->out().fpu_reg(); | 1233 XmmRegister result = locs()->out().fpu_reg(); |
| 1247 if ((index_scale() == 1) && index.IsRegister()) { | 1234 if ((index_scale() == 1) && index.IsRegister()) { |
| 1248 __ SmiUntag(index.reg()); | 1235 __ SmiUntag(index.reg()); |
| 1249 } | 1236 } |
| 1250 switch (class_id()) { | 1237 switch (class_id()) { |
| 1251 case kInt32ArrayCid: | |
| 1252 case kTypedDataInt32ArrayCid: | 1238 case kTypedDataInt32ArrayCid: |
| 1253 __ movss(result, element_address); | 1239 __ movss(result, element_address); |
| 1254 __ pmovsxdq(result, result); | 1240 __ pmovsxdq(result, result); |
| 1255 break; | 1241 break; |
| 1256 case kUint32ArrayCid: | |
| 1257 case kTypedDataUint32ArrayCid: | 1242 case kTypedDataUint32ArrayCid: |
| 1258 __ xorpd(result, result); | 1243 __ xorpd(result, result); |
| 1259 __ movss(result, element_address); | 1244 __ movss(result, element_address); |
| 1260 break; | 1245 break; |
| 1261 case kFloat32ArrayCid: | |
| 1262 case kTypedDataFloat32ArrayCid: | 1246 case kTypedDataFloat32ArrayCid: |
| 1263 // Load single precision float and promote to double. | 1247 // Load single precision float and promote to double. |
| 1264 __ movss(result, element_address); | 1248 __ movss(result, element_address); |
| 1265 __ cvtss2sd(result, locs()->out().fpu_reg()); | 1249 __ cvtss2sd(result, locs()->out().fpu_reg()); |
| 1266 break; | 1250 break; |
| 1267 case kFloat64ArrayCid: | |
| 1268 case kTypedDataFloat64ArrayCid: | 1251 case kTypedDataFloat64ArrayCid: |
| 1269 __ movsd(result, element_address); | 1252 __ movsd(result, element_address); |
| 1270 break; | 1253 break; |
| 1271 } | 1254 } |
| 1272 return; | 1255 return; |
| 1273 } | 1256 } |
| 1274 | 1257 |
| 1275 Register result = locs()->out().reg(); | 1258 Register result = locs()->out().reg(); |
| 1276 if ((index_scale() == 1) && index.IsRegister()) { | 1259 if ((index_scale() == 1) && index.IsRegister()) { |
| 1277 __ SmiUntag(index.reg()); | 1260 __ SmiUntag(index.reg()); |
| 1278 } | 1261 } |
| 1279 switch (class_id()) { | 1262 switch (class_id()) { |
| 1280 case kInt8ArrayCid: | |
| 1281 case kTypedDataInt8ArrayCid: | 1263 case kTypedDataInt8ArrayCid: |
| 1282 ASSERT(index_scale() == 1); | 1264 ASSERT(index_scale() == 1); |
| 1283 __ movsxb(result, element_address); | 1265 __ movsxb(result, element_address); |
| 1284 __ SmiTag(result); | 1266 __ SmiTag(result); |
| 1285 break; | 1267 break; |
| 1286 case kUint8ArrayCid: | |
| 1287 case kUint8ClampedArrayCid: | |
| 1288 case kTypedDataUint8ArrayCid: | 1268 case kTypedDataUint8ArrayCid: |
| 1289 case kTypedDataUint8ClampedArrayCid: | 1269 case kTypedDataUint8ClampedArrayCid: |
| 1270 case kExternalTypedDataUint8ArrayCid: | |
| 1271 case kExternalTypedDataUint8ClampedArrayCid: | |
| 1290 case kOneByteStringCid: | 1272 case kOneByteStringCid: |
| 1291 ASSERT(index_scale() == 1); | 1273 ASSERT(index_scale() == 1); |
| 1292 __ movzxb(result, element_address); | 1274 __ movzxb(result, element_address); |
| 1293 __ SmiTag(result); | 1275 __ SmiTag(result); |
| 1294 break; | 1276 break; |
| 1295 case kInt16ArrayCid: | |
| 1296 case kTypedDataInt16ArrayCid: | 1277 case kTypedDataInt16ArrayCid: |
| 1297 __ movsxw(result, element_address); | 1278 __ movsxw(result, element_address); |
| 1298 __ SmiTag(result); | 1279 __ SmiTag(result); |
| 1299 break; | 1280 break; |
| 1300 case kUint16ArrayCid: | |
| 1301 case kTypedDataUint16ArrayCid: | 1281 case kTypedDataUint16ArrayCid: |
| 1302 case kTwoByteStringCid: | 1282 case kTwoByteStringCid: |
| 1303 __ movzxw(result, element_address); | 1283 __ movzxw(result, element_address); |
| 1304 __ SmiTag(result); | 1284 __ SmiTag(result); |
| 1305 break; | 1285 break; |
| 1306 case kInt32ArrayCid: | |
| 1307 case kTypedDataInt32ArrayCid: { | 1286 case kTypedDataInt32ArrayCid: { |
| 1308 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load); | 1287 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load); |
| 1309 __ movl(result, element_address); | 1288 __ movl(result, element_address); |
| 1310 // Verify that the signed value in 'result' can fit inside a Smi. | 1289 // Verify that the signed value in 'result' can fit inside a Smi. |
| 1311 __ cmpl(result, Immediate(0xC0000000)); | 1290 __ cmpl(result, Immediate(0xC0000000)); |
| 1312 __ j(NEGATIVE, deopt); | 1291 __ j(NEGATIVE, deopt); |
| 1313 __ SmiTag(result); | 1292 __ SmiTag(result); |
| 1314 } | 1293 } |
| 1315 break; | 1294 break; |
| 1316 case kUint32ArrayCid: | |
| 1317 case kTypedDataUint32ArrayCid: { | 1295 case kTypedDataUint32ArrayCid: { |
| 1318 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); | 1296 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); |
| 1319 __ movl(result, element_address); | 1297 __ movl(result, element_address); |
| 1320 // Verify that the unsigned value in 'result' can fit inside a Smi. | 1298 // Verify that the unsigned value in 'result' can fit inside a Smi. |
| 1321 __ testl(result, Immediate(0xC0000000)); | 1299 __ testl(result, Immediate(0xC0000000)); |
| 1322 __ j(NOT_ZERO, deopt); | 1300 __ j(NOT_ZERO, deopt); |
| 1323 __ SmiTag(result); | 1301 __ SmiTag(result); |
| 1324 } | 1302 } |
| 1325 break; | 1303 break; |
| 1326 default: | 1304 default: |
| 1327 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1305 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1328 __ movl(result, element_address); | 1306 __ movl(result, element_address); |
| 1329 break; | 1307 break; |
| 1330 } | 1308 } |
| 1331 } | 1309 } |
| 1332 | 1310 |
| 1333 | 1311 |
| 1334 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1312 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1335 intptr_t idx) const { | 1313 intptr_t idx) const { |
| 1336 if ((idx == 0) || (idx == 1)) return kTagged; | 1314 if (idx == 0) return kNoRepresentation; // Array can be tagged or untagged. |
|
Vyacheslav Egorov (Google)
2013/03/18 18:42:29
Comment is somewhat confusing. Array can be either
Florian Schneider
2013/03/19 11:48:57
Done.
| |
| 1315 if (idx == 1) return kTagged; // Index is a smi. | |
| 1337 ASSERT(idx == 2); | 1316 ASSERT(idx == 2); |
| 1338 switch (class_id_) { | 1317 switch (class_id_) { |
| 1339 case kArrayCid: | 1318 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: | 1319 case kTypedDataInt8ArrayCid: |
| 1348 case kTypedDataUint8ArrayCid: | 1320 case kTypedDataUint8ArrayCid: |
| 1349 case kExternalTypedDataUint8ArrayCid: | 1321 case kExternalTypedDataUint8ArrayCid: |
| 1350 case kTypedDataUint8ClampedArrayCid: | 1322 case kTypedDataUint8ClampedArrayCid: |
| 1351 case kExternalTypedDataUint8ClampedArrayCid: | 1323 case kExternalTypedDataUint8ClampedArrayCid: |
| 1352 case kTypedDataInt16ArrayCid: | 1324 case kTypedDataInt16ArrayCid: |
| 1353 case kTypedDataUint16ArrayCid: | 1325 case kTypedDataUint16ArrayCid: |
| 1354 return kTagged; | 1326 return kTagged; |
| 1355 case kInt32ArrayCid: | |
| 1356 case kUint32ArrayCid: | |
| 1357 case kTypedDataInt32ArrayCid: | 1327 case kTypedDataInt32ArrayCid: |
| 1358 case kTypedDataUint32ArrayCid: | 1328 case kTypedDataUint32ArrayCid: |
| 1359 return value()->IsSmiValue() ? kTagged : kUnboxedMint; | 1329 return value()->IsSmiValue() ? kTagged : kUnboxedMint; |
| 1360 case kFloat32ArrayCid : | 1330 case kTypedDataFloat32ArrayCid: |
| 1361 case kFloat64ArrayCid : | 1331 case kTypedDataFloat64ArrayCid: |
| 1362 case kTypedDataFloat32ArrayCid : | |
| 1363 case kTypedDataFloat64ArrayCid : | |
| 1364 return kUnboxedDouble; | 1332 return kUnboxedDouble; |
| 1365 default: | 1333 default: |
| 1366 UNIMPLEMENTED(); | 1334 UNIMPLEMENTED(); |
| 1367 return kTagged; | 1335 return kTagged; |
| 1368 } | 1336 } |
| 1369 } | 1337 } |
| 1370 | 1338 |
| 1371 | 1339 |
| 1372 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1340 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 1373 const intptr_t kNumInputs = 3; | 1341 const intptr_t kNumInputs = 3; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1387 ? Location::Constant( | 1355 ? Location::Constant( |
| 1388 index()->definition()->AsConstant()->value()) | 1356 index()->definition()->AsConstant()->value()) |
| 1389 : Location::RequiresRegister()); | 1357 : Location::RequiresRegister()); |
| 1390 } | 1358 } |
| 1391 switch (class_id()) { | 1359 switch (class_id()) { |
| 1392 case kArrayCid: | 1360 case kArrayCid: |
| 1393 locs->set_in(2, ShouldEmitStoreBarrier() | 1361 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1394 ? Location::WritableRegister() | 1362 ? Location::WritableRegister() |
| 1395 : Location::RegisterOrConstant(value())); | 1363 : Location::RegisterOrConstant(value())); |
| 1396 break; | 1364 break; |
| 1397 case kExternalUint8ArrayCid: | |
| 1398 case kExternalUint8ClampedArrayCid: | |
| 1399 case kExternalTypedDataUint8ArrayCid: | 1365 case kExternalTypedDataUint8ArrayCid: |
| 1400 case kExternalTypedDataUint8ClampedArrayCid: | 1366 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: | 1367 case kTypedDataInt8ArrayCid: |
| 1408 case kTypedDataUint8ArrayCid: | 1368 case kTypedDataUint8ArrayCid: |
| 1409 case kTypedDataUint8ClampedArrayCid: | 1369 case kTypedDataUint8ClampedArrayCid: |
| 1410 // TODO(fschneider): Add location constraint for byte registers (EAX, | 1370 // TODO(fschneider): Add location constraint for byte registers (EAX, |
| 1411 // EBX, ECX, EDX) instead of using a fixed register. | 1371 // EBX, ECX, EDX) instead of using a fixed register. |
| 1412 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1372 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
| 1413 break; | 1373 break; |
| 1414 case kInt16ArrayCid: | |
| 1415 case kUint16ArrayCid: | |
| 1416 case kTypedDataInt16ArrayCid: | 1374 case kTypedDataInt16ArrayCid: |
| 1417 case kTypedDataUint16ArrayCid: | 1375 case kTypedDataUint16ArrayCid: |
| 1418 // Writable register because the value must be untagged before storing. | 1376 // Writable register because the value must be untagged before storing. |
| 1419 locs->set_in(2, Location::WritableRegister()); | 1377 locs->set_in(2, Location::WritableRegister()); |
| 1420 break; | 1378 break; |
| 1421 case kInt32ArrayCid: | |
| 1422 case kUint32ArrayCid: | |
| 1423 case kTypedDataInt32ArrayCid: | 1379 case kTypedDataInt32ArrayCid: |
| 1424 case kTypedDataUint32ArrayCid: | 1380 case kTypedDataUint32ArrayCid: |
| 1425 // Mints are stored in XMM registers. For smis, use a writable register | 1381 // Mints are stored in XMM registers. For smis, use a writable register |
| 1426 // because the value must be untagged before storing. | 1382 // because the value must be untagged before storing. |
| 1427 locs->set_in(2, value()->IsSmiValue() | 1383 locs->set_in(2, value()->IsSmiValue() |
| 1428 ? Location::WritableRegister() | 1384 ? Location::WritableRegister() |
| 1429 : Location::RequiresFpuRegister()); | 1385 : Location::RequiresFpuRegister()); |
| 1430 break; | 1386 break; |
| 1431 case kFloat32ArrayCid: | |
| 1432 case kTypedDataFloat32ArrayCid: | 1387 case kTypedDataFloat32ArrayCid: |
| 1433 // Need temp register for float-to-double conversion. | 1388 // Need temp register for float-to-double conversion. |
| 1434 locs->AddTemp(Location::RequiresFpuRegister()); | 1389 locs->AddTemp(Location::RequiresFpuRegister()); |
| 1435 // Fall through. | 1390 // Fall through. |
| 1436 case kFloat64ArrayCid: | |
| 1437 case kTypedDataFloat64ArrayCid: | 1391 case kTypedDataFloat64ArrayCid: |
| 1438 // TODO(srdjan): Support Float64 constants. | 1392 // TODO(srdjan): Support Float64 constants. |
| 1439 locs->set_in(2, Location::RequiresFpuRegister()); | 1393 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1440 break; | 1394 break; |
| 1441 default: | 1395 default: |
| 1442 UNREACHABLE(); | 1396 UNREACHABLE(); |
| 1443 return NULL; | 1397 return NULL; |
| 1444 } | 1398 } |
| 1445 return locs; | 1399 return locs; |
| 1446 } | 1400 } |
| 1447 | 1401 |
| 1448 | 1402 |
| 1449 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1403 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1450 Register array = locs()->in(0).reg(); | 1404 Register array = locs()->in(0).reg(); |
| 1451 Location index = locs()->in(1); | 1405 Location index = locs()->in(1); |
| 1452 | 1406 |
| 1453 Address element_address(kNoRegister, 0); | 1407 Address element_address(kNoRegister, 0); |
| 1454 if ((class_id() == kExternalUint8ArrayCid) || | 1408 const bool is_external = |
|
Vyacheslav Egorov (Google)
2013/03/18 18:42:29
consider creating helper method {Store,Load}Indexe
Florian Schneider
2013/03/19 11:48:57
Done.
| |
| 1455 (class_id() == kExternalUint8ClampedArrayCid) || | 1409 (this->array()->definition()->representation() == kUntagged); |
| 1456 (class_id() == kExternalTypedDataUint8ArrayCid) || | 1410 if (is_external) { |
| 1457 (class_id() == kExternalTypedDataUint8ClampedArrayCid)) { | |
| 1458 Register temp = locs()->temp(0).reg(); | |
| 1459 element_address = index.IsRegister() | 1411 element_address = index.IsRegister() |
| 1460 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1412 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
| 1461 index_scale(), temp, index.reg()) | 1413 index_scale(), array, index.reg()) |
| 1462 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1414 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
| 1463 index_scale(), temp, Smi::Cast(index.constant()).Value()); | 1415 index_scale(), array, Smi::Cast(index.constant()).Value()); |
| 1464 __ movl(temp, | |
| 1465 FieldAddress(array, ExternalUint8Array::data_offset())); | |
| 1466 } else { | 1416 } else { |
| 1417 ASSERT(this->array()->definition()->representation() == kTagged); | |
| 1467 element_address = index.IsRegister() | 1418 element_address = index.IsRegister() |
| 1468 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1419 ? FlowGraphCompiler::ElementAddressForRegIndex( |
| 1469 class_id(), index_scale(), array, index.reg()) | 1420 class_id(), index_scale(), array, index.reg()) |
| 1470 : FlowGraphCompiler::ElementAddressForIntIndex( | 1421 : FlowGraphCompiler::ElementAddressForIntIndex( |
| 1471 class_id(), index_scale(), array, | 1422 class_id(), index_scale(), array, |
| 1472 Smi::Cast(index.constant()).Value()); | 1423 Smi::Cast(index.constant()).Value()); |
| 1473 } | 1424 } |
| 1474 | 1425 |
| 1475 if ((index_scale() == 1) && index.IsRegister()) { | 1426 if ((index_scale() == 1) && index.IsRegister()) { |
| 1476 __ SmiUntag(index.reg()); | 1427 __ SmiUntag(index.reg()); |
| 1477 } | 1428 } |
| 1478 switch (class_id()) { | 1429 switch (class_id()) { |
| 1479 case kArrayCid: | 1430 case kArrayCid: |
| 1480 if (ShouldEmitStoreBarrier()) { | 1431 if (ShouldEmitStoreBarrier()) { |
| 1481 Register value = locs()->in(2).reg(); | 1432 Register value = locs()->in(2).reg(); |
| 1482 __ StoreIntoObject(array, element_address, value); | 1433 __ StoreIntoObject(array, element_address, value); |
| 1483 } else if (locs()->in(2).IsConstant()) { | 1434 } else if (locs()->in(2).IsConstant()) { |
| 1484 const Object& constant = locs()->in(2).constant(); | 1435 const Object& constant = locs()->in(2).constant(); |
| 1485 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1436 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1486 } else { | 1437 } else { |
| 1487 Register value = locs()->in(2).reg(); | 1438 Register value = locs()->in(2).reg(); |
| 1488 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1439 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 1489 } | 1440 } |
| 1490 break; | 1441 break; |
| 1491 case kInt8ArrayCid: | |
| 1492 case kUint8ArrayCid: | |
| 1493 case kExternalUint8ArrayCid: | |
| 1494 case kTypedDataInt8ArrayCid: | 1442 case kTypedDataInt8ArrayCid: |
| 1495 case kTypedDataUint8ArrayCid: | 1443 case kTypedDataUint8ArrayCid: |
| 1496 case kExternalTypedDataUint8ArrayCid: | 1444 case kExternalTypedDataUint8ArrayCid: |
| 1497 if (locs()->in(2).IsConstant()) { | 1445 if (locs()->in(2).IsConstant()) { |
| 1498 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1446 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1499 __ movb(element_address, | 1447 __ movb(element_address, |
| 1500 Immediate(static_cast<int8_t>(constant.Value()))); | 1448 Immediate(static_cast<int8_t>(constant.Value()))); |
| 1501 } else { | 1449 } else { |
| 1502 ASSERT(locs()->in(2).reg() == EAX); | 1450 ASSERT(locs()->in(2).reg() == EAX); |
| 1503 __ SmiUntag(EAX); | 1451 __ SmiUntag(EAX); |
| 1504 __ movb(element_address, AL); | 1452 __ movb(element_address, AL); |
| 1505 } | 1453 } |
| 1506 break; | 1454 break; |
| 1507 case kUint8ClampedArrayCid: | |
| 1508 case kExternalUint8ClampedArrayCid: | |
| 1509 case kTypedDataUint8ClampedArrayCid: | 1455 case kTypedDataUint8ClampedArrayCid: |
| 1510 case kExternalTypedDataUint8ClampedArrayCid: { | 1456 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1511 if (locs()->in(2).IsConstant()) { | 1457 if (locs()->in(2).IsConstant()) { |
| 1512 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1458 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1513 intptr_t value = constant.Value(); | 1459 intptr_t value = constant.Value(); |
| 1514 // Clamp to 0x0 or 0xFF respectively. | 1460 // Clamp to 0x0 or 0xFF respectively. |
| 1515 if (value > 0xFF) { | 1461 if (value > 0xFF) { |
| 1516 value = 0xFF; | 1462 value = 0xFF; |
| 1517 } else if (value < 0) { | 1463 } else if (value < 0) { |
| 1518 value = 0; | 1464 value = 0; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1529 __ j(GREATER, &store_0xff); | 1475 __ j(GREATER, &store_0xff); |
| 1530 __ xorl(EAX, EAX); | 1476 __ xorl(EAX, EAX); |
| 1531 __ jmp(&store_value, Assembler::kNearJump); | 1477 __ jmp(&store_value, Assembler::kNearJump); |
| 1532 __ Bind(&store_0xff); | 1478 __ Bind(&store_0xff); |
| 1533 __ movl(EAX, Immediate(0xFF)); | 1479 __ movl(EAX, Immediate(0xFF)); |
| 1534 __ Bind(&store_value); | 1480 __ Bind(&store_value); |
| 1535 __ movb(element_address, AL); | 1481 __ movb(element_address, AL); |
| 1536 } | 1482 } |
| 1537 break; | 1483 break; |
| 1538 } | 1484 } |
| 1539 case kInt16ArrayCid: | |
| 1540 case kUint16ArrayCid: | |
| 1541 case kTypedDataInt16ArrayCid: | 1485 case kTypedDataInt16ArrayCid: |
| 1542 case kTypedDataUint16ArrayCid: { | 1486 case kTypedDataUint16ArrayCid: { |
| 1543 Register value = locs()->in(2).reg(); | 1487 Register value = locs()->in(2).reg(); |
| 1544 __ SmiUntag(value); | 1488 __ SmiUntag(value); |
| 1545 __ movw(element_address, value); | 1489 __ movw(element_address, value); |
| 1546 break; | 1490 break; |
| 1547 } | 1491 } |
| 1548 case kInt32ArrayCid: | |
| 1549 case kUint32ArrayCid: | |
| 1550 case kTypedDataInt32ArrayCid: | 1492 case kTypedDataInt32ArrayCid: |
| 1551 case kTypedDataUint32ArrayCid: | 1493 case kTypedDataUint32ArrayCid: |
| 1552 if (value()->IsSmiValue()) { | 1494 if (value()->IsSmiValue()) { |
| 1553 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1495 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1554 Register value = locs()->in(2).reg(); | 1496 Register value = locs()->in(2).reg(); |
| 1555 __ SmiUntag(value); | 1497 __ SmiUntag(value); |
| 1556 __ movl(element_address, value); | 1498 __ movl(element_address, value); |
| 1557 } else { | 1499 } else { |
| 1558 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1500 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
| 1559 __ movss(element_address, locs()->in(2).fpu_reg()); | 1501 __ movss(element_address, locs()->in(2).fpu_reg()); |
| 1560 } | 1502 } |
| 1561 break; | 1503 break; |
| 1562 case kFloat32ArrayCid: | |
| 1563 case kTypedDataFloat32ArrayCid: | 1504 case kTypedDataFloat32ArrayCid: |
| 1564 // Convert to single precision. | 1505 // Convert to single precision. |
| 1565 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); | 1506 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
| 1566 // Store. | 1507 // Store. |
| 1567 __ movss(element_address, locs()->temp(0).fpu_reg()); | 1508 __ movss(element_address, locs()->temp(0).fpu_reg()); |
| 1568 break; | 1509 break; |
| 1569 case kFloat64ArrayCid: | |
| 1570 case kTypedDataFloat64ArrayCid: | 1510 case kTypedDataFloat64ArrayCid: |
| 1571 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1511 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1572 break; | 1512 break; |
| 1573 default: | 1513 default: |
| 1574 UNREACHABLE(); | 1514 UNREACHABLE(); |
| 1575 } | 1515 } |
| 1576 } | 1516 } |
| 1577 | 1517 |
| 1578 | 1518 |
| 1579 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1519 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| (...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2802 UNREACHABLE(); | 2742 UNREACHABLE(); |
| 2803 } | 2743 } |
| 2804 } | 2744 } |
| 2805 | 2745 |
| 2806 | 2746 |
| 2807 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { | 2747 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const { |
| 2808 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 2748 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 2809 const intptr_t kNumTemps = 0; | 2749 const intptr_t kNumTemps = 0; |
| 2810 LocationSummary* result = | 2750 LocationSummary* result = |
| 2811 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 2751 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 2812 result->set_in(0, Location::FpuRegisterLocation(XMM1, Location::kDouble)); | 2752 result->set_in(0, Location::FpuRegisterLocation(XMM1, kUnboxedDouble)); |
| 2813 if (InputCount() == 2) { | 2753 if (InputCount() == 2) { |
| 2814 result->set_in(1, Location::FpuRegisterLocation(XMM2, Location::kDouble)); | 2754 result->set_in(1, Location::FpuRegisterLocation(XMM2, kUnboxedDouble)); |
| 2815 } | 2755 } |
| 2816 result->set_out(Location::FpuRegisterLocation(XMM1, Location::kDouble)); | 2756 result->set_out(Location::FpuRegisterLocation(XMM1, kUnboxedDouble)); |
| 2817 return result; | 2757 return result; |
| 2818 } | 2758 } |
| 2819 | 2759 |
| 2820 | 2760 |
| 2821 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2761 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2822 __ EnterFrame(0); | 2762 __ EnterFrame(0); |
| 2823 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 2763 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
| 2824 for (intptr_t i = 0; i < InputCount(); i++) { | 2764 for (intptr_t i = 0; i < InputCount(); i++) { |
| 2825 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 2765 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
| 2826 } | 2766 } |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3622 PcDescriptors::kOther, | 3562 PcDescriptors::kOther, |
| 3623 locs()); | 3563 locs()); |
| 3624 __ Drop(2); // Discard type arguments and receiver. | 3564 __ Drop(2); // Discard type arguments and receiver. |
| 3625 } | 3565 } |
| 3626 | 3566 |
| 3627 } // namespace dart | 3567 } // namespace dart |
| 3628 | 3568 |
| 3629 #undef __ | 3569 #undef __ |
| 3630 | 3570 |
| 3631 #endif // defined TARGET_ARCH_IA32 | 3571 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |