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

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

Issue 252333002: Use GPRs for mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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
OLDNEW
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 "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 default: 216 default:
217 UNREACHABLE(); 217 UNREACHABLE();
218 return OVERFLOW; 218 return OVERFLOW;
219 } 219 }
220 } 220 }
221 221
222 222
223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
224 const intptr_t kNumInputs = 2; 224 const intptr_t kNumInputs = 2;
225 if (operation_cid() == kMintCid) { 225 if (operation_cid() == kMintCid) {
226 const intptr_t kNumTemps = 1; 226 const intptr_t kNumTemps = 0;
227 LocationSummary* locs = 227 LocationSummary* locs =
228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
229 locs->set_in(0, Location::RequiresFpuRegister()); 229 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
230 locs->set_in(1, Location::RequiresFpuRegister()); 230 Location::RequiresRegister()));
231 locs->set_temp(0, Location::RequiresRegister()); 231 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
232 Location::RequiresRegister()));
232 locs->set_out(0, Location::RequiresRegister()); 233 locs->set_out(0, Location::RequiresRegister());
233 return locs; 234 return locs;
234 } 235 }
235 if (operation_cid() == kDoubleCid) { 236 if (operation_cid() == kDoubleCid) {
236 const intptr_t kNumTemps = 0; 237 const intptr_t kNumTemps = 0;
237 LocationSummary* locs = 238 LocationSummary* locs =
238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 239 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
239 locs->set_in(0, Location::RequiresFpuRegister()); 240 locs->set_in(0, Location::RequiresFpuRegister());
240 locs->set_in(1, Location::RequiresFpuRegister()); 241 locs->set_in(1, Location::RequiresFpuRegister());
241 locs->set_out(0, Location::RequiresRegister()); 242 locs->set_out(0, Location::RequiresRegister());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 __ cmpl(left.reg(), right.ToStackSlotAddress()); 356 __ cmpl(left.reg(), right.ToStackSlotAddress());
356 } else { 357 } else {
357 __ cmpl(left.reg(), right.reg()); 358 __ cmpl(left.reg(), right.reg());
358 } 359 }
359 return true_condition; 360 return true_condition;
360 } 361 }
361 362
362 363
363 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 364 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
364 Label* overflow, 365 Label* overflow,
365 XmmRegister result, 366 Register result_lo,
367 Register result_hi,
366 Register tmp) { 368 Register tmp) {
367 // Compare upper half. 369 // Compare upper half.
368 Label check_lower; 370 Label check_lower;
369 __ pextrd(tmp, result, Immediate(1)); 371 __ movl(tmp, result_hi);
Florian Schneider 2014/04/30 18:55:46 I think tmp is not needed anymore here.
Cutch 2014/05/14 17:16:19 Done.
370 __ cmpl(tmp, Immediate(0x00200000)); 372 __ cmpl(tmp, Immediate(0x00200000));
371 __ j(GREATER, overflow); 373 __ j(GREATER, overflow);
372 __ j(NOT_EQUAL, &check_lower); 374 __ j(NOT_EQUAL, &check_lower);
373 375
374 __ pextrd(tmp, result, Immediate(0)); 376 __ movl(tmp, result_lo);
375 __ cmpl(tmp, Immediate(0)); 377 __ cmpl(tmp, Immediate(0));
376 __ j(ABOVE, overflow); 378 __ j(ABOVE, overflow);
377 379
378 __ Bind(&check_lower); 380 __ Bind(&check_lower);
379 __ pextrd(tmp, result, Immediate(1)); 381 __ movl(tmp, result_hi);
380 __ cmpl(tmp, Immediate(-0x00200000)); 382 __ cmpl(tmp, Immediate(-0x00200000));
381 __ j(LESS, overflow); 383 __ j(LESS, overflow);
382 // Anything in the lower part would make the number bigger than the lower 384 // Anything in the lower part would make the number bigger than the lower
383 // bound, so we are done. 385 // bound, so we are done.
384 } 386 }
385 387
386 388
387 static Condition TokenKindToMintCondition(Token::Kind kind) { 389 static Condition TokenKindToMintCondition(Token::Kind kind) {
388 switch (kind) { 390 switch (kind) {
389 case Token::kEQ: return EQUAL; 391 case Token::kEQ: return EQUAL;
390 case Token::kNE: return NOT_EQUAL; 392 case Token::kNE: return NOT_EQUAL;
391 case Token::kLT: return LESS; 393 case Token::kLT: return LESS;
392 case Token::kGT: return GREATER; 394 case Token::kGT: return GREATER;
393 case Token::kLTE: return LESS_EQUAL; 395 case Token::kLTE: return LESS_EQUAL;
394 case Token::kGTE: return GREATER_EQUAL; 396 case Token::kGTE: return GREATER_EQUAL;
395 default: 397 default:
396 UNREACHABLE(); 398 UNREACHABLE();
397 return OVERFLOW; 399 return OVERFLOW;
398 } 400 }
399 } 401 }
400 402
401 403
402 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 404 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
403 const LocationSummary& locs, 405 const LocationSummary& locs,
404 Token::Kind kind, 406 Token::Kind kind,
405 BranchLabels labels) { 407 BranchLabels labels) {
406 ASSERT(Token::IsEqualityOperator(kind)); 408 ASSERT(Token::IsEqualityOperator(kind));
407 XmmRegister left = locs.in(0).fpu_reg(); 409 PairLocation* left_pair = locs.in(0).AsPairLocation();
408 XmmRegister right = locs.in(1).fpu_reg(); 410 Register left1 = left_pair->At(0).reg();
409 Register temp = locs.temp(0).reg(); 411 Register left2 = left_pair->At(1).reg();
410 __ movaps(XMM0, left); 412 PairLocation* right_pair = locs.in(1).AsPairLocation();
411 __ pcmpeqq(XMM0, right); 413 Register right1 = right_pair->At(0).reg();
412 __ movd(temp, XMM0); 414 Register right2 = right_pair->At(1).reg();
413 415 Label done;
416 // Compare lower.
417 __ cmpl(left1, right1);
418 __ j(NOT_EQUAL, &done);
419 // Lower is equal, compare upper.
420 __ cmpl(left2, right2);
421 __ Bind(&done);
414 Condition true_condition = TokenKindToMintCondition(kind); 422 Condition true_condition = TokenKindToMintCondition(kind);
415 __ cmpl(temp, Immediate(-1));
416 return true_condition; 423 return true_condition;
417 } 424 }
418 425
419 426
420 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 427 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
421 const LocationSummary& locs, 428 const LocationSummary& locs,
422 Token::Kind kind, 429 Token::Kind kind,
423 BranchLabels labels) { 430 BranchLabels labels) {
424 XmmRegister left = locs.in(0).fpu_reg(); 431 PairLocation* left_pair = locs.in(0).AsPairLocation();
425 XmmRegister right = locs.in(1).fpu_reg(); 432 Register left1 = left_pair->At(0).reg();
426 Register left_tmp = locs.temp(0).reg(); 433 Register left2 = left_pair->At(1).reg();
427 Register right_tmp = locs.temp(1).reg(); 434 PairLocation* right_pair = locs.in(1).AsPairLocation();
435 Register right1 = right_pair->At(0).reg();
436 Register right2 = right_pair->At(1).reg();
428 437
429 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; 438 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
430 switch (kind) { 439 switch (kind) {
431 case Token::kLT: 440 case Token::kLT:
432 hi_cond = LESS; 441 hi_cond = LESS;
433 lo_cond = BELOW; 442 lo_cond = BELOW;
434 break; 443 break;
435 case Token::kGT: 444 case Token::kGT:
436 hi_cond = GREATER; 445 hi_cond = GREATER;
437 lo_cond = ABOVE; 446 lo_cond = ABOVE;
438 break; 447 break;
439 case Token::kLTE: 448 case Token::kLTE:
440 hi_cond = LESS; 449 hi_cond = LESS;
441 lo_cond = BELOW_EQUAL; 450 lo_cond = BELOW_EQUAL;
442 break; 451 break;
443 case Token::kGTE: 452 case Token::kGTE:
444 hi_cond = GREATER; 453 hi_cond = GREATER;
445 lo_cond = ABOVE_EQUAL; 454 lo_cond = ABOVE_EQUAL;
446 break; 455 break;
447 default: 456 default:
448 break; 457 break;
449 } 458 }
450 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); 459 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
451 Label is_true, is_false; 460 Label is_true, is_false;
452 // Compare upper halves first. 461 // Compare upper halves first.
453 __ pextrd(left_tmp, left, Immediate(1)); 462 __ cmpl(left2, right2);
454 __ pextrd(right_tmp, right, Immediate(1));
455 __ cmpl(left_tmp, right_tmp);
456 __ j(hi_cond, labels.true_label); 463 __ j(hi_cond, labels.true_label);
457 __ j(FlipCondition(hi_cond), labels.false_label); 464 __ j(FlipCondition(hi_cond), labels.false_label);
458 465
459 // If upper is equal, compare lower half. 466 // If upper is equal, compare lower half.
460 __ pextrd(left_tmp, left, Immediate(0)); 467 __ cmpl(left1, right1);
461 __ pextrd(right_tmp, right, Immediate(0));
462 __ cmpl(left_tmp, right_tmp);
463 return lo_cond; 468 return lo_cond;
464 } 469 }
465 470
466 471
467 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 472 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
468 switch (kind) { 473 switch (kind) {
469 case Token::kEQ: return EQUAL; 474 case Token::kEQ: return EQUAL;
470 case Token::kNE: return NOT_EQUAL; 475 case Token::kNE: return NOT_EQUAL;
471 case Token::kLT: return BELOW; 476 case Token::kLT: return BELOW;
472 case Token::kGT: return ABOVE; 477 case Token::kGT: return ABOVE;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 __ Bind(&is_true); 656 __ Bind(&is_true);
652 __ LoadObject(result_reg, Bool::True()); 657 __ LoadObject(result_reg, Bool::True());
653 __ Bind(&done); 658 __ Bind(&done);
654 } 659 }
655 660
656 661
657 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { 662 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
658 const intptr_t kNumInputs = 2; 663 const intptr_t kNumInputs = 2;
659 const intptr_t kNumTemps = 0; 664 const intptr_t kNumTemps = 0;
660 if (operation_cid() == kMintCid) { 665 if (operation_cid() == kMintCid) {
661 const intptr_t kNumTemps = 2; 666 const intptr_t kNumTemps = 0;
662 LocationSummary* locs = 667 LocationSummary* locs =
663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 668 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
664 locs->set_in(0, Location::RequiresFpuRegister()); 669 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
665 locs->set_in(1, Location::RequiresFpuRegister()); 670 Location::RequiresRegister()));
666 locs->set_temp(0, Location::RequiresRegister()); 671 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
667 locs->set_temp(1, Location::RequiresRegister()); 672 Location::RequiresRegister()));
668 locs->set_out(0, Location::RequiresRegister()); 673 locs->set_out(0, Location::RequiresRegister());
669 return locs; 674 return locs;
670 } 675 }
671 if (operation_cid() == kDoubleCid) { 676 if (operation_cid() == kDoubleCid) {
672 LocationSummary* summary = 677 LocationSummary* summary =
673 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 678 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
674 summary->set_in(0, Location::RequiresFpuRegister()); 679 summary->set_in(0, Location::RequiresFpuRegister());
675 summary->set_in(1, Location::RequiresFpuRegister()); 680 summary->set_in(1, Location::RequiresFpuRegister());
676 summary->set_out(0, Location::RequiresRegister()); 681 summary->set_out(0, Location::RequiresRegister());
677 return summary; 682 return summary;
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 // element sizes > 1). 988 // element sizes > 1).
984 locs->set_in(1, (index_scale() == 1) 989 locs->set_in(1, (index_scale() == 1)
985 ? Location::WritableRegister() 990 ? Location::WritableRegister()
986 : Location::RequiresRegister()); 991 : Location::RequiresRegister());
987 } 992 }
988 if ((representation() == kUnboxedDouble) || 993 if ((representation() == kUnboxedDouble) ||
989 (representation() == kUnboxedFloat32x4) || 994 (representation() == kUnboxedFloat32x4) ||
990 (representation() == kUnboxedInt32x4) || 995 (representation() == kUnboxedInt32x4) ||
991 (representation() == kUnboxedFloat64x2)) { 996 (representation() == kUnboxedFloat64x2)) {
992 locs->set_out(0, Location::RequiresFpuRegister()); 997 locs->set_out(0, Location::RequiresFpuRegister());
998 } else if (representation() == kUnboxedMint) {
999 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
1000 Location::RegisterLocation(EDX)));
993 } else { 1001 } else {
1002 ASSERT(representation() == kTagged);
994 locs->set_out(0, Location::RequiresRegister()); 1003 locs->set_out(0, Location::RequiresRegister());
995 } 1004 }
996 return locs; 1005 return locs;
997 } 1006 }
998 1007
999 1008
1000 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1009 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1001 Register array = locs()->in(0).reg(); 1010 Register array = locs()->in(0).reg();
1002 Location index = locs()->in(1); 1011 Location index = locs()->in(1);
1003 1012
1004 Address element_address(kNoRegister, 0); 1013 Address element_address(kNoRegister, 0);
1005 if (IsExternal()) { 1014 if (IsExternal()) {
1006 element_address = index.IsRegister() 1015 element_address = index.IsRegister()
1007 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( 1016 ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
1008 index_scale(), array, index.reg()) 1017 index_scale(), array, index.reg())
1009 : FlowGraphCompiler::ExternalElementAddressForIntIndex( 1018 : FlowGraphCompiler::ExternalElementAddressForIntIndex(
1010 index_scale(), array, Smi::Cast(index.constant()).Value()); 1019 index_scale(), array, Smi::Cast(index.constant()).Value());
1011 } else { 1020 } else {
1012 ASSERT(this->array()->definition()->representation() == kTagged); 1021 ASSERT(this->array()->definition()->representation() == kTagged);
1013 element_address = index.IsRegister() 1022 element_address = index.IsRegister()
1014 ? FlowGraphCompiler::ElementAddressForRegIndex( 1023 ? FlowGraphCompiler::ElementAddressForRegIndex(
1015 class_id(), index_scale(), array, index.reg()) 1024 class_id(), index_scale(), array, index.reg())
1016 : FlowGraphCompiler::ElementAddressForIntIndex( 1025 : FlowGraphCompiler::ElementAddressForIntIndex(
1017 class_id(), index_scale(), array, 1026 class_id(), index_scale(), array,
1018 Smi::Cast(index.constant()).Value()); 1027 Smi::Cast(index.constant()).Value());
1019 } 1028 }
1020 1029
1021 if ((representation() == kUnboxedDouble) || 1030 if ((representation() == kUnboxedDouble) ||
1022 (representation() == kUnboxedMint) ||
1023 (representation() == kUnboxedFloat32x4) || 1031 (representation() == kUnboxedFloat32x4) ||
1024 (representation() == kUnboxedInt32x4) || 1032 (representation() == kUnboxedInt32x4) ||
1025 (representation() == kUnboxedFloat64x2)) { 1033 (representation() == kUnboxedFloat64x2)) {
1026 XmmRegister result = locs()->out(0).fpu_reg(); 1034 XmmRegister result = locs()->out(0).fpu_reg();
1027 if ((index_scale() == 1) && index.IsRegister()) { 1035 if ((index_scale() == 1) && index.IsRegister()) {
1028 __ SmiUntag(index.reg()); 1036 __ SmiUntag(index.reg());
1029 } 1037 }
1030 switch (class_id()) { 1038 switch (class_id()) {
1031 case kTypedDataInt32ArrayCid:
1032 __ movss(result, element_address);
1033 __ pmovsxdq(result, result);
1034 break;
1035 case kTypedDataUint32ArrayCid:
1036 __ xorpd(result, result);
1037 __ movss(result, element_address);
1038 break;
1039 case kTypedDataFloat32ArrayCid: 1039 case kTypedDataFloat32ArrayCid:
1040 __ movss(result, element_address); 1040 __ movss(result, element_address);
1041 break; 1041 break;
1042 case kTypedDataFloat64ArrayCid: 1042 case kTypedDataFloat64ArrayCid:
1043 __ movsd(result, element_address); 1043 __ movsd(result, element_address);
1044 break; 1044 break;
1045 case kTypedDataInt32x4ArrayCid: 1045 case kTypedDataInt32x4ArrayCid:
1046 case kTypedDataFloat32x4ArrayCid: 1046 case kTypedDataFloat32x4ArrayCid:
1047 case kTypedDataFloat64x2ArrayCid: 1047 case kTypedDataFloat64x2ArrayCid:
1048 __ movups(result, element_address); 1048 __ movups(result, element_address);
1049 break; 1049 break;
1050 default:
1051 UNREACHABLE();
1050 } 1052 }
1051 return; 1053 return;
1052 } 1054 }
1053 1055
1056 if (representation() == kUnboxedMint) {
1057 ASSERT(locs()->out(0).IsPairLocation());
1058 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1059 Register result1 = result_pair->At(0).reg();
1060 Register result2 = result_pair->At(1).reg();
1061 ASSERT(result1 == EAX);
1062 ASSERT(result2 == EDX);
1063 if ((index_scale() == 1) && index.IsRegister()) {
1064 __ SmiUntag(index.reg());
1065 }
1066 switch (class_id()) {
1067 case kTypedDataInt32ArrayCid:
1068 __ movl(result1, element_address);
1069 __ cdq();
1070 break;
1071 case kTypedDataUint32ArrayCid:
1072 __ movl(result1, element_address);
1073 __ xorl(result2, result2);
1074 break;
1075 default:
1076 UNREACHABLE();
1077 }
1078 return;
1079 }
1080
1081 ASSERT(representation() == kTagged);
1082
1054 Register result = locs()->out(0).reg(); 1083 Register result = locs()->out(0).reg();
1055 if ((index_scale() == 1) && index.IsRegister()) { 1084 if ((index_scale() == 1) && index.IsRegister()) {
1056 __ SmiUntag(index.reg()); 1085 __ SmiUntag(index.reg());
1057 } 1086 }
1058 switch (class_id()) { 1087 switch (class_id()) {
1059 case kTypedDataInt8ArrayCid: 1088 case kTypedDataInt8ArrayCid:
1060 ASSERT(index_scale() == 1); 1089 ASSERT(index_scale() == 1);
1061 __ movsxb(result, element_address); 1090 __ movsxb(result, element_address);
1062 __ SmiTag(result); 1091 __ SmiTag(result);
1063 break; 1092 break;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 // EBX, ECX, EDX) instead of using a fixed register. 1204 // EBX, ECX, EDX) instead of using a fixed register.
1176 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); 1205 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
1177 break; 1206 break;
1178 case kTypedDataInt16ArrayCid: 1207 case kTypedDataInt16ArrayCid:
1179 case kTypedDataUint16ArrayCid: 1208 case kTypedDataUint16ArrayCid:
1180 // Writable register because the value must be untagged before storing. 1209 // Writable register because the value must be untagged before storing.
1181 locs->set_in(2, Location::WritableRegister()); 1210 locs->set_in(2, Location::WritableRegister());
1182 break; 1211 break;
1183 case kTypedDataInt32ArrayCid: 1212 case kTypedDataInt32ArrayCid:
1184 case kTypedDataUint32ArrayCid: 1213 case kTypedDataUint32ArrayCid:
1185 // Mints are stored in XMM registers. For smis, use a writable register 1214 // For smis, use a writable register because the value must be untagged
1186 // because the value must be untagged before storing. 1215 // before storing. Mints are stored in registers pairs.
1187 locs->set_in(2, value()->IsSmiValue() 1216 if (value()->IsSmiValue()) {
1188 ? Location::WritableRegister() 1217 locs->set_in(2, Location::WritableRegister());
1189 : Location::RequiresFpuRegister()); 1218 } else {
1219 // We only move the lower 32-bits so we don't care where the high bits
1220 // are located.
1221 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1222 Location::Any()));
1223 }
1190 break; 1224 break;
1191 case kTypedDataFloat32ArrayCid: 1225 case kTypedDataFloat32ArrayCid:
1192 case kTypedDataFloat64ArrayCid: 1226 case kTypedDataFloat64ArrayCid:
1193 // TODO(srdjan): Support Float64 constants. 1227 // TODO(srdjan): Support Float64 constants.
1194 locs->set_in(2, Location::RequiresFpuRegister()); 1228 locs->set_in(2, Location::RequiresFpuRegister());
1195 break; 1229 break;
1196 case kTypedDataInt32x4ArrayCid: 1230 case kTypedDataInt32x4ArrayCid:
1197 case kTypedDataFloat32x4ArrayCid: 1231 case kTypedDataFloat32x4ArrayCid:
1198 case kTypedDataFloat64x2ArrayCid: 1232 case kTypedDataFloat64x2ArrayCid:
1199 locs->set_in(2, Location::RequiresFpuRegister()); 1233 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 } 1330 }
1297 case kTypedDataInt32ArrayCid: 1331 case kTypedDataInt32ArrayCid:
1298 case kTypedDataUint32ArrayCid: 1332 case kTypedDataUint32ArrayCid:
1299 if (value()->IsSmiValue()) { 1333 if (value()->IsSmiValue()) {
1300 ASSERT(RequiredInputRepresentation(2) == kTagged); 1334 ASSERT(RequiredInputRepresentation(2) == kTagged);
1301 Register value = locs()->in(2).reg(); 1335 Register value = locs()->in(2).reg();
1302 __ SmiUntag(value); 1336 __ SmiUntag(value);
1303 __ movl(element_address, value); 1337 __ movl(element_address, value);
1304 } else { 1338 } else {
1305 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1339 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1306 __ movss(element_address, locs()->in(2).fpu_reg()); 1340 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1341 Register value1 = value_pair->At(0).reg();
1342 __ movl(element_address, value1);
1307 } 1343 }
1308 break; 1344 break;
1309 case kTypedDataFloat32ArrayCid: 1345 case kTypedDataFloat32ArrayCid:
1310 __ movss(element_address, locs()->in(2).fpu_reg()); 1346 __ movss(element_address, locs()->in(2).fpu_reg());
1311 break; 1347 break;
1312 case kTypedDataFloat64ArrayCid: 1348 case kTypedDataFloat64ArrayCid:
1313 __ movsd(element_address, locs()->in(2).fpu_reg()); 1349 __ movsd(element_address, locs()->in(2).fpu_reg());
1314 break; 1350 break;
1315 case kTypedDataInt32x4ArrayCid: 1351 case kTypedDataInt32x4ArrayCid:
1316 case kTypedDataFloat32x4ArrayCid: 1352 case kTypedDataFloat32x4ArrayCid:
(...skipping 4002 matching lines...) Expand 10 before | Expand all | Expand 10 after
5319 Register length = length_loc.reg(); 5355 Register length = length_loc.reg();
5320 Register index = index_loc.reg(); 5356 Register index = index_loc.reg();
5321 __ cmpl(index, length); 5357 __ cmpl(index, length);
5322 __ j(ABOVE_EQUAL, deopt); 5358 __ j(ABOVE_EQUAL, deopt);
5323 } 5359 }
5324 } 5360 }
5325 5361
5326 5362
5327 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5363 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5328 const intptr_t kNumInputs = 1; 5364 const intptr_t kNumInputs = 1;
5329 const intptr_t value_cid = value()->Type()->ToCid(); 5365 const intptr_t kNumTemps = 0;
5330 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid));
5331 const bool needs_writable_input = (value_cid == kSmiCid);
5332 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5333 LocationSummary* summary = 5366 LocationSummary* summary =
5334 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5367 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5335 summary->set_in(0, needs_writable_input 5368 summary->set_in(0, Location::RequiresRegister());
5336 ? Location::WritableRegister() 5369 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5337 : Location::RequiresRegister()); 5370 Location::RegisterLocation(EDX)));
5338 if (needs_temp) {
5339 summary->set_temp(0, Location::RequiresRegister());
5340 }
5341 summary->set_out(0, Location::RequiresFpuRegister());
5342 return summary; 5371 return summary;
5343 } 5372 }
5344 5373
5345 5374
5346 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5375 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5347 const intptr_t value_cid = value()->Type()->ToCid(); 5376 const intptr_t value_cid = value()->Type()->ToCid();
5348 const Register value = locs()->in(0).reg(); 5377 const Register value = locs()->in(0).reg();
5349 const XmmRegister result = locs()->out(0).fpu_reg(); 5378 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5379 Register result1 = result_pair->At(0).reg();
5380 Register result2 = result_pair->At(1).reg();
5381
5382 ASSERT(value != result1);
5383 ASSERT(value != result2);
5384 ASSERT(result1 == EAX);
5385 ASSERT(result2 == EDX);
5350 5386
5351 if (value_cid == kMintCid) { 5387 if (value_cid == kMintCid) {
5352 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5388 __ movl(result1, FieldAddress(value, Mint::value_offset()));
5389 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize));
5353 } else if (value_cid == kSmiCid) { 5390 } else if (value_cid == kSmiCid) {
5354 __ SmiUntag(value); // Untag input before conversion. 5391 __ movl(result1, value);
5355 __ movd(result, value); 5392 __ SmiUntag(result1);
5356 __ pmovsxdq(result, result); 5393 // Sign extend into result2.
5394 __ cdq();
5357 } else { 5395 } else {
5358 Register temp = locs()->temp(0).reg();
5359 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5396 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5360 ICData::kDeoptUnboxInteger); 5397 ICData::kDeoptUnboxInteger);
5361 Label is_smi, done; 5398 Label is_smi, done;
5362 __ testl(value, Immediate(kSmiTagMask)); 5399 __ testl(value, Immediate(kSmiTagMask));
5363 __ j(ZERO, &is_smi); 5400 __ j(ZERO, &is_smi);
5364 __ CompareClassId(value, kMintCid, temp); 5401 __ CompareClassId(value, kMintCid, result1);
5365 __ j(NOT_EQUAL, deopt); 5402 __ j(NOT_EQUAL, deopt);
5366 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5403 __ movl(result1, FieldAddress(value, Mint::value_offset()));
5404 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize));
5367 __ jmp(&done); 5405 __ jmp(&done);
5368 __ Bind(&is_smi); 5406 __ Bind(&is_smi);
5369 __ movl(temp, value); 5407 __ movl(result1, value);
5370 __ SmiUntag(temp); 5408 __ SmiUntag(result1);
5371 __ movd(result, temp); 5409 // Sign extend into result2.
5372 __ pmovsxdq(result, result); 5410 __ cdq();
5373 __ Bind(&done); 5411 __ Bind(&done);
5374 } 5412 }
5375 } 5413 }
5376 5414
5377 5415
5378 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5416 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5379 const intptr_t kNumInputs = 1; 5417 const intptr_t kNumInputs = 1;
5380 const intptr_t kNumTemps = 2; 5418 const intptr_t kNumTemps = 1;
5381 LocationSummary* summary = 5419 LocationSummary* summary =
5382 new LocationSummary(kNumInputs, 5420 new LocationSummary(kNumInputs,
5383 kNumTemps, 5421 kNumTemps,
5384 LocationSummary::kCallOnSlowPath); 5422 LocationSummary::kCallOnSlowPath);
5385 summary->set_in(0, Location::RequiresFpuRegister()); 5423 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX),
5386 summary->set_temp(0, Location::RegisterLocation(EAX)); 5424 Location::RegisterLocation(EDX)));
5387 summary->set_temp(1, Location::RegisterLocation(EDX)); 5425 summary->set_temp(0, Location::RequiresRegister());
5388 // TODO(fschneider): Save one temp by using result register as a temp.
5389 summary->set_out(0, Location::RequiresRegister()); 5426 summary->set_out(0, Location::RequiresRegister());
5390 return summary; 5427 return summary;
5391 } 5428 }
5392 5429
5393 5430
5394 class BoxIntegerSlowPath : public SlowPathCode { 5431 class BoxIntegerSlowPath : public SlowPathCode {
5395 public: 5432 public:
5396 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5433 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5397 : instruction_(instruction) { } 5434 : instruction_(instruction) { }
5398 5435
(...skipping 21 matching lines...) Expand all
5420 } 5457 }
5421 5458
5422 private: 5459 private:
5423 BoxIntegerInstr* instruction_; 5460 BoxIntegerInstr* instruction_;
5424 }; 5461 };
5425 5462
5426 5463
5427 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5464 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5428 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5465 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5429 compiler->AddSlowPathCode(slow_path); 5466 compiler->AddSlowPathCode(slow_path);
5467 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5468 Register value1 = value_pair->At(0).reg();
5469 Register value2 = value_pair->At(1).reg();
5470 Register out_reg = locs()->out(0).reg();
5430 5471
5431 Register out_reg = locs()->out(0).reg(); 5472 ASSERT(value1 == EAX);
5432 XmmRegister value = locs()->in(0).fpu_reg(); 5473 ASSERT(value2 == EDX);
5474
5475 // Copy value2 into out_reg as a temporary.
5476 // We modify value1 but restore it before using it.
5477 __ movl(out_reg, value2);
5433 5478
5434 // Unboxed operations produce smis or mint-sized values. 5479 // Unboxed operations produce smis or mint-sized values.
5435 // Check if value fits into a smi. 5480 // Check if value fits into a smi.
5436 Label not_smi, done; 5481 Label not_smi, done;
5437 __ pextrd(EDX, value, Immediate(1)); // Upper half. 5482
5438 __ pextrd(EAX, value, Immediate(0)); // Lower half.
5439 // 1. Compute (x + -kMinSmi) which has to be in the range 5483 // 1. Compute (x + -kMinSmi) which has to be in the range
5440 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. 5484 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
5441 __ addl(EAX, Immediate(0x40000000)); 5485 __ addl(value1, Immediate(0x40000000));
5442 __ adcl(EDX, Immediate(0)); 5486 __ adcl(out_reg, Immediate(0));
5443 // 2. Unsigned compare to -kMinSmi+kMaxSmi. 5487 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
5444 __ cmpl(EAX, Immediate(0x80000000)); 5488 __ cmpl(value1, Immediate(0x80000000));
5445 __ sbbl(EDX, Immediate(0)); 5489 __ sbbl(out_reg, Immediate(0));
5446 __ j(ABOVE_EQUAL, &not_smi); 5490 __ j(ABOVE_EQUAL, &not_smi);
5447 // 3. Restore lower half if result is a smi. 5491 // 3. Restore lower half if result is a smi.
5448 __ subl(EAX, Immediate(0x40000000)); 5492 __ subl(value1, Immediate(0x40000000));
5449 5493 __ movl(out_reg, value1);
5450 __ SmiTag(EAX); 5494 __ SmiTag(out_reg);
5451 __ movl(out_reg, EAX);
5452 __ jmp(&done); 5495 __ jmp(&done);
5453
5454 __ Bind(&not_smi); 5496 __ Bind(&not_smi);
5455 __ TryAllocate( 5497 __ TryAllocate(
5456 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5498 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5457 slow_path->entry_label(), 5499 slow_path->entry_label(),
5458 Assembler::kFarJump, 5500 Assembler::kFarJump,
5459 out_reg, 5501 out_reg,
5460 kNoRegister); 5502 kNoRegister);
5461 __ Bind(slow_path->exit_label()); 5503 __ Bind(slow_path->exit_label());
5462 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); 5504 // 3. Restore lower half of input before using it.
5505 __ subl(value1, Immediate(0x40000000));
5506 __ movl(FieldAddress(out_reg, Mint::value_offset()), value1);
5507 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value2);
5463 __ Bind(&done); 5508 __ Bind(&done);
5464 } 5509 }
5465 5510
5466 5511
5467 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5512 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5468 const intptr_t kNumInputs = 2; 5513 const intptr_t kNumInputs = 2;
5469 switch (op_kind()) { 5514 switch (op_kind()) {
5470 case Token::kBIT_AND: 5515 case Token::kBIT_AND:
5471 case Token::kBIT_OR: 5516 case Token::kBIT_OR:
5472 case Token::kBIT_XOR: { 5517 case Token::kBIT_XOR: {
5473 const intptr_t kNumTemps = 5518 const intptr_t kNumTemps = FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5474 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5475 LocationSummary* summary = 5519 LocationSummary* summary =
5476 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5520 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5477 summary->set_in(0, Location::RequiresFpuRegister()); 5521 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5478 summary->set_in(1, Location::RequiresFpuRegister()); 5522 Location::RequiresRegister()));
5523 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5524 Location::RequiresRegister()));
5479 if (FLAG_throw_on_javascript_int_overflow) { 5525 if (FLAG_throw_on_javascript_int_overflow) {
5480 summary->set_temp(0, Location::RequiresRegister()); 5526 summary->set_temp(0, Location::RequiresRegister());
5481 } 5527 }
5482 summary->set_out(0, Location::SameAsFirstInput()); 5528 summary->set_out(0, Location::SameAsFirstInput());
5483 return summary; 5529 return summary;
5484 } 5530 }
5485 case Token::kADD: 5531 case Token::kADD:
5486 case Token::kSUB: { 5532 case Token::kSUB: {
5487 const intptr_t kNumTemps = 2; 5533 const intptr_t kNumTemps = FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5488 LocationSummary* summary = 5534 LocationSummary* summary =
5489 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5535 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5490 summary->set_in(0, Location::RequiresFpuRegister()); 5536 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5491 summary->set_in(1, Location::RequiresFpuRegister()); 5537 Location::RequiresRegister()));
5492 summary->set_temp(0, Location::RequiresRegister()); 5538 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5493 summary->set_temp(1, Location::RequiresRegister()); 5539 Location::RequiresRegister()));
5494 summary->set_out(0, Location::SameAsFirstInput()); 5540 summary->set_out(0, Location::SameAsFirstInput());
5541 if (FLAG_throw_on_javascript_int_overflow) {
5542 summary->set_temp(0, Location::RequiresRegister());
Florian Schneider 2014/04/30 18:55:46 A temp may not be needed anymore with your new cod
Cutch 2014/05/14 17:16:19 Done.
5543 }
5495 return summary; 5544 return summary;
5496 } 5545 }
5497 default: 5546 default:
5498 UNREACHABLE(); 5547 UNREACHABLE();
5499 return NULL; 5548 return NULL;
5500 } 5549 }
5501 } 5550 }
5502 5551
5503 5552
5504 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5553 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5505 XmmRegister left = locs()->in(0).fpu_reg(); 5554 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5506 XmmRegister right = locs()->in(1).fpu_reg(); 5555 Register left1 = left_pair->At(0).reg();
5507 5556 Register left2 = left_pair->At(1).reg();
5508 ASSERT(locs()->out(0).fpu_reg() == left); 5557 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5558 Register right1 = right_pair->At(0).reg();
5559 Register right2 = right_pair->At(1).reg();
5560 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5561 Register out1 = out_pair->At(0).reg();
5562 Register out2 = out_pair->At(1).reg();
5563 ASSERT(out1 == left1);
5564 ASSERT(out2 == left2);
5509 5565
5510 Label* deopt = NULL; 5566 Label* deopt = NULL;
5511 if (FLAG_throw_on_javascript_int_overflow) { 5567 if (FLAG_throw_on_javascript_int_overflow) {
5512 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5568 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5513 } 5569 }
5514 switch (op_kind()) { 5570 switch (op_kind()) {
5515 case Token::kBIT_AND: __ andpd(left, right); break; 5571 case Token::kBIT_AND:
5516 case Token::kBIT_OR: __ orpd(left, right); break; 5572 __ andl(left1, right1);
5517 case Token::kBIT_XOR: __ xorpd(left, right); break; 5573 __ andl(left2, right2);
5574 break;
5575 case Token::kBIT_OR:
5576 __ orl(left1, right1);
5577 __ orl(left2, right2);
5578 break;
5579 case Token::kBIT_XOR:
5580 __ xorl(left1, right1);
5581 __ xorl(left2, right2);
5582 break;
5518 case Token::kADD: 5583 case Token::kADD:
5519 case Token::kSUB: { 5584 case Token::kSUB: {
5520 Register lo = locs()->temp(0).reg();
5521 Register hi = locs()->temp(1).reg();
5522 if (!FLAG_throw_on_javascript_int_overflow) { 5585 if (!FLAG_throw_on_javascript_int_overflow) {
5523 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5586 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5524 } 5587 }
5525
5526 Label done, overflow;
5527 __ pextrd(lo, right, Immediate(0)); // Lower half
5528 __ pextrd(hi, right, Immediate(1)); // Upper half
5529 __ subl(ESP, Immediate(2 * kWordSize));
5530 __ movq(Address(ESP, 0), left);
5531 if (op_kind() == Token::kADD) { 5588 if (op_kind() == Token::kADD) {
5532 __ addl(Address(ESP, 0), lo); 5589 __ addl(left1, right1);
5533 __ adcl(Address(ESP, 1 * kWordSize), hi); 5590 __ adcl(left2, right2);
5534 } else { 5591 } else {
5535 __ subl(Address(ESP, 0), lo); 5592 __ subl(left1, right1);
5536 __ sbbl(Address(ESP, 1 * kWordSize), hi); 5593 __ sbbl(left2, right2);
5537 } 5594 }
5538 __ j(OVERFLOW, &overflow); 5595 __ j(OVERFLOW, deopt);
5539 __ movq(left, Address(ESP, 0));
5540 __ addl(ESP, Immediate(2 * kWordSize));
5541 __ jmp(&done);
5542 __ Bind(&overflow);
5543 __ addl(ESP, Immediate(2 * kWordSize));
5544 __ jmp(deopt);
5545 __ Bind(&done);
5546 break; 5596 break;
5547 } 5597 }
5548 default: UNREACHABLE(); 5598 default: UNREACHABLE();
5549 } 5599 }
5550 if (FLAG_throw_on_javascript_int_overflow) { 5600 if (FLAG_throw_on_javascript_int_overflow) {
5551 Register tmp = locs()->temp(0).reg(); 5601 Register tmp = locs()->temp(0).reg();
5552 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); 5602 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp);
5553 } 5603 }
5554 } 5604 }
5555 5605
5556 5606
5557 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5607 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5558 const intptr_t kNumInputs = 2; 5608 const intptr_t kNumInputs = 2;
5559 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; 5609 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1;
5560 LocationSummary* summary = 5610 LocationSummary* summary =
5561 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5611 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5562 summary->set_in(0, Location::RequiresFpuRegister()); 5612 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5613 Location::RequiresRegister()));
5563 summary->set_in(1, Location::RegisterLocation(ECX)); 5614 summary->set_in(1, Location::RegisterLocation(ECX));
5564 summary->set_temp(0, Location::RequiresRegister()); 5615 summary->set_temp(0, Location::RequiresRegister());
5565 if (op_kind() == Token::kSHL) { 5616 if (op_kind() == Token::kSHL) {
5566 summary->set_temp(1, Location::RequiresRegister()); 5617 summary->set_temp(1, Location::RequiresRegister());
5567 } 5618 }
5568 summary->set_out(0, Location::SameAsFirstInput()); 5619 summary->set_out(0, Location::SameAsFirstInput());
5569 return summary; 5620 return summary;
5570 } 5621 }
5571 5622
5572 5623
5573 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5624 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5574 XmmRegister left = locs()->in(0).fpu_reg(); 5625 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5575 ASSERT(locs()->in(1).reg() == ECX); 5626 Register left1 = left_pair->At(0).reg();
5576 ASSERT(locs()->out(0).fpu_reg() == left); 5627 Register left2 = left_pair->At(1).reg();
5628 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5629 Register out1 = out_pair->At(0).reg();
5630 Register out2 = out_pair->At(1).reg();
5631 ASSERT(out1 == left1);
5632 ASSERT(out2 == left2);
5577 5633
5578 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5634 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5579 Label done; 5635 Label done;
5580 __ testl(ECX, ECX); 5636 __ testl(ECX, ECX);
5581 __ j(ZERO, &done); // Shift by 0 is a nop. 5637 __ j(ZERO, &done); // Shift by 0 is a nop.
5582 __ subl(ESP, Immediate(2 * kWordSize));
5583 __ movq(Address(ESP, 0), left);
5584 // Deoptimize if shift count is > 31. 5638 // Deoptimize if shift count is > 31.
5585 // sarl operation masks the count to 5 bits and 5639 // sarl operation masks the count to 5 bits and
5586 // shrd is undefined with count > operand size (32) 5640 // shrd is undefined with count > operand size (32)
5587 // TODO(fschneider): Support shift counts > 31 without deoptimization. 5641 // TODO(fschneider): Support shift counts > 31 without deoptimization.
5588 __ SmiUntag(ECX); 5642 __ SmiUntag(ECX);
5589 const Immediate& kCountLimit = Immediate(31); 5643 const Immediate& kCountLimit = Immediate(31);
5590 __ cmpl(ECX, kCountLimit); 5644 __ cmpl(ECX, kCountLimit);
5591 __ j(ABOVE, deopt); 5645 __ j(ABOVE, deopt);
5592 switch (op_kind()) { 5646 switch (op_kind()) {
5593 case Token::kSHR: { 5647 case Token::kSHR: {
5594 Register temp = locs()->temp(0).reg(); 5648 __ shrd(left1, left2); // Shift count in CL.
5595 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. 5649 __ sarl(left2, ECX); // Shift count in CL.
5596 __ shrd(Address(ESP, 0), temp); // Shift count in CL.
5597 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL.
5598 break; 5650 break;
5599 } 5651 }
5600 case Token::kSHL: { 5652 case Token::kSHL: {
5601 Register temp1 = locs()->temp(0).reg(); 5653 Register temp1 = locs()->temp(0).reg();
5602 Register temp2 = locs()->temp(1).reg(); 5654 Register temp2 = locs()->temp(1).reg();
5603 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. 5655 __ movl(temp1, left1); // Low 32 bits.
5604 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. 5656 __ movl(temp2, left2); // High 32 bits.
5605 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. 5657 __ shll(left1, ECX); // Shift count in CL.
5606 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. 5658 __ shld(left2, temp1); // Shift count in CL.
5607 // Check for overflow by shifting back the high 32 bits 5659 // Check for overflow by shifting back the high 32 bits
5608 // and comparing with the input. 5660 // and comparing with the input.
5609 __ movl(temp1, temp2); 5661 __ movl(temp1, temp2);
5610 __ movl(temp2, Address(ESP, 1 * kWordSize)); 5662 __ movl(temp2, left2);
5611 __ sarl(temp2, ECX); 5663 __ sarl(temp2, ECX);
5612 __ cmpl(temp1, temp2); 5664 __ cmpl(temp1, temp2);
5613 __ j(NOT_EQUAL, deopt); 5665 __ j(NOT_EQUAL, deopt);
5614 break; 5666 break;
5615 } 5667 }
5616 default: 5668 default:
5617 UNREACHABLE(); 5669 UNREACHABLE();
5618 break; 5670 break;
5619 } 5671 }
5620 __ movq(left, Address(ESP, 0));
5621 __ addl(ESP, Immediate(2 * kWordSize));
5622 __ Bind(&done); 5672 __ Bind(&done);
5623 if (FLAG_throw_on_javascript_int_overflow) { 5673 if (FLAG_throw_on_javascript_int_overflow) {
5624 Register tmp = locs()->temp(0).reg(); 5674 Register tmp = locs()->temp(0).reg();
5625 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); 5675 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp);
5626 } 5676 }
5627 } 5677 }
5628 5678
5629 5679
5630 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5680 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5631 const intptr_t kNumInputs = 1; 5681 const intptr_t kNumInputs = 1;
5632 const intptr_t kNumTemps = 5682 const intptr_t kNumTemps =
5633 FLAG_throw_on_javascript_int_overflow ? 1 : 0; 5683 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5634 LocationSummary* summary = 5684 LocationSummary* summary =
5635 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5685 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5636 summary->set_in(0, Location::RequiresFpuRegister()); 5686 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5687 Location::RequiresRegister()));
5637 summary->set_out(0, Location::SameAsFirstInput()); 5688 summary->set_out(0, Location::SameAsFirstInput());
5638 if (FLAG_throw_on_javascript_int_overflow) { 5689 if (FLAG_throw_on_javascript_int_overflow) {
5639 summary->set_temp(0, Location::RequiresRegister()); 5690 summary->set_temp(0, Location::RequiresRegister());
Florian Schneider 2014/04/30 18:55:46 temp not needed here anymore.
Cutch 2014/05/14 17:16:19 Done.
5640 } 5691 }
5641 return summary; 5692 return summary;
5642 } 5693 }
5643 5694
5644 5695
5645 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5696 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5646 ASSERT(op_kind() == Token::kBIT_NOT); 5697 ASSERT(op_kind() == Token::kBIT_NOT);
5647 XmmRegister value = locs()->in(0).fpu_reg(); 5698 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5648 ASSERT(value == locs()->out(0).fpu_reg()); 5699 Register left1 = left_pair->At(0).reg();
5700 Register left2 = left_pair->At(1).reg();
5701 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5702 Register out1 = out_pair->At(0).reg();
5703 Register out2 = out_pair->At(1).reg();
5704 ASSERT(out1 == left1);
5705 ASSERT(out2 == left2);
5706
5649 Label* deopt = NULL; 5707 Label* deopt = NULL;
5650 if (FLAG_throw_on_javascript_int_overflow) { 5708 if (FLAG_throw_on_javascript_int_overflow) {
5651 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 5709 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
5652 } 5710 }
5653 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 5711
5654 __ pxor(value, XMM0); 5712 __ notl(left1);
5713 __ notl(left2);
5714
5655 if (FLAG_throw_on_javascript_int_overflow) { 5715 if (FLAG_throw_on_javascript_int_overflow) {
5656 Register tmp = locs()->temp(0).reg(); 5716 Register tmp = locs()->temp(0).reg();
5657 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); 5717 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp);
5658 } 5718 }
5659 } 5719 }
5660 5720
5661 5721
5662 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5722 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5663 return new LocationSummary(0, 0, LocationSummary::kCall); 5723 return new LocationSummary(0, 0, LocationSummary::kCall);
5664 } 5724 }
5665 5725
5666 5726
5667 5727
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
5984 PcDescriptors::kOther, 6044 PcDescriptors::kOther,
5985 locs()); 6045 locs());
5986 __ Drop(ArgumentCount()); // Discard arguments. 6046 __ Drop(ArgumentCount()); // Discard arguments.
5987 } 6047 }
5988 6048
5989 } // namespace dart 6049 } // namespace dart
5990 6050
5991 #undef __ 6051 #undef __
5992 6052
5993 #endif // defined TARGET_ARCH_IA32 6053 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698