Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 11967012: Optimized loads/stores for scalar list: Uint8Clamped, Int8, Int16, Uint16. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 return Utils::IsInt(32, disp); 1065 return Utils::IsInt(32, disp);
1066 } 1066 }
1067 1067
1068 1068
1069 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { 1069 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const {
1070 const intptr_t kNumInputs = 2; 1070 const intptr_t kNumInputs = 2;
1071 const intptr_t kNumTemps = 0; 1071 const intptr_t kNumTemps = 0;
1072 LocationSummary* locs = 1072 LocationSummary* locs =
1073 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1073 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1074 locs->set_in(0, Location::RequiresRegister()); 1074 locs->set_in(0, Location::RequiresRegister());
1075 // The smi index is either untagged and tagged again at the end of the
1076 // operation (element size == 1), or it is left smi tagged (for all element
1077 // sizes > 1).
1075 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 1078 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
1076 ? Location::RegisterOrSmiConstant(index()) 1079 ? Location::RegisterOrSmiConstant(index())
1077 : Location::RequiresRegister()); 1080 : Location::RequiresRegister());
1078 locs->set_out(Location::RequiresRegister()); 1081 locs->set_out(Location::RequiresRegister());
1079 return locs; 1082 return locs;
1080 } 1083 }
1081 1084
1082 1085
1083 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1086 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1084 Register str = locs()->in(0).reg(); 1087 Register str = locs()->in(0).reg();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 Symbols::kNullCharCodeSymbolOffset * kWordSize)); 1137 Symbols::kNullCharCodeSymbolOffset * kWordSize));
1135 } 1138 }
1136 1139
1137 1140
1138 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { 1141 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
1139 const intptr_t kNumInputs = 2; 1142 const intptr_t kNumInputs = 2;
1140 const intptr_t kNumTemps = 0; 1143 const intptr_t kNumTemps = 0;
1141 LocationSummary* locs = 1144 LocationSummary* locs =
1142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1143 locs->set_in(0, Location::RequiresRegister()); 1146 locs->set_in(0, Location::RequiresRegister());
1147 // The smi index is either untagged and tagged again at the end of the
1148 // operation (element size == 1), or it is left smi tagged (for all element
1149 // sizes > 1).
1144 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 1150 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
1145 ? Location::RegisterOrSmiConstant(index()) 1151 ? Location::RegisterOrSmiConstant(index())
1146 : Location::RequiresRegister()); 1152 : Location::RequiresRegister());
1147 if (representation() == kUnboxedDouble) { 1153 if (representation() == kUnboxedDouble) {
1148 locs->set_out(Location::RequiresXmmRegister()); 1154 locs->set_out(Location::RequiresXmmRegister());
1149 } else { 1155 } else {
1150 locs->set_out(Location::RequiresRegister()); 1156 locs->set_out(Location::RequiresRegister());
1151 } 1157 }
1152 return locs; 1158 return locs;
1153 } 1159 }
1154 1160
1155 1161
1156 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1162 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1157 Register array = locs()->in(0).reg(); 1163 Register array = locs()->in(0).reg();
1158 Location index = locs()->in(1); 1164 Location index = locs()->in(1);
1159 1165
1160 if (class_id() == kExternalUint8ArrayCid) { 1166 if (class_id() == kExternalUint8ArrayCid) {
1161 Register result = locs()->out().reg(); 1167 Register result = locs()->out().reg();
1162 Address element_address = index.IsRegister() 1168 Address element_address = index.IsRegister()
1163 ? Address(result, index.reg(), TIMES_1, 0) 1169 ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
1164 : Address(result, Smi::Cast(index.constant()).Value()); 1170 class_id(), result, index.reg())
1171 : FlowGraphCompiler::ExternalElementAddressForIntIndex(
1172 class_id(), result, Smi::Cast(index.constant()).Value());
1165 if (index.IsRegister()) { 1173 if (index.IsRegister()) {
1166 __ SmiUntag(index.reg()); 1174 __ SmiUntag(index.reg());
1167 } 1175 }
1168 __ movl(result, 1176 __ movl(result,
1169 FieldAddress(array, ExternalUint8Array::external_data_offset())); 1177 FieldAddress(array, ExternalUint8Array::external_data_offset()));
1170 __ movl(result, 1178 __ movl(result,
1171 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); 1179 Address(result, ExternalByteArrayData<uint8_t>::data_offset()));
1172 __ movzxb(result, element_address); 1180 __ movzxb(result, element_address);
1173 __ SmiTag(result); 1181 __ SmiTag(result);
1174 if (index.IsRegister()) { 1182 if (index.IsRegister()) {
1175 __ SmiTag(index.reg()); // Re-tag. 1183 __ SmiTag(index.reg()); // Re-tag.
1176 } 1184 }
1177 return; 1185 return;
1178 } 1186 }
1179 1187
1180 FieldAddress element_address = index.IsRegister() ? 1188 FieldAddress element_address = index.IsRegister()
1181 FlowGraphCompiler::ElementAddressForRegIndex( 1189 ? FlowGraphCompiler::ElementAddressForRegIndex(
1182 class_id(), array, index.reg()) : 1190 class_id(), array, index.reg())
1183 FlowGraphCompiler::ElementAddressForIntIndex( 1191 : FlowGraphCompiler::ElementAddressForIntIndex(
1184 class_id(), array, Smi::Cast(index.constant()).Value()); 1192 class_id(), array, Smi::Cast(index.constant()).Value());
1185 1193
1186 if (representation() == kUnboxedDouble) { 1194 if (representation() == kUnboxedDouble) {
1187 XmmRegister result = locs()->out().xmm_reg(); 1195 XmmRegister result = locs()->out().xmm_reg();
1188 if (class_id() == kFloat32ArrayCid) { 1196 if (class_id() == kFloat32ArrayCid) {
1189 // Load single precision float. 1197 // Load single precision float.
1190 __ movss(result, element_address); 1198 __ movss(result, element_address);
1191 // Promote to double. 1199 // Promote to double.
1192 __ cvtss2sd(result, locs()->out().xmm_reg()); 1200 __ cvtss2sd(result, locs()->out().xmm_reg());
1193 } else { 1201 } else {
1194 ASSERT(class_id() == kFloat64ArrayCid); 1202 ASSERT(class_id() == kFloat64ArrayCid);
1195 __ movsd(result, element_address); 1203 __ movsd(result, element_address);
1196 } 1204 }
1197 return; 1205 return;
1198 } 1206 }
1199 1207
1200 Register result = locs()->out().reg(); 1208 Register result = locs()->out().reg();
1201 if ((class_id() == kUint8ArrayCid) || 1209 switch (class_id()) {
1202 (class_id() == kUint8ClampedArrayCid)) { 1210 case kInt8ArrayCid:
1203 if (index.IsRegister()) { 1211 case kUint8ArrayCid:
1204 __ SmiUntag(index.reg()); 1212 case kUint8ClampedArrayCid:
1205 } 1213 if (index.IsRegister()) {
1206 __ movzxb(result, element_address); 1214 __ SmiUntag(index.reg());
1207 __ SmiTag(result); 1215 }
1208 if (index.IsRegister()) { 1216 if (class_id() == kInt8ArrayCid) {
1209 __ SmiTag(index.reg()); // Re-tag. 1217 __ movsxb(result, element_address);
1210 } 1218 } else {
1211 return; 1219 __ movzxb(result, element_address);
1220 }
1221 __ SmiTag(result);
1222 if (index.IsRegister()) {
1223 __ SmiTag(index.reg()); // Re-tag.
1224 }
1225 break;
1226 case kInt16ArrayCid:
1227 __ movsxw(result, element_address);
1228 __ SmiTag(result);
1229 break;
1230 case kUint16ArrayCid:
1231 __ movzxw(result, element_address);
1232 __ SmiTag(result);
1233 break;
1234 default:
1235 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1236 __ movl(result, element_address);
1237 break;
1212 } 1238 }
1213
1214 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid));
1215 __ movl(result, element_address);
1216 } 1239 }
1217 1240
1218 1241
1219 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { 1242 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
1220 const intptr_t kNumInputs = 3; 1243 const intptr_t kNumInputs = 3;
1221 const intptr_t kNumTemps = 0; 1244 const intptr_t kNumTemps = 0;
1222 LocationSummary* locs = 1245 LocationSummary* locs =
1223 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1246 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1224 locs->set_in(0, Location::RequiresRegister()); 1247 locs->set_in(0, Location::RequiresRegister());
1248 // The smi index is either untagged and tagged again at the end of the
1249 // operation (element size == 1), or it is left smi tagged (for all element
1250 // sizes > 1).
1225 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) 1251 locs->set_in(1, CanBeImmediateIndex(index(), class_id())
1226 ? Location::RegisterOrSmiConstant(index()) 1252 ? Location::RegisterOrSmiConstant(index())
1227 : Location::RequiresRegister()); 1253 : Location::RequiresRegister());
1228 switch (class_id()) { 1254 switch (class_id()) {
1229 case kArrayCid: 1255 case kArrayCid:
1230 locs->set_in(2, ShouldEmitStoreBarrier() 1256 locs->set_in(2, ShouldEmitStoreBarrier()
1231 ? Location::WritableRegister() 1257 ? Location::WritableRegister()
1232 : Location::RegisterOrConstant(value())); 1258 : Location::RegisterOrConstant(value()));
1233 break; 1259 break;
1260 case kInt8ArrayCid:
1234 case kUint8ArrayCid: 1261 case kUint8ArrayCid:
1262 case kUint8ClampedArrayCid:
1235 // TODO(fschneider): Add location constraint for byte registers (EAX, 1263 // TODO(fschneider): Add location constraint for byte registers (EAX,
1236 // EBX, ECX, EDX) instead of using a fixed register. 1264 // EBX, ECX, EDX) instead of using a fixed register.
1237 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); 1265 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
1238 break; 1266 break;
1267 case kInt16ArrayCid:
1268 case kUint16ArrayCid:
1269 // Writable register because the value must be untagged before storing.
1270 locs->set_in(2, Location::WritableRegister());
1271 break;
1239 case kFloat32ArrayCid: 1272 case kFloat32ArrayCid:
1240 // Need temp register for float-to-double conversion. 1273 // Need temp register for float-to-double conversion.
1241 locs->AddTemp(Location::RequiresXmmRegister()); 1274 locs->AddTemp(Location::RequiresXmmRegister());
1242 // Fall through. 1275 // Fall through.
1243 case kFloat64ArrayCid: 1276 case kFloat64ArrayCid:
1244 // TODO(srdjan): Support Float64 constants. 1277 // TODO(srdjan): Support Float64 constants.
1245 locs->set_in(2, Location::RequiresXmmRegister()); 1278 locs->set_in(2, Location::RequiresXmmRegister());
1246 break; 1279 break;
1247 default: 1280 default:
1248 UNREACHABLE(); 1281 UNREACHABLE();
(...skipping 19 matching lines...) Expand all
1268 Register value = locs()->in(2).reg(); 1301 Register value = locs()->in(2).reg();
1269 __ StoreIntoObject(array, element_address, value); 1302 __ StoreIntoObject(array, element_address, value);
1270 } else if (locs()->in(2).IsConstant()) { 1303 } else if (locs()->in(2).IsConstant()) {
1271 const Object& constant = locs()->in(2).constant(); 1304 const Object& constant = locs()->in(2).constant();
1272 __ StoreIntoObjectNoBarrier(array, element_address, constant); 1305 __ StoreIntoObjectNoBarrier(array, element_address, constant);
1273 } else { 1306 } else {
1274 Register value = locs()->in(2).reg(); 1307 Register value = locs()->in(2).reg();
1275 __ StoreIntoObjectNoBarrier(array, element_address, value); 1308 __ StoreIntoObjectNoBarrier(array, element_address, value);
1276 } 1309 }
1277 break; 1310 break;
1311 case kInt8ArrayCid:
1278 case kUint8ArrayCid: 1312 case kUint8ArrayCid:
1279 if (index.IsRegister()) { 1313 if (index.IsRegister()) {
1280 __ SmiUntag(index.reg()); 1314 __ SmiUntag(index.reg());
1281 } 1315 }
1282 if (locs()->in(2).IsConstant()) { 1316 if (locs()->in(2).IsConstant()) {
1283 const Smi& constant = Smi::Cast(locs()->in(2).constant()); 1317 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1284 __ movb(element_address, 1318 __ movb(element_address,
1285 Immediate(static_cast<int8_t>(constant.Value()))); 1319 Immediate(static_cast<int8_t>(constant.Value())));
1286 } else { 1320 } else {
1287 ASSERT(locs()->in(2).reg() == EAX); 1321 ASSERT(locs()->in(2).reg() == EAX);
1288 __ SmiUntag(EAX); 1322 __ SmiUntag(EAX);
1289 __ movb(element_address, AL); 1323 __ movb(element_address, AL);
1290 } 1324 }
1291 if (index.IsRegister()) { 1325 if (index.IsRegister()) {
1292 __ SmiTag(index.reg()); // Re-tag. 1326 __ SmiTag(index.reg()); // Re-tag.
1293 } 1327 }
1294 break; 1328 break;
1329 case kUint8ClampedArrayCid: {
1330 if (index.IsRegister()) {
1331 __ SmiUntag(index.reg());
1332 }
1333 if (locs()->in(2).IsConstant()) {
1334 const Smi& constant = Smi::Cast(locs()->in(2).constant());
1335 intptr_t value = constant.Value();
1336 // Clamp to 0x0 or 0xFF respectively.
1337 if (value > 0xFF) {
1338 value = 0xFF;
1339 } else if (value < 0) {
1340 value = 0;
1341 }
1342 __ movb(element_address,
1343 Immediate(static_cast<int8_t>(value)));
1344 } else {
1345 ASSERT(locs()->in(2).reg() == EAX);
1346 Label store_value, store_0xff;
1347 __ SmiUntag(EAX);
1348 __ cmpl(EAX, Immediate(0xFF));
1349 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
1350 // Clamp to 0x0 or 0xFF respectively.
1351 __ j(GREATER, &store_0xff);
1352 __ xorl(EAX, EAX);
1353 __ jmp(&store_value, Assembler::kNearJump);
1354 __ Bind(&store_0xff);
1355 __ movl(EAX, Immediate(0xFF));
1356 __ Bind(&store_value);
1357 __ movb(element_address, AL);
1358 }
1359 if (index.IsRegister()) {
1360 __ SmiTag(index.reg()); // Re-tag.
1361 }
1362 break;
1363 }
1364 case kInt16ArrayCid:
1365 case kUint16ArrayCid: {
1366 Register value = locs()->in(2).reg();
1367 __ SmiUntag(value);
1368 __ movw(element_address, value);
1369 break;
1370 }
1295 case kFloat32ArrayCid: 1371 case kFloat32ArrayCid:
1296 // Convert to single precision. 1372 // Convert to single precision.
1297 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); 1373 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg());
1298 // Store. 1374 // Store.
1299 __ movss(element_address, locs()->temp(0).xmm_reg()); 1375 __ movss(element_address, locs()->temp(0).xmm_reg());
1300 break; 1376 break;
1301 case kFloat64ArrayCid: 1377 case kFloat64ArrayCid:
1302 __ movsd(element_address, locs()->in(2).xmm_reg()); 1378 __ movsd(element_address, locs()->in(2).xmm_reg());
1303 break; 1379 break;
1304 default: 1380 default:
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1487 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1412 locs->set_in(0, Location::RegisterLocation(ECX)); 1488 locs->set_in(0, Location::RegisterLocation(ECX));
1413 locs->set_out(Location::RegisterLocation(EAX)); 1489 locs->set_out(Location::RegisterLocation(EAX));
1414 return locs; 1490 return locs;
1415 } 1491 }
1416 1492
1417 1493
1418 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1494 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1419 // Allocate the array. EDX = length, ECX = element type. 1495 // Allocate the array. EDX = length, ECX = element type.
1420 ASSERT(locs()->in(0).reg() == ECX); 1496 ASSERT(locs()->in(0).reg() == ECX);
1421 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); 1497 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount())));
1422 compiler->GenerateCall(token_pos(), 1498 compiler->GenerateCall(token_pos(),
1423 &StubCode::AllocateArrayLabel(), 1499 &StubCode::AllocateArrayLabel(),
1424 PcDescriptors::kOther, 1500 PcDescriptors::kOther,
1425 locs()); 1501 locs());
1426 ASSERT(locs()->out().reg() == EAX); 1502 ASSERT(locs()->out().reg() == EAX);
1427 1503
1428 // Pop the element values from the stack into the array. 1504 // Pop the element values from the stack into the array.
1429 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); 1505 __ leal(EDX, FieldAddress(EAX, Array::data_offset()));
1430 for (int i = ArgumentCount() - 1; i >= 0; --i) { 1506 for (int i = ArgumentCount() - 1; i >= 0; --i) {
1431 __ popl(Address(EDX, i * kWordSize)); 1507 __ popl(Address(EDX, i * kWordSize));
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2860 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 2936 __ pcmpeqq(XMM0, XMM0); // Generate all 1's.
2861 __ pxor(value, XMM0); 2937 __ pxor(value, XMM0);
2862 } 2938 }
2863 2939
2864 2940
2865 } // namespace dart 2941 } // namespace dart
2866 2942
2867 #undef __ 2943 #undef __
2868 2944
2869 #endif // defined TARGET_ARCH_X64 2945 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698