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

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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 default: 246 default:
247 UNREACHABLE(); 247 UNREACHABLE();
248 return OVERFLOW; 248 return OVERFLOW;
249 } 249 }
250 } 250 }
251 251
252 252
253 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 253 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
254 const intptr_t kNumInputs = 2; 254 const intptr_t kNumInputs = 2;
255 if (operation_cid() == kMintCid) { 255 if (operation_cid() == kMintCid) {
256 const intptr_t kNumTemps = 1; 256 const intptr_t kNumTemps = 0;
257 LocationSummary* locs = 257 LocationSummary* locs =
258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
259 locs->set_in(0, Location::RequiresFpuRegister()); 259 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
260 locs->set_in(1, Location::RequiresFpuRegister()); 260 Location::RequiresRegister()));
261 locs->set_temp(0, Location::RequiresRegister()); 261 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
262 Location::RequiresRegister()));
262 locs->set_out(0, Location::RequiresRegister()); 263 locs->set_out(0, Location::RequiresRegister());
263 return locs; 264 return locs;
264 } 265 }
265 if (operation_cid() == kDoubleCid) { 266 if (operation_cid() == kDoubleCid) {
266 const intptr_t kNumTemps = 0; 267 const intptr_t kNumTemps = 0;
267 LocationSummary* locs = 268 LocationSummary* locs =
268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 269 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
269 locs->set_in(0, Location::RequiresFpuRegister()); 270 locs->set_in(0, Location::RequiresFpuRegister());
270 locs->set_in(1, Location::RequiresFpuRegister()); 271 locs->set_in(1, Location::RequiresFpuRegister());
271 locs->set_out(0, Location::RequiresRegister()); 272 locs->set_out(0, Location::RequiresRegister());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 __ cmpl(left.reg(), right.ToStackSlotAddress()); 386 __ cmpl(left.reg(), right.ToStackSlotAddress());
386 } else { 387 } else {
387 __ cmpl(left.reg(), right.reg()); 388 __ cmpl(left.reg(), right.reg());
388 } 389 }
389 return true_condition; 390 return true_condition;
390 } 391 }
391 392
392 393
393 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 394 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
394 Label* overflow, 395 Label* overflow,
395 XmmRegister result, 396 Register result_lo,
396 Register tmp) { 397 Register result_hi) {
397 // Compare upper half. 398 // Compare upper half.
398 Label check_lower; 399 Label check_lower;
399 __ pextrd(tmp, result, Immediate(1)); 400 __ cmpl(result_hi, Immediate(0x00200000));
400 __ cmpl(tmp, Immediate(0x00200000));
401 __ j(GREATER, overflow); 401 __ j(GREATER, overflow);
402 __ j(NOT_EQUAL, &check_lower); 402 __ j(NOT_EQUAL, &check_lower);
403 403
404 __ pextrd(tmp, result, Immediate(0)); 404 __ cmpl(result_lo, Immediate(0));
405 __ cmpl(tmp, Immediate(0));
406 __ j(ABOVE, overflow); 405 __ j(ABOVE, overflow);
407 406
408 __ Bind(&check_lower); 407 __ Bind(&check_lower);
409 __ pextrd(tmp, result, Immediate(1)); 408 __ cmpl(result_hi, Immediate(-0x00200000));
410 __ cmpl(tmp, Immediate(-0x00200000));
411 __ j(LESS, overflow); 409 __ j(LESS, overflow);
412 // Anything in the lower part would make the number bigger than the lower 410 // Anything in the lower part would make the number bigger than the lower
413 // bound, so we are done. 411 // bound, so we are done.
414 } 412 }
415 413
416 414
417 static Condition TokenKindToMintCondition(Token::Kind kind) { 415 static Condition TokenKindToMintCondition(Token::Kind kind) {
418 switch (kind) { 416 switch (kind) {
419 case Token::kEQ: return EQUAL; 417 case Token::kEQ: return EQUAL;
420 case Token::kNE: return NOT_EQUAL; 418 case Token::kNE: return NOT_EQUAL;
421 case Token::kLT: return LESS; 419 case Token::kLT: return LESS;
422 case Token::kGT: return GREATER; 420 case Token::kGT: return GREATER;
423 case Token::kLTE: return LESS_EQUAL; 421 case Token::kLTE: return LESS_EQUAL;
424 case Token::kGTE: return GREATER_EQUAL; 422 case Token::kGTE: return GREATER_EQUAL;
425 default: 423 default:
426 UNREACHABLE(); 424 UNREACHABLE();
427 return OVERFLOW; 425 return OVERFLOW;
428 } 426 }
429 } 427 }
430 428
431 429
432 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 430 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
433 const LocationSummary& locs, 431 const LocationSummary& locs,
434 Token::Kind kind, 432 Token::Kind kind,
435 BranchLabels labels) { 433 BranchLabels labels) {
436 ASSERT(Token::IsEqualityOperator(kind)); 434 ASSERT(Token::IsEqualityOperator(kind));
437 XmmRegister left = locs.in(0).fpu_reg(); 435 PairLocation* left_pair = locs.in(0).AsPairLocation();
438 XmmRegister right = locs.in(1).fpu_reg(); 436 Register left1 = left_pair->At(0).reg();
439 Register temp = locs.temp(0).reg(); 437 Register left2 = left_pair->At(1).reg();
440 __ movaps(XMM0, left); 438 PairLocation* right_pair = locs.in(1).AsPairLocation();
441 __ pcmpeqq(XMM0, right); 439 Register right1 = right_pair->At(0).reg();
442 __ movd(temp, XMM0); 440 Register right2 = right_pair->At(1).reg();
443 441 Label done;
442 // Compare lower.
443 __ cmpl(left1, right1);
444 __ j(NOT_EQUAL, &done);
445 // Lower is equal, compare upper.
446 __ cmpl(left2, right2);
447 __ Bind(&done);
444 Condition true_condition = TokenKindToMintCondition(kind); 448 Condition true_condition = TokenKindToMintCondition(kind);
445 __ cmpl(temp, Immediate(-1));
446 return true_condition; 449 return true_condition;
447 } 450 }
448 451
449 452
450 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 453 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
451 const LocationSummary& locs, 454 const LocationSummary& locs,
452 Token::Kind kind, 455 Token::Kind kind,
453 BranchLabels labels) { 456 BranchLabels labels) {
454 XmmRegister left = locs.in(0).fpu_reg(); 457 PairLocation* left_pair = locs.in(0).AsPairLocation();
455 XmmRegister right = locs.in(1).fpu_reg(); 458 Register left1 = left_pair->At(0).reg();
456 Register left_tmp = locs.temp(0).reg(); 459 Register left2 = left_pair->At(1).reg();
457 Register right_tmp = locs.temp(1).reg(); 460 PairLocation* right_pair = locs.in(1).AsPairLocation();
461 Register right1 = right_pair->At(0).reg();
462 Register right2 = right_pair->At(1).reg();
458 463
459 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; 464 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
460 switch (kind) { 465 switch (kind) {
461 case Token::kLT: 466 case Token::kLT:
462 hi_cond = LESS; 467 hi_cond = LESS;
463 lo_cond = BELOW; 468 lo_cond = BELOW;
464 break; 469 break;
465 case Token::kGT: 470 case Token::kGT:
466 hi_cond = GREATER; 471 hi_cond = GREATER;
467 lo_cond = ABOVE; 472 lo_cond = ABOVE;
468 break; 473 break;
469 case Token::kLTE: 474 case Token::kLTE:
470 hi_cond = LESS; 475 hi_cond = LESS;
471 lo_cond = BELOW_EQUAL; 476 lo_cond = BELOW_EQUAL;
472 break; 477 break;
473 case Token::kGTE: 478 case Token::kGTE:
474 hi_cond = GREATER; 479 hi_cond = GREATER;
475 lo_cond = ABOVE_EQUAL; 480 lo_cond = ABOVE_EQUAL;
476 break; 481 break;
477 default: 482 default:
478 break; 483 break;
479 } 484 }
480 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); 485 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
481 Label is_true, is_false; 486 Label is_true, is_false;
482 // Compare upper halves first. 487 // Compare upper halves first.
483 __ pextrd(left_tmp, left, Immediate(1)); 488 __ cmpl(left2, right2);
484 __ pextrd(right_tmp, right, Immediate(1));
485 __ cmpl(left_tmp, right_tmp);
486 __ j(hi_cond, labels.true_label); 489 __ j(hi_cond, labels.true_label);
487 __ j(FlipCondition(hi_cond), labels.false_label); 490 __ j(FlipCondition(hi_cond), labels.false_label);
488 491
489 // If upper is equal, compare lower half. 492 // If upper is equal, compare lower half.
490 __ pextrd(left_tmp, left, Immediate(0)); 493 __ cmpl(left1, right1);
491 __ pextrd(right_tmp, right, Immediate(0));
492 __ cmpl(left_tmp, right_tmp);
493 return lo_cond; 494 return lo_cond;
494 } 495 }
495 496
496 497
497 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 498 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
498 switch (kind) { 499 switch (kind) {
499 case Token::kEQ: return EQUAL; 500 case Token::kEQ: return EQUAL;
500 case Token::kNE: return NOT_EQUAL; 501 case Token::kNE: return NOT_EQUAL;
501 case Token::kLT: return BELOW; 502 case Token::kLT: return BELOW;
502 case Token::kGT: return ABOVE; 503 case Token::kGT: return ABOVE;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 __ Bind(&is_true); 682 __ Bind(&is_true);
682 __ LoadObject(result_reg, Bool::True()); 683 __ LoadObject(result_reg, Bool::True());
683 __ Bind(&done); 684 __ Bind(&done);
684 } 685 }
685 686
686 687
687 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { 688 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
688 const intptr_t kNumInputs = 2; 689 const intptr_t kNumInputs = 2;
689 const intptr_t kNumTemps = 0; 690 const intptr_t kNumTemps = 0;
690 if (operation_cid() == kMintCid) { 691 if (operation_cid() == kMintCid) {
691 const intptr_t kNumTemps = 2; 692 const intptr_t kNumTemps = 0;
692 LocationSummary* locs = 693 LocationSummary* locs =
693 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 694 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
694 locs->set_in(0, Location::RequiresFpuRegister()); 695 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
695 locs->set_in(1, Location::RequiresFpuRegister()); 696 Location::RequiresRegister()));
696 locs->set_temp(0, Location::RequiresRegister()); 697 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
697 locs->set_temp(1, Location::RequiresRegister()); 698 Location::RequiresRegister()));
698 locs->set_out(0, Location::RequiresRegister()); 699 locs->set_out(0, Location::RequiresRegister());
699 return locs; 700 return locs;
700 } 701 }
701 if (operation_cid() == kDoubleCid) { 702 if (operation_cid() == kDoubleCid) {
702 LocationSummary* summary = 703 LocationSummary* summary =
703 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 704 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
704 summary->set_in(0, Location::RequiresFpuRegister()); 705 summary->set_in(0, Location::RequiresFpuRegister());
705 summary->set_in(1, Location::RequiresFpuRegister()); 706 summary->set_in(1, Location::RequiresFpuRegister());
706 summary->set_out(0, Location::RequiresRegister()); 707 summary->set_out(0, Location::RequiresRegister());
707 return summary; 708 return summary;
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 // element sizes > 1). 1014 // element sizes > 1).
1014 locs->set_in(1, (index_scale() == 1) 1015 locs->set_in(1, (index_scale() == 1)
1015 ? Location::WritableRegister() 1016 ? Location::WritableRegister()
1016 : Location::RequiresRegister()); 1017 : Location::RequiresRegister());
1017 } 1018 }
1018 if ((representation() == kUnboxedDouble) || 1019 if ((representation() == kUnboxedDouble) ||
1019 (representation() == kUnboxedFloat32x4) || 1020 (representation() == kUnboxedFloat32x4) ||
1020 (representation() == kUnboxedInt32x4) || 1021 (representation() == kUnboxedInt32x4) ||
1021 (representation() == kUnboxedFloat64x2)) { 1022 (representation() == kUnboxedFloat64x2)) {
1022 locs->set_out(0, Location::RequiresFpuRegister()); 1023 locs->set_out(0, Location::RequiresFpuRegister());
1024 } else if (representation() == kUnboxedMint) {
1025 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
1026 Location::RegisterLocation(EDX)));
1023 } else { 1027 } else {
1028 ASSERT(representation() == kTagged);
1024 locs->set_out(0, Location::RequiresRegister()); 1029 locs->set_out(0, Location::RequiresRegister());
1025 } 1030 }
1026 return locs; 1031 return locs;
1027 } 1032 }
1028 1033
1029 1034
1030 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1035 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1031 Register array = locs()->in(0).reg(); 1036 Register array = locs()->in(0).reg();
1032 Location index = locs()->in(1); 1037 Location index = locs()->in(1);
1033 1038
1034 Address element_address(kNoRegister, 0); 1039 Address element_address(kNoRegister, 0);
1035 if (IsExternal()) { 1040 if (IsExternal()) {
1036 element_address = index.IsRegister() 1041 element_address = index.IsRegister()
1037 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( 1042 ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
1038 index_scale(), array, index.reg()) 1043 index_scale(), array, index.reg())
1039 : FlowGraphCompiler::ExternalElementAddressForIntIndex( 1044 : FlowGraphCompiler::ExternalElementAddressForIntIndex(
1040 index_scale(), array, Smi::Cast(index.constant()).Value()); 1045 index_scale(), array, Smi::Cast(index.constant()).Value());
1041 } else { 1046 } else {
1042 ASSERT(this->array()->definition()->representation() == kTagged); 1047 ASSERT(this->array()->definition()->representation() == kTagged);
1043 element_address = index.IsRegister() 1048 element_address = index.IsRegister()
1044 ? FlowGraphCompiler::ElementAddressForRegIndex( 1049 ? FlowGraphCompiler::ElementAddressForRegIndex(
1045 class_id(), index_scale(), array, index.reg()) 1050 class_id(), index_scale(), array, index.reg())
1046 : FlowGraphCompiler::ElementAddressForIntIndex( 1051 : FlowGraphCompiler::ElementAddressForIntIndex(
1047 class_id(), index_scale(), array, 1052 class_id(), index_scale(), array,
1048 Smi::Cast(index.constant()).Value()); 1053 Smi::Cast(index.constant()).Value());
1049 } 1054 }
1050 1055
1051 if ((representation() == kUnboxedDouble) || 1056 if ((representation() == kUnboxedDouble) ||
1052 (representation() == kUnboxedMint) ||
1053 (representation() == kUnboxedFloat32x4) || 1057 (representation() == kUnboxedFloat32x4) ||
1054 (representation() == kUnboxedInt32x4) || 1058 (representation() == kUnboxedInt32x4) ||
1055 (representation() == kUnboxedFloat64x2)) { 1059 (representation() == kUnboxedFloat64x2)) {
1056 XmmRegister result = locs()->out(0).fpu_reg(); 1060 XmmRegister result = locs()->out(0).fpu_reg();
1057 if ((index_scale() == 1) && index.IsRegister()) { 1061 if ((index_scale() == 1) && index.IsRegister()) {
1058 __ SmiUntag(index.reg()); 1062 __ SmiUntag(index.reg());
1059 } 1063 }
1060 switch (class_id()) { 1064 switch (class_id()) {
1061 case kTypedDataInt32ArrayCid:
1062 __ movss(result, element_address);
1063 __ pmovsxdq(result, result);
1064 break;
1065 case kTypedDataUint32ArrayCid:
1066 __ xorpd(result, result);
1067 __ movss(result, element_address);
1068 break;
1069 case kTypedDataFloat32ArrayCid: 1065 case kTypedDataFloat32ArrayCid:
1070 __ movss(result, element_address); 1066 __ movss(result, element_address);
1071 break; 1067 break;
1072 case kTypedDataFloat64ArrayCid: 1068 case kTypedDataFloat64ArrayCid:
1073 __ movsd(result, element_address); 1069 __ movsd(result, element_address);
1074 break; 1070 break;
1075 case kTypedDataInt32x4ArrayCid: 1071 case kTypedDataInt32x4ArrayCid:
1076 case kTypedDataFloat32x4ArrayCid: 1072 case kTypedDataFloat32x4ArrayCid:
1077 case kTypedDataFloat64x2ArrayCid: 1073 case kTypedDataFloat64x2ArrayCid:
1078 __ movups(result, element_address); 1074 __ movups(result, element_address);
1079 break; 1075 break;
1076 default:
1077 UNREACHABLE();
1080 } 1078 }
1081 return; 1079 return;
1082 } 1080 }
1083 1081
1082 if (representation() == kUnboxedMint) {
1083 ASSERT(locs()->out(0).IsPairLocation());
1084 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1085 Register result1 = result_pair->At(0).reg();
1086 Register result2 = result_pair->At(1).reg();
1087 ASSERT(result1 == EAX);
1088 ASSERT(result2 == EDX);
1089 if ((index_scale() == 1) && index.IsRegister()) {
1090 __ SmiUntag(index.reg());
1091 }
1092 switch (class_id()) {
1093 case kTypedDataInt32ArrayCid:
1094 __ movl(result1, element_address);
1095 __ cdq();
1096 break;
1097 case kTypedDataUint32ArrayCid:
1098 __ movl(result1, element_address);
1099 __ xorl(result2, result2);
1100 break;
1101 default:
1102 UNREACHABLE();
1103 }
1104 return;
1105 }
1106
1107 ASSERT(representation() == kTagged);
1108
1084 Register result = locs()->out(0).reg(); 1109 Register result = locs()->out(0).reg();
1085 if ((index_scale() == 1) && index.IsRegister()) { 1110 if ((index_scale() == 1) && index.IsRegister()) {
1086 __ SmiUntag(index.reg()); 1111 __ SmiUntag(index.reg());
1087 } 1112 }
1088 switch (class_id()) { 1113 switch (class_id()) {
1089 case kTypedDataInt8ArrayCid: 1114 case kTypedDataInt8ArrayCid:
1090 ASSERT(index_scale() == 1); 1115 ASSERT(index_scale() == 1);
1091 __ movsxb(result, element_address); 1116 __ movsxb(result, element_address);
1092 __ SmiTag(result); 1117 __ SmiTag(result);
1093 break; 1118 break;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 // EBX, ECX, EDX) instead of using a fixed register. 1230 // EBX, ECX, EDX) instead of using a fixed register.
1206 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); 1231 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
1207 break; 1232 break;
1208 case kTypedDataInt16ArrayCid: 1233 case kTypedDataInt16ArrayCid:
1209 case kTypedDataUint16ArrayCid: 1234 case kTypedDataUint16ArrayCid:
1210 // Writable register because the value must be untagged before storing. 1235 // Writable register because the value must be untagged before storing.
1211 locs->set_in(2, Location::WritableRegister()); 1236 locs->set_in(2, Location::WritableRegister());
1212 break; 1237 break;
1213 case kTypedDataInt32ArrayCid: 1238 case kTypedDataInt32ArrayCid:
1214 case kTypedDataUint32ArrayCid: 1239 case kTypedDataUint32ArrayCid:
1215 // Mints are stored in XMM registers. For smis, use a writable register 1240 // For smis, use a writable register because the value must be untagged
1216 // because the value must be untagged before storing. 1241 // before storing. Mints are stored in registers pairs.
1217 locs->set_in(2, value()->IsSmiValue() 1242 if (value()->IsSmiValue()) {
1218 ? Location::WritableRegister() 1243 locs->set_in(2, Location::WritableRegister());
1219 : Location::RequiresFpuRegister()); 1244 } else {
1245 // We only move the lower 32-bits so we don't care where the high bits
1246 // are located.
1247 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1248 Location::Any()));
1249 }
1220 break; 1250 break;
1221 case kTypedDataFloat32ArrayCid: 1251 case kTypedDataFloat32ArrayCid:
1222 case kTypedDataFloat64ArrayCid: 1252 case kTypedDataFloat64ArrayCid:
1223 // TODO(srdjan): Support Float64 constants. 1253 // TODO(srdjan): Support Float64 constants.
1224 locs->set_in(2, Location::RequiresFpuRegister()); 1254 locs->set_in(2, Location::RequiresFpuRegister());
1225 break; 1255 break;
1226 case kTypedDataInt32x4ArrayCid: 1256 case kTypedDataInt32x4ArrayCid:
1227 case kTypedDataFloat32x4ArrayCid: 1257 case kTypedDataFloat32x4ArrayCid:
1228 case kTypedDataFloat64x2ArrayCid: 1258 case kTypedDataFloat64x2ArrayCid:
1229 locs->set_in(2, Location::RequiresFpuRegister()); 1259 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 } 1356 }
1327 case kTypedDataInt32ArrayCid: 1357 case kTypedDataInt32ArrayCid:
1328 case kTypedDataUint32ArrayCid: 1358 case kTypedDataUint32ArrayCid:
1329 if (value()->IsSmiValue()) { 1359 if (value()->IsSmiValue()) {
1330 ASSERT(RequiredInputRepresentation(2) == kTagged); 1360 ASSERT(RequiredInputRepresentation(2) == kTagged);
1331 Register value = locs()->in(2).reg(); 1361 Register value = locs()->in(2).reg();
1332 __ SmiUntag(value); 1362 __ SmiUntag(value);
1333 __ movl(element_address, value); 1363 __ movl(element_address, value);
1334 } else { 1364 } else {
1335 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1365 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1336 __ movss(element_address, locs()->in(2).fpu_reg()); 1366 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1367 Register value1 = value_pair->At(0).reg();
1368 __ movl(element_address, value1);
1337 } 1369 }
1338 break; 1370 break;
1339 case kTypedDataFloat32ArrayCid: 1371 case kTypedDataFloat32ArrayCid:
1340 __ movss(element_address, locs()->in(2).fpu_reg()); 1372 __ movss(element_address, locs()->in(2).fpu_reg());
1341 break; 1373 break;
1342 case kTypedDataFloat64ArrayCid: 1374 case kTypedDataFloat64ArrayCid:
1343 __ movsd(element_address, locs()->in(2).fpu_reg()); 1375 __ movsd(element_address, locs()->in(2).fpu_reg());
1344 break; 1376 break;
1345 case kTypedDataInt32x4ArrayCid: 1377 case kTypedDataInt32x4ArrayCid:
1346 case kTypedDataFloat32x4ArrayCid: 1378 case kTypedDataFloat32x4ArrayCid:
(...skipping 4080 matching lines...) Expand 10 before | Expand all | Expand 10 after
5427 Register length = length_loc.reg(); 5459 Register length = length_loc.reg();
5428 Register index = index_loc.reg(); 5460 Register index = index_loc.reg();
5429 __ cmpl(index, length); 5461 __ cmpl(index, length);
5430 __ j(ABOVE_EQUAL, deopt); 5462 __ j(ABOVE_EQUAL, deopt);
5431 } 5463 }
5432 } 5464 }
5433 5465
5434 5466
5435 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5467 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5436 const intptr_t kNumInputs = 1; 5468 const intptr_t kNumInputs = 1;
5437 const intptr_t value_cid = value()->Type()->ToCid(); 5469 const intptr_t kNumTemps = 0;
5438 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid));
5439 const bool needs_writable_input = (value_cid == kSmiCid);
5440 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5441 LocationSummary* summary = 5470 LocationSummary* summary =
5442 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5471 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5443 summary->set_in(0, needs_writable_input 5472 summary->set_in(0, Location::RequiresRegister());
5444 ? Location::WritableRegister() 5473 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5445 : Location::RequiresRegister()); 5474 Location::RegisterLocation(EDX)));
5446 if (needs_temp) {
5447 summary->set_temp(0, Location::RequiresRegister());
5448 }
5449 summary->set_out(0, Location::RequiresFpuRegister());
5450 return summary; 5475 return summary;
5451 } 5476 }
5452 5477
5453 5478
5454 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5479 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5455 const intptr_t value_cid = value()->Type()->ToCid(); 5480 const intptr_t value_cid = value()->Type()->ToCid();
5456 const Register value = locs()->in(0).reg(); 5481 const Register value = locs()->in(0).reg();
5457 const XmmRegister result = locs()->out(0).fpu_reg(); 5482 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5483 Register result1 = result_pair->At(0).reg();
5484 Register result2 = result_pair->At(1).reg();
5485
5486 ASSERT(value != result1);
5487 ASSERT(value != result2);
5488 ASSERT(result1 == EAX);
5489 ASSERT(result2 == EDX);
5458 5490
5459 if (value_cid == kMintCid) { 5491 if (value_cid == kMintCid) {
5460 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5492 __ movl(result1, FieldAddress(value, Mint::value_offset()));
5493 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize));
5461 } else if (value_cid == kSmiCid) { 5494 } else if (value_cid == kSmiCid) {
5462 __ SmiUntag(value); // Untag input before conversion. 5495 __ movl(result1, value);
5463 __ movd(result, value); 5496 __ SmiUntag(result1);
5464 __ pmovsxdq(result, result); 5497 // Sign extend into result2.
5498 __ cdq();
5465 } else { 5499 } else {
5466 Register temp = locs()->temp(0).reg();
5467 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5500 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5468 ICData::kDeoptUnboxInteger); 5501 ICData::kDeoptUnboxInteger);
5469 Label is_smi, done; 5502 Label is_smi, done;
5470 __ testl(value, Immediate(kSmiTagMask)); 5503 __ testl(value, Immediate(kSmiTagMask));
5471 __ j(ZERO, &is_smi); 5504 __ j(ZERO, &is_smi);
5472 __ CompareClassId(value, kMintCid, temp); 5505 __ CompareClassId(value, kMintCid, result1);
5473 __ j(NOT_EQUAL, deopt); 5506 __ j(NOT_EQUAL, deopt);
5474 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5507 __ movl(result1, FieldAddress(value, Mint::value_offset()));
5508 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize));
5475 __ jmp(&done); 5509 __ jmp(&done);
5476 __ Bind(&is_smi); 5510 __ Bind(&is_smi);
5477 __ movl(temp, value); 5511 __ movl(result1, value);
5478 __ SmiUntag(temp); 5512 __ SmiUntag(result1);
5479 __ movd(result, temp); 5513 // Sign extend into result2.
5480 __ pmovsxdq(result, result); 5514 __ cdq();
5481 __ Bind(&done); 5515 __ Bind(&done);
5482 } 5516 }
5483 } 5517 }
5484 5518
5485 5519
5486 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5520 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5487 const intptr_t kNumInputs = 1; 5521 const intptr_t kNumInputs = 1;
5488 const intptr_t kNumTemps = 2; 5522 const intptr_t kNumTemps = 1;
5489 LocationSummary* summary = 5523 LocationSummary* summary =
5490 new LocationSummary(kNumInputs, 5524 new LocationSummary(kNumInputs,
5491 kNumTemps, 5525 kNumTemps,
5492 LocationSummary::kCallOnSlowPath); 5526 LocationSummary::kCallOnSlowPath);
5493 summary->set_in(0, Location::RequiresFpuRegister()); 5527 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX),
5494 summary->set_temp(0, Location::RegisterLocation(EAX)); 5528 Location::RegisterLocation(EDX)));
5495 summary->set_temp(1, Location::RegisterLocation(EDX)); 5529 summary->set_temp(0, Location::RequiresRegister());
5496 // TODO(fschneider): Save one temp by using result register as a temp.
5497 summary->set_out(0, Location::RequiresRegister()); 5530 summary->set_out(0, Location::RequiresRegister());
5498 return summary; 5531 return summary;
5499 } 5532 }
5500 5533
5501 5534
5502 class BoxIntegerSlowPath : public SlowPathCode { 5535 class BoxIntegerSlowPath : public SlowPathCode {
5503 public: 5536 public:
5504 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5537 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5505 : instruction_(instruction) { } 5538 : instruction_(instruction) { }
5506 5539
(...skipping 21 matching lines...) Expand all
5528 } 5561 }
5529 5562
5530 private: 5563 private:
5531 BoxIntegerInstr* instruction_; 5564 BoxIntegerInstr* instruction_;
5532 }; 5565 };
5533 5566
5534 5567
5535 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5568 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5536 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5569 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5537 compiler->AddSlowPathCode(slow_path); 5570 compiler->AddSlowPathCode(slow_path);
5571 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5572 Register value1 = value_pair->At(0).reg();
5573 Register value2 = value_pair->At(1).reg();
5574 Register out_reg = locs()->out(0).reg();
5538 5575
5539 Register out_reg = locs()->out(0).reg(); 5576 ASSERT(value1 == EAX);
5540 XmmRegister value = locs()->in(0).fpu_reg(); 5577 ASSERT(value2 == EDX);
5578
5579 // Copy value2 into out_reg as a temporary.
5580 // We modify value1 but restore it before using it.
5581 __ movl(out_reg, value2);
5541 5582
5542 // Unboxed operations produce smis or mint-sized values. 5583 // Unboxed operations produce smis or mint-sized values.
5543 // Check if value fits into a smi. 5584 // Check if value fits into a smi.
5544 Label not_smi, done; 5585 Label not_smi, done;
5545 __ pextrd(EDX, value, Immediate(1)); // Upper half. 5586
5546 __ pextrd(EAX, value, Immediate(0)); // Lower half.
5547 // 1. Compute (x + -kMinSmi) which has to be in the range 5587 // 1. Compute (x + -kMinSmi) which has to be in the range
5548 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. 5588 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
5549 __ addl(EAX, Immediate(0x40000000)); 5589 __ addl(value1, Immediate(0x40000000));
5550 __ adcl(EDX, Immediate(0)); 5590 __ adcl(out_reg, Immediate(0));
5551 // 2. Unsigned compare to -kMinSmi+kMaxSmi. 5591 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
5552 __ cmpl(EAX, Immediate(0x80000000)); 5592 __ cmpl(value1, Immediate(0x80000000));
5553 __ sbbl(EDX, Immediate(0)); 5593 __ sbbl(out_reg, Immediate(0));
5554 __ j(ABOVE_EQUAL, &not_smi); 5594 __ j(ABOVE_EQUAL, &not_smi);
5555 // 3. Restore lower half if result is a smi. 5595 // 3. Restore lower half if result is a smi.
5556 __ subl(EAX, Immediate(0x40000000)); 5596 __ subl(value1, Immediate(0x40000000));
5557 5597 __ movl(out_reg, value1);
5558 __ SmiTag(EAX); 5598 __ SmiTag(out_reg);
5559 __ movl(out_reg, EAX);
5560 __ jmp(&done); 5599 __ jmp(&done);
5561
5562 __ Bind(&not_smi); 5600 __ Bind(&not_smi);
5563 __ TryAllocate( 5601 __ TryAllocate(
5564 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5602 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5565 slow_path->entry_label(), 5603 slow_path->entry_label(),
5566 Assembler::kFarJump, 5604 Assembler::kFarJump,
5567 out_reg, 5605 out_reg,
5568 kNoRegister); 5606 kNoRegister);
5569 __ Bind(slow_path->exit_label()); 5607 __ Bind(slow_path->exit_label());
5570 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); 5608 // 3. Restore lower half of input before using it.
5609 __ subl(value1, Immediate(0x40000000));
5610 __ movl(FieldAddress(out_reg, Mint::value_offset()), value1);
5611 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value2);
5571 __ Bind(&done); 5612 __ Bind(&done);
5572 } 5613 }
5573 5614
5574 5615
5575 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5616 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5576 const intptr_t kNumInputs = 2; 5617 const intptr_t kNumInputs = 2;
5577 switch (op_kind()) { 5618 switch (op_kind()) {
5578 case Token::kBIT_AND: 5619 case Token::kBIT_AND:
5579 case Token::kBIT_OR: 5620 case Token::kBIT_OR:
5580 case Token::kBIT_XOR: { 5621 case Token::kBIT_XOR: {
5581 const intptr_t kNumTemps = 5622 const intptr_t kNumTemps = 0;
5582 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5583 LocationSummary* summary = 5623 LocationSummary* summary =
5584 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5624 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5585 summary->set_in(0, Location::RequiresFpuRegister()); 5625 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5586 summary->set_in(1, Location::RequiresFpuRegister()); 5626 Location::RequiresRegister()));
5587 if (FLAG_throw_on_javascript_int_overflow) { 5627 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5588 summary->set_temp(0, Location::RequiresRegister()); 5628 Location::RequiresRegister()));
5589 }
5590 summary->set_out(0, Location::SameAsFirstInput()); 5629 summary->set_out(0, Location::SameAsFirstInput());
5591 return summary; 5630 return summary;
5592 } 5631 }
5593 case Token::kADD: 5632 case Token::kADD:
5594 case Token::kSUB: { 5633 case Token::kSUB: {
5595 const intptr_t kNumTemps = 2; 5634 const intptr_t kNumTemps = 0;
5596 LocationSummary* summary = 5635 LocationSummary* summary =
5597 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5636 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5598 summary->set_in(0, Location::RequiresFpuRegister()); 5637 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5599 summary->set_in(1, Location::RequiresFpuRegister()); 5638 Location::RequiresRegister()));
5600 summary->set_temp(0, Location::RequiresRegister()); 5639 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5601 summary->set_temp(1, Location::RequiresRegister()); 5640 Location::RequiresRegister()));
5602 summary->set_out(0, Location::SameAsFirstInput()); 5641 summary->set_out(0, Location::SameAsFirstInput());
5603 return summary; 5642 return summary;
5604 } 5643 }
5605 default: 5644 default:
5606 UNREACHABLE(); 5645 UNREACHABLE();
5607 return NULL; 5646 return NULL;
5608 } 5647 }
5609 } 5648 }
5610 5649
5611 5650
5612 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5651 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5613 XmmRegister left = locs()->in(0).fpu_reg(); 5652 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5614 XmmRegister right = locs()->in(1).fpu_reg(); 5653 Register left1 = left_pair->At(0).reg();
5615 5654 Register left2 = left_pair->At(1).reg();
5616 ASSERT(locs()->out(0).fpu_reg() == left); 5655 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5656 Register right1 = right_pair->At(0).reg();
5657 Register right2 = right_pair->At(1).reg();
5658 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5659 Register out1 = out_pair->At(0).reg();
5660 Register out2 = out_pair->At(1).reg();
5661 ASSERT(out1 == left1);
5662 ASSERT(out2 == left2);
5617 5663
5618 Label* deopt = NULL; 5664 Label* deopt = NULL;
5619 if (FLAG_throw_on_javascript_int_overflow) { 5665 if (FLAG_throw_on_javascript_int_overflow) {
5620 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5666 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5621 } 5667 }
5622 switch (op_kind()) { 5668 switch (op_kind()) {
5623 case Token::kBIT_AND: __ andpd(left, right); break; 5669 case Token::kBIT_AND:
5624 case Token::kBIT_OR: __ orpd(left, right); break; 5670 __ andl(left1, right1);
5625 case Token::kBIT_XOR: __ xorpd(left, right); break; 5671 __ andl(left2, right2);
5672 break;
5673 case Token::kBIT_OR:
5674 __ orl(left1, right1);
5675 __ orl(left2, right2);
5676 break;
5677 case Token::kBIT_XOR:
5678 __ xorl(left1, right1);
5679 __ xorl(left2, right2);
5680 break;
5626 case Token::kADD: 5681 case Token::kADD:
5627 case Token::kSUB: { 5682 case Token::kSUB: {
5628 Register lo = locs()->temp(0).reg();
5629 Register hi = locs()->temp(1).reg();
5630 if (!FLAG_throw_on_javascript_int_overflow) { 5683 if (!FLAG_throw_on_javascript_int_overflow) {
5631 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5684 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5632 } 5685 }
5633
5634 Label done, overflow;
5635 __ pextrd(lo, right, Immediate(0)); // Lower half
5636 __ pextrd(hi, right, Immediate(1)); // Upper half
5637 __ subl(ESP, Immediate(2 * kWordSize));
5638 __ movq(Address(ESP, 0), left);
5639 if (op_kind() == Token::kADD) { 5686 if (op_kind() == Token::kADD) {
5640 __ addl(Address(ESP, 0), lo); 5687 __ addl(left1, right1);
5641 __ adcl(Address(ESP, 1 * kWordSize), hi); 5688 __ adcl(left2, right2);
5642 } else { 5689 } else {
5643 __ subl(Address(ESP, 0), lo); 5690 __ subl(left1, right1);
5644 __ sbbl(Address(ESP, 1 * kWordSize), hi); 5691 __ sbbl(left2, right2);
5645 } 5692 }
5646 __ j(OVERFLOW, &overflow); 5693 __ j(OVERFLOW, deopt);
5647 __ movq(left, Address(ESP, 0));
5648 __ addl(ESP, Immediate(2 * kWordSize));
5649 __ jmp(&done);
5650 __ Bind(&overflow);
5651 __ addl(ESP, Immediate(2 * kWordSize));
5652 __ jmp(deopt);
5653 __ Bind(&done);
5654 break; 5694 break;
5655 } 5695 }
5656 default: UNREACHABLE(); 5696 default: UNREACHABLE();
5657 } 5697 }
5658 if (FLAG_throw_on_javascript_int_overflow) { 5698 if (FLAG_throw_on_javascript_int_overflow) {
5659 Register tmp = locs()->temp(0).reg(); 5699 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2);
5660 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5661 } 5700 }
5662 } 5701 }
5663 5702
5664 5703
5665 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5704 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5666 const intptr_t kNumInputs = 2; 5705 const intptr_t kNumInputs = 2;
5667 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; 5706 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0;
5668 LocationSummary* summary = 5707 LocationSummary* summary =
5669 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5708 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5670 summary->set_in(0, Location::RequiresFpuRegister()); 5709 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5710 Location::RequiresRegister()));
5671 summary->set_in(1, Location::RegisterLocation(ECX)); 5711 summary->set_in(1, Location::RegisterLocation(ECX));
5672 summary->set_temp(0, Location::RequiresRegister());
5673 if (op_kind() == Token::kSHL) { 5712 if (op_kind() == Token::kSHL) {
5713 summary->set_temp(0, Location::RequiresRegister());
5674 summary->set_temp(1, Location::RequiresRegister()); 5714 summary->set_temp(1, Location::RequiresRegister());
5675 } 5715 }
5676 summary->set_out(0, Location::SameAsFirstInput()); 5716 summary->set_out(0, Location::SameAsFirstInput());
5677 return summary; 5717 return summary;
5678 } 5718 }
5679 5719
5680 5720
5681 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5721 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5682 XmmRegister left = locs()->in(0).fpu_reg(); 5722 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5683 ASSERT(locs()->in(1).reg() == ECX); 5723 Register left1 = left_pair->At(0).reg();
5684 ASSERT(locs()->out(0).fpu_reg() == left); 5724 Register left2 = left_pair->At(1).reg();
5725 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5726 Register out1 = out_pair->At(0).reg();
5727 Register out2 = out_pair->At(1).reg();
5728 ASSERT(out1 == left1);
5729 ASSERT(out2 == left2);
5685 5730
5686 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5731 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5687 Label done; 5732 Label done;
5688 __ testl(ECX, ECX); 5733 __ testl(ECX, ECX);
5689 __ j(ZERO, &done); // Shift by 0 is a nop. 5734 __ j(ZERO, &done); // Shift by 0 is a nop.
5690 __ subl(ESP, Immediate(2 * kWordSize));
5691 __ movq(Address(ESP, 0), left);
5692 // Deoptimize if shift count is > 31. 5735 // Deoptimize if shift count is > 31.
5693 // sarl operation masks the count to 5 bits and 5736 // sarl operation masks the count to 5 bits and
5694 // shrd is undefined with count > operand size (32) 5737 // shrd is undefined with count > operand size (32)
5695 // TODO(fschneider): Support shift counts > 31 without deoptimization. 5738 // TODO(fschneider): Support shift counts > 31 without deoptimization.
5696 __ SmiUntag(ECX); 5739 __ SmiUntag(ECX);
5697 const Immediate& kCountLimit = Immediate(31); 5740 const Immediate& kCountLimit = Immediate(31);
5698 __ cmpl(ECX, kCountLimit); 5741 __ cmpl(ECX, kCountLimit);
5699 __ j(ABOVE, deopt); 5742 __ j(ABOVE, deopt);
5700 switch (op_kind()) { 5743 switch (op_kind()) {
5701 case Token::kSHR: { 5744 case Token::kSHR: {
5702 Register temp = locs()->temp(0).reg(); 5745 __ shrd(left1, left2); // Shift count in CL.
5703 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. 5746 __ sarl(left2, ECX); // Shift count in CL.
5704 __ shrd(Address(ESP, 0), temp); // Shift count in CL.
5705 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL.
5706 break; 5747 break;
5707 } 5748 }
5708 case Token::kSHL: { 5749 case Token::kSHL: {
5709 Register temp1 = locs()->temp(0).reg(); 5750 Register temp1 = locs()->temp(0).reg();
5710 Register temp2 = locs()->temp(1).reg(); 5751 Register temp2 = locs()->temp(1).reg();
5711 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. 5752 __ movl(temp1, left1); // Low 32 bits.
5712 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. 5753 __ movl(temp2, left2); // High 32 bits.
5713 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. 5754 __ shll(left1, ECX); // Shift count in CL.
5714 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. 5755 __ shld(left2, temp1); // Shift count in CL.
5715 // Check for overflow by shifting back the high 32 bits 5756 // Check for overflow by shifting back the high 32 bits
5716 // and comparing with the input. 5757 // and comparing with the input.
5717 __ movl(temp1, temp2); 5758 __ movl(temp1, temp2);
5718 __ movl(temp2, Address(ESP, 1 * kWordSize)); 5759 __ movl(temp2, left2);
5719 __ sarl(temp2, ECX); 5760 __ sarl(temp2, ECX);
5720 __ cmpl(temp1, temp2); 5761 __ cmpl(temp1, temp2);
5721 __ j(NOT_EQUAL, deopt); 5762 __ j(NOT_EQUAL, deopt);
5722 break; 5763 break;
5723 } 5764 }
5724 default: 5765 default:
5725 UNREACHABLE(); 5766 UNREACHABLE();
5726 break; 5767 break;
5727 } 5768 }
5728 __ movq(left, Address(ESP, 0));
5729 __ addl(ESP, Immediate(2 * kWordSize));
5730 __ Bind(&done); 5769 __ Bind(&done);
5731 if (FLAG_throw_on_javascript_int_overflow) { 5770 if (FLAG_throw_on_javascript_int_overflow) {
5732 Register tmp = locs()->temp(0).reg(); 5771 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2);
5733 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5734 } 5772 }
5735 } 5773 }
5736 5774
5737 5775
5738 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5776 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5739 const intptr_t kNumInputs = 1; 5777 const intptr_t kNumInputs = 1;
5740 const intptr_t kNumTemps = 5778 const intptr_t kNumTemps = 0;
5741 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5742 LocationSummary* summary = 5779 LocationSummary* summary =
5743 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5780 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5744 summary->set_in(0, Location::RequiresFpuRegister()); 5781 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5782 Location::RequiresRegister()));
5745 summary->set_out(0, Location::SameAsFirstInput()); 5783 summary->set_out(0, Location::SameAsFirstInput());
5746 if (FLAG_throw_on_javascript_int_overflow) { 5784 if (FLAG_throw_on_javascript_int_overflow) {
5747 summary->set_temp(0, Location::RequiresRegister()); 5785 summary->set_temp(0, Location::RequiresRegister());
5748 } 5786 }
5749 return summary; 5787 return summary;
5750 } 5788 }
5751 5789
5752 5790
5753 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5791 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5754 ASSERT(op_kind() == Token::kBIT_NOT); 5792 ASSERT(op_kind() == Token::kBIT_NOT);
5755 XmmRegister value = locs()->in(0).fpu_reg(); 5793 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5756 ASSERT(value == locs()->out(0).fpu_reg()); 5794 Register left1 = left_pair->At(0).reg();
5795 Register left2 = left_pair->At(1).reg();
5796 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5797 Register out1 = out_pair->At(0).reg();
5798 Register out2 = out_pair->At(1).reg();
5799 ASSERT(out1 == left1);
5800 ASSERT(out2 == left2);
5801
5757 Label* deopt = NULL; 5802 Label* deopt = NULL;
5758 if (FLAG_throw_on_javascript_int_overflow) { 5803 if (FLAG_throw_on_javascript_int_overflow) {
5759 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 5804 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
5760 } 5805 }
5761 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 5806
5762 __ pxor(value, XMM0); 5807 __ notl(left1);
5808 __ notl(left2);
5809
5763 if (FLAG_throw_on_javascript_int_overflow) { 5810 if (FLAG_throw_on_javascript_int_overflow) {
5764 Register tmp = locs()->temp(0).reg(); 5811 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2);
5765 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp);
5766 } 5812 }
5767 } 5813 }
5768 5814
5769 5815
5770 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5816 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5771 return new LocationSummary(0, 0, LocationSummary::kCall); 5817 return new LocationSummary(0, 0, LocationSummary::kCall);
5772 } 5818 }
5773 5819
5774 5820
5775 5821
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
6090 PcDescriptors::kOther, 6136 PcDescriptors::kOther,
6091 locs()); 6137 locs());
6092 __ Drop(ArgumentCount()); // Discard arguments. 6138 __ Drop(ArgumentCount()); // Discard arguments.
6093 } 6139 }
6094 6140
6095 } // namespace dart 6141 } // namespace dart
6096 6142
6097 #undef __ 6143 #undef __
6098 6144
6099 #endif // defined TARGET_ARCH_IA32 6145 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698