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

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 if (class_id() == kTypedDataInt32ArrayCid) {
1026 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
1027 Location::RegisterLocation(EDX)));
1028 } else {
1029 ASSERT(class_id() == kTypedDataUint32ArrayCid);
1030 locs->set_out(0, Location::Pair(Location::RequiresRegister(),
1031 Location::RequiresRegister()));
1032 }
1023 } else { 1033 } else {
1034 ASSERT(representation() == kTagged);
1024 locs->set_out(0, Location::RequiresRegister()); 1035 locs->set_out(0, Location::RequiresRegister());
1025 } 1036 }
1026 return locs; 1037 return locs;
1027 } 1038 }
1028 1039
1029 1040
1030 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1041 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1031 Register array = locs()->in(0).reg(); 1042 Register array = locs()->in(0).reg();
1032 Location index = locs()->in(1); 1043 Location index = locs()->in(1);
1033 1044
1034 Address element_address(kNoRegister, 0); 1045 Address element_address(kNoRegister, 0);
1035 if (IsExternal()) { 1046 if (IsExternal()) {
1036 element_address = index.IsRegister() 1047 element_address = index.IsRegister()
1037 ? compiler->ExternalElementAddressForRegIndex( 1048 ? compiler->ExternalElementAddressForRegIndex(
1038 index_scale(), array, index.reg()) 1049 index_scale(), array, index.reg())
1039 : compiler->ExternalElementAddressForIntIndex( 1050 : compiler->ExternalElementAddressForIntIndex(
1040 index_scale(), array, Smi::Cast(index.constant()).Value()); 1051 index_scale(), array, Smi::Cast(index.constant()).Value());
1041 } else { 1052 } else {
1042 ASSERT(this->array()->definition()->representation() == kTagged); 1053 ASSERT(this->array()->definition()->representation() == kTagged);
1043 element_address = index.IsRegister() 1054 element_address = index.IsRegister()
1044 ? compiler->ElementAddressForRegIndex( 1055 ? compiler->ElementAddressForRegIndex(
1045 class_id(), index_scale(), array, index.reg()) 1056 class_id(), index_scale(), array, index.reg())
1046 : compiler->ElementAddressForIntIndex( 1057 : compiler->ElementAddressForIntIndex(
1047 class_id(), index_scale(), array, 1058 class_id(), index_scale(), array,
1048 Smi::Cast(index.constant()).Value()); 1059 Smi::Cast(index.constant()).Value());
1049 } 1060 }
1050 1061
1051 if ((representation() == kUnboxedDouble) || 1062 if ((representation() == kUnboxedDouble) ||
1052 (representation() == kUnboxedMint) ||
1053 (representation() == kUnboxedFloat32x4) || 1063 (representation() == kUnboxedFloat32x4) ||
1054 (representation() == kUnboxedInt32x4) || 1064 (representation() == kUnboxedInt32x4) ||
1055 (representation() == kUnboxedFloat64x2)) { 1065 (representation() == kUnboxedFloat64x2)) {
1056 XmmRegister result = locs()->out(0).fpu_reg(); 1066 XmmRegister result = locs()->out(0).fpu_reg();
1057 if ((index_scale() == 1) && index.IsRegister()) { 1067 if ((index_scale() == 1) && index.IsRegister()) {
1058 __ SmiUntag(index.reg()); 1068 __ SmiUntag(index.reg());
1059 } 1069 }
1060 switch (class_id()) { 1070 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: 1071 case kTypedDataFloat32ArrayCid:
1070 __ movss(result, element_address); 1072 __ movss(result, element_address);
1071 break; 1073 break;
1072 case kTypedDataFloat64ArrayCid: 1074 case kTypedDataFloat64ArrayCid:
1073 __ movsd(result, element_address); 1075 __ movsd(result, element_address);
1074 break; 1076 break;
1075 case kTypedDataInt32x4ArrayCid: 1077 case kTypedDataInt32x4ArrayCid:
1076 case kTypedDataFloat32x4ArrayCid: 1078 case kTypedDataFloat32x4ArrayCid:
1077 case kTypedDataFloat64x2ArrayCid: 1079 case kTypedDataFloat64x2ArrayCid:
1078 __ movups(result, element_address); 1080 __ movups(result, element_address);
1079 break; 1081 break;
1082 default:
1083 UNREACHABLE();
1080 } 1084 }
1081 return; 1085 return;
1082 } 1086 }
1083 1087
1088 if (representation() == kUnboxedMint) {
1089 ASSERT(locs()->out(0).IsPairLocation());
1090 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1091 Register result1 = result_pair->At(0).reg();
1092 Register result2 = result_pair->At(1).reg();
1093 if ((index_scale() == 1) && index.IsRegister()) {
1094 __ SmiUntag(index.reg());
1095 }
1096 switch (class_id()) {
1097 case kTypedDataInt32ArrayCid:
1098 ASSERT(result1 == EAX);
1099 ASSERT(result2 == EDX);
1100 __ movl(result1, element_address);
1101 __ cdq();
1102 break;
1103 case kTypedDataUint32ArrayCid:
1104 __ movl(result1, element_address);
1105 __ xorl(result2, result2);
1106 break;
1107 default:
1108 UNREACHABLE();
1109 }
1110 return;
1111 }
1112
1113 ASSERT(representation() == kTagged);
1114
1084 Register result = locs()->out(0).reg(); 1115 Register result = locs()->out(0).reg();
1085 if ((index_scale() == 1) && index.IsRegister()) { 1116 if ((index_scale() == 1) && index.IsRegister()) {
1086 __ SmiUntag(index.reg()); 1117 __ SmiUntag(index.reg());
1087 } 1118 }
1088 switch (class_id()) { 1119 switch (class_id()) {
1089 case kTypedDataInt8ArrayCid: 1120 case kTypedDataInt8ArrayCid:
1090 ASSERT(index_scale() == 1); 1121 ASSERT(index_scale() == 1);
1091 __ movsxb(result, element_address); 1122 __ movsxb(result, element_address);
1092 __ SmiTag(result); 1123 __ SmiTag(result);
1093 break; 1124 break;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 // EBX, ECX, EDX) instead of using a fixed register. 1236 // EBX, ECX, EDX) instead of using a fixed register.
1206 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); 1237 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
1207 break; 1238 break;
1208 case kTypedDataInt16ArrayCid: 1239 case kTypedDataInt16ArrayCid:
1209 case kTypedDataUint16ArrayCid: 1240 case kTypedDataUint16ArrayCid:
1210 // Writable register because the value must be untagged before storing. 1241 // Writable register because the value must be untagged before storing.
1211 locs->set_in(2, Location::WritableRegister()); 1242 locs->set_in(2, Location::WritableRegister());
1212 break; 1243 break;
1213 case kTypedDataInt32ArrayCid: 1244 case kTypedDataInt32ArrayCid:
1214 case kTypedDataUint32ArrayCid: 1245 case kTypedDataUint32ArrayCid:
1215 // Mints are stored in XMM registers. For smis, use a writable register 1246 // For smis, use a writable register because the value must be untagged
1216 // because the value must be untagged before storing. 1247 // before storing. Mints are stored in registers pairs.
1217 locs->set_in(2, value()->IsSmiValue() 1248 if (value()->IsSmiValue()) {
1218 ? Location::WritableRegister() 1249 locs->set_in(2, Location::WritableRegister());
1219 : Location::RequiresFpuRegister()); 1250 } else {
1251 // We only move the lower 32-bits so we don't care where the high bits
1252 // are located.
1253 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1254 Location::Any()));
1255 }
1220 break; 1256 break;
1221 case kTypedDataFloat32ArrayCid: 1257 case kTypedDataFloat32ArrayCid:
1222 case kTypedDataFloat64ArrayCid: 1258 case kTypedDataFloat64ArrayCid:
1223 // TODO(srdjan): Support Float64 constants. 1259 // TODO(srdjan): Support Float64 constants.
1224 locs->set_in(2, Location::RequiresFpuRegister()); 1260 locs->set_in(2, Location::RequiresFpuRegister());
1225 break; 1261 break;
1226 case kTypedDataInt32x4ArrayCid: 1262 case kTypedDataInt32x4ArrayCid:
1227 case kTypedDataFloat32x4ArrayCid: 1263 case kTypedDataFloat32x4ArrayCid:
1228 case kTypedDataFloat64x2ArrayCid: 1264 case kTypedDataFloat64x2ArrayCid:
1229 locs->set_in(2, Location::RequiresFpuRegister()); 1265 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 } 1362 }
1327 case kTypedDataInt32ArrayCid: 1363 case kTypedDataInt32ArrayCid:
1328 case kTypedDataUint32ArrayCid: 1364 case kTypedDataUint32ArrayCid:
1329 if (value()->IsSmiValue()) { 1365 if (value()->IsSmiValue()) {
1330 ASSERT(RequiredInputRepresentation(2) == kTagged); 1366 ASSERT(RequiredInputRepresentation(2) == kTagged);
1331 Register value = locs()->in(2).reg(); 1367 Register value = locs()->in(2).reg();
1332 __ SmiUntag(value); 1368 __ SmiUntag(value);
1333 __ movl(element_address, value); 1369 __ movl(element_address, value);
1334 } else { 1370 } else {
1335 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1371 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1336 __ movss(element_address, locs()->in(2).fpu_reg()); 1372 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1373 Register value1 = value_pair->At(0).reg();
1374 __ movl(element_address, value1);
1337 } 1375 }
1338 break; 1376 break;
1339 case kTypedDataFloat32ArrayCid: 1377 case kTypedDataFloat32ArrayCid:
1340 __ movss(element_address, locs()->in(2).fpu_reg()); 1378 __ movss(element_address, locs()->in(2).fpu_reg());
1341 break; 1379 break;
1342 case kTypedDataFloat64ArrayCid: 1380 case kTypedDataFloat64ArrayCid:
1343 __ movsd(element_address, locs()->in(2).fpu_reg()); 1381 __ movsd(element_address, locs()->in(2).fpu_reg());
1344 break; 1382 break;
1345 case kTypedDataInt32x4ArrayCid: 1383 case kTypedDataInt32x4ArrayCid:
1346 case kTypedDataFloat32x4ArrayCid: 1384 case kTypedDataFloat32x4ArrayCid:
(...skipping 4182 matching lines...) Expand 10 before | Expand all | Expand 10 after
5529 Register length = length_loc.reg(); 5567 Register length = length_loc.reg();
5530 Register index = index_loc.reg(); 5568 Register index = index_loc.reg();
5531 __ cmpl(index, length); 5569 __ cmpl(index, length);
5532 __ j(ABOVE_EQUAL, deopt); 5570 __ j(ABOVE_EQUAL, deopt);
5533 } 5571 }
5534 } 5572 }
5535 5573
5536 5574
5537 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5575 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5538 const intptr_t kNumInputs = 1; 5576 const intptr_t kNumInputs = 1;
5539 const intptr_t value_cid = value()->Type()->ToCid(); 5577 const intptr_t kNumTemps = 0;
5540 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid));
5541 const bool needs_writable_input = (value_cid == kSmiCid);
5542 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5543 LocationSummary* summary = 5578 LocationSummary* summary =
5544 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5579 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5545 summary->set_in(0, needs_writable_input 5580 summary->set_in(0, Location::RequiresRegister());
5546 ? Location::WritableRegister() 5581 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5547 : Location::RequiresRegister()); 5582 Location::RegisterLocation(EDX)));
5548 if (needs_temp) {
5549 summary->set_temp(0, Location::RequiresRegister());
5550 }
5551 summary->set_out(0, Location::RequiresFpuRegister());
5552 return summary; 5583 return summary;
5553 } 5584 }
5554 5585
5555 5586
5556 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5587 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5557 const intptr_t value_cid = value()->Type()->ToCid(); 5588 const intptr_t value_cid = value()->Type()->ToCid();
5558 const Register value = locs()->in(0).reg(); 5589 const Register value = locs()->in(0).reg();
5559 const XmmRegister result = locs()->out(0).fpu_reg(); 5590 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5591 Register result_lo = result_pair->At(0).reg();
5592 Register result_hi = result_pair->At(1).reg();
5593
5594 ASSERT(value != result_lo);
5595 ASSERT(value != result_hi);
5596 ASSERT(result_lo == EAX);
5597 ASSERT(result_hi == EDX);
5560 5598
5561 if (value_cid == kMintCid) { 5599 if (value_cid == kMintCid) {
5562 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5600 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5601 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5563 } else if (value_cid == kSmiCid) { 5602 } else if (value_cid == kSmiCid) {
5564 __ SmiUntag(value); // Untag input before conversion. 5603 __ movl(result_lo, value);
5565 __ movd(result, value); 5604 __ SmiUntag(result_lo);
5566 __ pmovsxdq(result, result); 5605 // Sign extend into result_hi.
5606 __ cdq();
5567 } else { 5607 } else {
5568 Register temp = locs()->temp(0).reg();
5569 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5608 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5570 ICData::kDeoptUnboxInteger); 5609 ICData::kDeoptUnboxInteger);
5571 Label is_smi, done; 5610 Label is_smi, done;
5572 __ testl(value, Immediate(kSmiTagMask)); 5611 __ testl(value, Immediate(kSmiTagMask));
5573 __ j(ZERO, &is_smi); 5612 __ j(ZERO, &is_smi);
5574 __ CompareClassId(value, kMintCid, temp); 5613 __ CompareClassId(value, kMintCid, result_lo);
5575 __ j(NOT_EQUAL, deopt); 5614 __ j(NOT_EQUAL, deopt);
5576 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5615 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5616 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5577 __ jmp(&done); 5617 __ jmp(&done);
5578 __ Bind(&is_smi); 5618 __ Bind(&is_smi);
5579 __ movl(temp, value); 5619 __ movl(result_lo, value);
5580 __ SmiUntag(temp); 5620 __ SmiUntag(result_lo);
5581 __ movd(result, temp); 5621 // Sign extend into result_hi.
5582 __ pmovsxdq(result, result); 5622 __ cdq();
5583 __ Bind(&done); 5623 __ Bind(&done);
5584 } 5624 }
5585 } 5625 }
5586 5626
5587 5627
5588 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5628 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5589 const intptr_t kNumInputs = 1; 5629 const intptr_t kNumInputs = 1;
5590 const intptr_t kNumTemps = 2; 5630 const intptr_t kNumTemps = 1;
5591 LocationSummary* summary = 5631 LocationSummary* summary =
5592 new LocationSummary(kNumInputs, 5632 new LocationSummary(kNumInputs,
5593 kNumTemps, 5633 kNumTemps,
5594 LocationSummary::kCallOnSlowPath); 5634 LocationSummary::kCallOnSlowPath);
5595 summary->set_in(0, Location::RequiresFpuRegister()); 5635 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5596 summary->set_temp(0, Location::RegisterLocation(EAX)); 5636 Location::RequiresRegister()));
5597 summary->set_temp(1, Location::RegisterLocation(EDX)); 5637 summary->set_temp(0, Location::RequiresRegister());
5598 // TODO(fschneider): Save one temp by using result register as a temp.
5599 summary->set_out(0, Location::RequiresRegister()); 5638 summary->set_out(0, Location::RequiresRegister());
5600 return summary; 5639 return summary;
5601 } 5640 }
5602 5641
5603 5642
5604 class BoxIntegerSlowPath : public SlowPathCode { 5643 class BoxIntegerSlowPath : public SlowPathCode {
5605 public: 5644 public:
5606 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5645 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5607 : instruction_(instruction) { } 5646 : instruction_(instruction) { }
5608 5647
(...skipping 21 matching lines...) Expand all
5630 } 5669 }
5631 5670
5632 private: 5671 private:
5633 BoxIntegerInstr* instruction_; 5672 BoxIntegerInstr* instruction_;
5634 }; 5673 };
5635 5674
5636 5675
5637 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5676 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5638 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5677 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5639 compiler->AddSlowPathCode(slow_path); 5678 compiler->AddSlowPathCode(slow_path);
5679 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5680 Register value_lo = value_pair->At(0).reg();
5681 Register value_hi = value_pair->At(1).reg();
5682 Register out_reg = locs()->out(0).reg();
5640 5683
5641 Register out_reg = locs()->out(0).reg(); 5684 // Copy value_hi into out_reg as a temporary.
5642 XmmRegister value = locs()->in(0).fpu_reg(); 5685 // We modify value_lo but restore it before using it.
5686 __ movl(out_reg, value_hi);
5643 5687
5644 // Unboxed operations produce smis or mint-sized values. 5688 // Unboxed operations produce smis or mint-sized values.
5645 // Check if value fits into a smi. 5689 // Check if value fits into a smi.
5646 Label not_smi, done; 5690 Label not_smi, done;
5647 __ pextrd(EDX, value, Immediate(1)); // Upper half. 5691
5648 __ pextrd(EAX, value, Immediate(0)); // Lower half.
5649 // 1. Compute (x + -kMinSmi) which has to be in the range 5692 // 1. Compute (x + -kMinSmi) which has to be in the range
5650 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. 5693 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
5651 __ addl(EAX, Immediate(0x40000000)); 5694 __ addl(value_lo, Immediate(0x40000000));
5652 __ adcl(EDX, Immediate(0)); 5695 __ adcl(out_reg, Immediate(0));
5653 // 2. Unsigned compare to -kMinSmi+kMaxSmi. 5696 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
5654 __ cmpl(EAX, Immediate(0x80000000)); 5697 __ cmpl(value_lo, Immediate(0x80000000));
5655 __ sbbl(EDX, Immediate(0)); 5698 __ sbbl(out_reg, Immediate(0));
5656 __ j(ABOVE_EQUAL, &not_smi); 5699 __ j(ABOVE_EQUAL, &not_smi);
5657 // 3. Restore lower half if result is a smi. 5700 // 3. Restore lower half if result is a smi.
5658 __ subl(EAX, Immediate(0x40000000)); 5701 __ subl(value_lo, Immediate(0x40000000));
5659 5702 __ movl(out_reg, value_lo);
5660 __ SmiTag(EAX); 5703 __ SmiTag(out_reg);
5661 __ movl(out_reg, EAX);
5662 __ jmp(&done); 5704 __ jmp(&done);
5663
5664 __ Bind(&not_smi); 5705 __ Bind(&not_smi);
5665 __ TryAllocate( 5706 __ TryAllocate(
5666 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5707 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5667 slow_path->entry_label(), 5708 slow_path->entry_label(),
5668 Assembler::kFarJump, 5709 Assembler::kFarJump,
5669 out_reg, 5710 out_reg,
5670 kNoRegister); 5711 kNoRegister);
5671 __ Bind(slow_path->exit_label()); 5712 __ Bind(slow_path->exit_label());
5672 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); 5713 // 3. Restore lower half of input before using it.
5714 __ subl(value_lo, Immediate(0x40000000));
5715 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
5716 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
5673 __ Bind(&done); 5717 __ Bind(&done);
5674 } 5718 }
5675 5719
5676 5720
5677 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5721 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5678 const intptr_t kNumInputs = 2; 5722 const intptr_t kNumInputs = 2;
5679 switch (op_kind()) { 5723 switch (op_kind()) {
5680 case Token::kBIT_AND: 5724 case Token::kBIT_AND:
5681 case Token::kBIT_OR: 5725 case Token::kBIT_OR:
5682 case Token::kBIT_XOR: { 5726 case Token::kBIT_XOR: {
5683 const intptr_t kNumTemps = 5727 const intptr_t kNumTemps = 0;
5684 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5685 LocationSummary* summary = 5728 LocationSummary* summary =
5686 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5729 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5687 summary->set_in(0, Location::RequiresFpuRegister()); 5730 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5688 summary->set_in(1, Location::RequiresFpuRegister()); 5731 Location::RequiresRegister()));
5689 if (FLAG_throw_on_javascript_int_overflow) { 5732 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5690 summary->set_temp(0, Location::RequiresRegister()); 5733 Location::RequiresRegister()));
5691 }
5692 summary->set_out(0, Location::SameAsFirstInput()); 5734 summary->set_out(0, Location::SameAsFirstInput());
5693 return summary; 5735 return summary;
5694 } 5736 }
5695 case Token::kADD: 5737 case Token::kADD:
5696 case Token::kSUB: { 5738 case Token::kSUB: {
5697 const intptr_t kNumTemps = 2; 5739 const intptr_t kNumTemps = 0;
5698 LocationSummary* summary = 5740 LocationSummary* summary =
5699 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5741 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5700 summary->set_in(0, Location::RequiresFpuRegister()); 5742 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5701 summary->set_in(1, Location::RequiresFpuRegister()); 5743 Location::RequiresRegister()));
5702 summary->set_temp(0, Location::RequiresRegister()); 5744 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5703 summary->set_temp(1, Location::RequiresRegister()); 5745 Location::RequiresRegister()));
5704 summary->set_out(0, Location::SameAsFirstInput()); 5746 summary->set_out(0, Location::SameAsFirstInput());
5705 return summary; 5747 return summary;
5706 } 5748 }
5707 default: 5749 default:
5708 UNREACHABLE(); 5750 UNREACHABLE();
5709 return NULL; 5751 return NULL;
5710 } 5752 }
5711 } 5753 }
5712 5754
5713 5755
5714 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5756 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5715 XmmRegister left = locs()->in(0).fpu_reg(); 5757 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5716 XmmRegister right = locs()->in(1).fpu_reg(); 5758 Register left_lo = left_pair->At(0).reg();
5717 5759 Register left_hi = left_pair->At(1).reg();
5718 ASSERT(locs()->out(0).fpu_reg() == left); 5760 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5761 Register right_lo = right_pair->At(0).reg();
5762 Register right_hi = right_pair->At(1).reg();
5763 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5764 Register out_lo = out_pair->At(0).reg();
5765 Register out_hi = out_pair->At(1).reg();
5766 ASSERT(out_lo == left_lo);
5767 ASSERT(out_hi == left_hi);
5719 5768
5720 Label* deopt = NULL; 5769 Label* deopt = NULL;
5721 if (FLAG_throw_on_javascript_int_overflow) { 5770 if (FLAG_throw_on_javascript_int_overflow) {
5722 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5771 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5723 } 5772 }
5724 switch (op_kind()) { 5773 switch (op_kind()) {
5725 case Token::kBIT_AND: __ andpd(left, right); break; 5774 case Token::kBIT_AND:
5726 case Token::kBIT_OR: __ orpd(left, right); break; 5775 __ andl(left_lo, right_lo);
5727 case Token::kBIT_XOR: __ xorpd(left, right); break; 5776 __ andl(left_hi, right_hi);
5777 break;
5778 case Token::kBIT_OR:
5779 __ orl(left_lo, right_lo);
5780 __ orl(left_hi, right_hi);
5781 break;
5782 case Token::kBIT_XOR:
5783 __ xorl(left_lo, right_lo);
5784 __ xorl(left_hi, right_hi);
5785 break;
5728 case Token::kADD: 5786 case Token::kADD:
5729 case Token::kSUB: { 5787 case Token::kSUB: {
5730 Register lo = locs()->temp(0).reg();
5731 Register hi = locs()->temp(1).reg();
5732 if (!FLAG_throw_on_javascript_int_overflow) { 5788 if (!FLAG_throw_on_javascript_int_overflow) {
5733 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5789 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5734 } 5790 }
5735
5736 Label done, overflow;
5737 __ pextrd(lo, right, Immediate(0)); // Lower half
5738 __ pextrd(hi, right, Immediate(1)); // Upper half
5739 __ subl(ESP, Immediate(2 * kWordSize));
5740 __ movq(Address(ESP, 0), left);
5741 if (op_kind() == Token::kADD) { 5791 if (op_kind() == Token::kADD) {
5742 __ addl(Address(ESP, 0), lo); 5792 __ addl(left_lo, right_lo);
5743 __ adcl(Address(ESP, 1 * kWordSize), hi); 5793 __ adcl(left_hi, right_hi);
5744 } else { 5794 } else {
5745 __ subl(Address(ESP, 0), lo); 5795 __ subl(left_lo, right_lo);
5746 __ sbbl(Address(ESP, 1 * kWordSize), hi); 5796 __ sbbl(left_hi, right_hi);
5747 } 5797 }
5748 __ j(OVERFLOW, &overflow); 5798 __ j(OVERFLOW, deopt);
5749 __ movq(left, Address(ESP, 0));
5750 __ addl(ESP, Immediate(2 * kWordSize));
5751 __ jmp(&done);
5752 __ Bind(&overflow);
5753 __ addl(ESP, Immediate(2 * kWordSize));
5754 __ jmp(deopt);
5755 __ Bind(&done);
5756 break; 5799 break;
5757 } 5800 }
5758 default: UNREACHABLE(); 5801 default: UNREACHABLE();
5759 } 5802 }
5760 if (FLAG_throw_on_javascript_int_overflow) { 5803 if (FLAG_throw_on_javascript_int_overflow) {
5761 Register tmp = locs()->temp(0).reg(); 5804 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5762 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5763 } 5805 }
5764 } 5806 }
5765 5807
5766 5808
5767 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5809 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5768 const intptr_t kNumInputs = 2; 5810 const intptr_t kNumInputs = 2;
5769 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; 5811 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0;
5770 LocationSummary* summary = 5812 LocationSummary* summary =
5771 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5772 summary->set_in(0, Location::RequiresFpuRegister()); 5814 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5815 Location::RequiresRegister()));
5773 summary->set_in(1, Location::RegisterLocation(ECX)); 5816 summary->set_in(1, Location::RegisterLocation(ECX));
5774 summary->set_temp(0, Location::RequiresRegister());
5775 if (op_kind() == Token::kSHL) { 5817 if (op_kind() == Token::kSHL) {
5818 summary->set_temp(0, Location::RequiresRegister());
5776 summary->set_temp(1, Location::RequiresRegister()); 5819 summary->set_temp(1, Location::RequiresRegister());
5777 } 5820 }
5778 summary->set_out(0, Location::SameAsFirstInput()); 5821 summary->set_out(0, Location::SameAsFirstInput());
5779 return summary; 5822 return summary;
5780 } 5823 }
5781 5824
5782 5825
5783 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5826 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5784 XmmRegister left = locs()->in(0).fpu_reg(); 5827 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5785 ASSERT(locs()->in(1).reg() == ECX); 5828 Register left_lo = left_pair->At(0).reg();
5786 ASSERT(locs()->out(0).fpu_reg() == left); 5829 Register left_hi = left_pair->At(1).reg();
5830 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5831 Register out_lo = out_pair->At(0).reg();
5832 Register out_hi = out_pair->At(1).reg();
5833 ASSERT(out_lo == left_lo);
5834 ASSERT(out_hi == left_hi);
5787 5835
5788 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5836 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5789 Label done; 5837 Label done;
5790 __ testl(ECX, ECX); 5838 __ testl(ECX, ECX);
5791 __ j(ZERO, &done); // Shift by 0 is a nop. 5839 __ j(ZERO, &done); // Shift by 0 is a nop.
5792 __ subl(ESP, Immediate(2 * kWordSize));
5793 __ movq(Address(ESP, 0), left);
5794 // Deoptimize if shift count is > 31. 5840 // Deoptimize if shift count is > 31.
5795 // sarl operation masks the count to 5 bits and 5841 // sarl operation masks the count to 5 bits and
5796 // shrd is undefined with count > operand size (32) 5842 // shrd is undefined with count > operand size (32)
5797 // TODO(fschneider): Support shift counts > 31 without deoptimization. 5843 // TODO(fschneider): Support shift counts > 31 without deoptimization.
5798 __ SmiUntag(ECX); 5844 __ SmiUntag(ECX);
5799 const Immediate& kCountLimit = Immediate(31); 5845 const Immediate& kCountLimit = Immediate(31);
5800 __ cmpl(ECX, kCountLimit); 5846 __ cmpl(ECX, kCountLimit);
5801 __ j(ABOVE, deopt); 5847 __ j(ABOVE, deopt);
5802 switch (op_kind()) { 5848 switch (op_kind()) {
5803 case Token::kSHR: { 5849 case Token::kSHR: {
5804 Register temp = locs()->temp(0).reg(); 5850 __ shrd(left_lo, left_hi); // Shift count in CL.
5805 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. 5851 __ sarl(left_hi, ECX); // Shift count in CL.
5806 __ shrd(Address(ESP, 0), temp); // Shift count in CL.
5807 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL.
5808 break; 5852 break;
5809 } 5853 }
5810 case Token::kSHL: { 5854 case Token::kSHL: {
5811 Register temp1 = locs()->temp(0).reg(); 5855 Register temp1 = locs()->temp(0).reg();
5812 Register temp2 = locs()->temp(1).reg(); 5856 Register temp2 = locs()->temp(1).reg();
5813 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. 5857 __ movl(temp1, left_lo); // Low 32 bits.
5814 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. 5858 __ movl(temp2, left_hi); // High 32 bits.
5815 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. 5859 __ shll(left_lo, ECX); // Shift count in CL.
5816 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. 5860 __ shld(left_hi, temp1); // Shift count in CL.
5817 // Check for overflow by shifting back the high 32 bits 5861 // Check for overflow by shifting back the high 32 bits
5818 // and comparing with the input. 5862 // and comparing with the input.
5819 __ movl(temp1, temp2); 5863 __ movl(temp1, temp2);
5820 __ movl(temp2, Address(ESP, 1 * kWordSize)); 5864 __ movl(temp2, left_hi);
5821 __ sarl(temp2, ECX); 5865 __ sarl(temp2, ECX);
5822 __ cmpl(temp1, temp2); 5866 __ cmpl(temp1, temp2);
5823 __ j(NOT_EQUAL, deopt); 5867 __ j(NOT_EQUAL, deopt);
5824 break; 5868 break;
5825 } 5869 }
5826 default: 5870 default:
5827 UNREACHABLE(); 5871 UNREACHABLE();
5828 break; 5872 break;
5829 } 5873 }
5830 __ movq(left, Address(ESP, 0));
5831 __ addl(ESP, Immediate(2 * kWordSize));
5832 __ Bind(&done); 5874 __ Bind(&done);
5833 if (FLAG_throw_on_javascript_int_overflow) { 5875 if (FLAG_throw_on_javascript_int_overflow) {
5834 Register tmp = locs()->temp(0).reg(); 5876 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5835 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5836 } 5877 }
5837 } 5878 }
5838 5879
5839 5880
5840 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5881 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5841 const intptr_t kNumInputs = 1; 5882 const intptr_t kNumInputs = 1;
5842 const intptr_t kNumTemps = 5883 const intptr_t kNumTemps = 0;
5843 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5844 LocationSummary* summary = 5884 LocationSummary* summary =
5845 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5885 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5846 summary->set_in(0, Location::RequiresFpuRegister()); 5886 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5887 Location::RequiresRegister()));
5847 summary->set_out(0, Location::SameAsFirstInput()); 5888 summary->set_out(0, Location::SameAsFirstInput());
5848 if (FLAG_throw_on_javascript_int_overflow) { 5889 if (FLAG_throw_on_javascript_int_overflow) {
5849 summary->set_temp(0, Location::RequiresRegister()); 5890 summary->set_temp(0, Location::RequiresRegister());
5850 } 5891 }
5851 return summary; 5892 return summary;
5852 } 5893 }
5853 5894
5854 5895
5855 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5896 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5856 ASSERT(op_kind() == Token::kBIT_NOT); 5897 ASSERT(op_kind() == Token::kBIT_NOT);
5857 XmmRegister value = locs()->in(0).fpu_reg(); 5898 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5858 ASSERT(value == locs()->out(0).fpu_reg()); 5899 Register left_lo = left_pair->At(0).reg();
5900 Register left_hi = left_pair->At(1).reg();
5901 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5902 Register out_lo = out_pair->At(0).reg();
5903 Register out_hi = out_pair->At(1).reg();
5904 ASSERT(out_lo == left_lo);
5905 ASSERT(out_hi == left_hi);
5906
5859 Label* deopt = NULL; 5907 Label* deopt = NULL;
5860 if (FLAG_throw_on_javascript_int_overflow) { 5908 if (FLAG_throw_on_javascript_int_overflow) {
5861 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 5909 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
5862 } 5910 }
5863 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 5911
5864 __ pxor(value, XMM0); 5912 __ notl(left_lo);
5913 __ notl(left_hi);
5914
5865 if (FLAG_throw_on_javascript_int_overflow) { 5915 if (FLAG_throw_on_javascript_int_overflow) {
5866 Register tmp = locs()->temp(0).reg(); 5916 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5867 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp);
5868 } 5917 }
5869 } 5918 }
5870 5919
5871 5920
5872 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5921 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5873 return new LocationSummary(0, 0, LocationSummary::kCall); 5922 return new LocationSummary(0, 0, LocationSummary::kCall);
5874 } 5923 }
5875 5924
5876 5925
5877 5926
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
6192 PcDescriptors::kOther, 6241 PcDescriptors::kOther,
6193 locs()); 6242 locs());
6194 __ Drop(ArgumentCount()); // Discard arguments. 6243 __ Drop(ArgumentCount()); // Discard arguments.
6195 } 6244 }
6196 6245
6197 } // namespace dart 6246 } // namespace dart
6198 6247
6199 #undef __ 6248 #undef __
6200 6249
6201 #endif // defined TARGET_ARCH_IA32 6250 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698