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

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)));
Florian Schneider 2014/05/21 12:50:59 For the case of Uint32Array you don't actually nee
Cutch 2014/05/21 17:00:03 Done.
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);
Florian Schneider 2014/05/21 12:50:59 Move these two ASSERTs into the Int32Array case (w
Cutch 2014/05/21 17:00:03 Done.
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 4182 matching lines...) Expand 10 before | Expand all | Expand 10 after
5529 Register length = length_loc.reg(); 5561 Register length = length_loc.reg();
5530 Register index = index_loc.reg(); 5562 Register index = index_loc.reg();
5531 __ cmpl(index, length); 5563 __ cmpl(index, length);
5532 __ j(ABOVE_EQUAL, deopt); 5564 __ j(ABOVE_EQUAL, deopt);
5533 } 5565 }
5534 } 5566 }
5535 5567
5536 5568
5537 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5569 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5538 const intptr_t kNumInputs = 1; 5570 const intptr_t kNumInputs = 1;
5539 const intptr_t value_cid = value()->Type()->ToCid(); 5571 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 = 5572 LocationSummary* summary =
5544 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5573 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5545 summary->set_in(0, needs_writable_input 5574 summary->set_in(0, Location::RequiresRegister());
5546 ? Location::WritableRegister() 5575 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5547 : Location::RequiresRegister()); 5576 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; 5577 return summary;
5553 } 5578 }
5554 5579
5555 5580
5556 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5581 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5557 const intptr_t value_cid = value()->Type()->ToCid(); 5582 const intptr_t value_cid = value()->Type()->ToCid();
5558 const Register value = locs()->in(0).reg(); 5583 const Register value = locs()->in(0).reg();
5559 const XmmRegister result = locs()->out(0).fpu_reg(); 5584 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5585 Register result_lo = result_pair->At(0).reg();
5586 Register result_hi = result_pair->At(1).reg();
5587
5588 ASSERT(value != result_lo);
5589 ASSERT(value != result_hi);
5590 ASSERT(result_lo == EAX);
5591 ASSERT(result_hi == EDX);
5560 5592
5561 if (value_cid == kMintCid) { 5593 if (value_cid == kMintCid) {
5562 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5594 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5595 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5563 } else if (value_cid == kSmiCid) { 5596 } else if (value_cid == kSmiCid) {
5564 __ SmiUntag(value); // Untag input before conversion. 5597 __ movl(result_lo, value);
5565 __ movd(result, value); 5598 __ SmiUntag(result_lo);
5566 __ pmovsxdq(result, result); 5599 // Sign extend into result_hi.
5600 __ cdq();
5567 } else { 5601 } else {
5568 Register temp = locs()->temp(0).reg();
5569 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5602 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5570 ICData::kDeoptUnboxInteger); 5603 ICData::kDeoptUnboxInteger);
5571 Label is_smi, done; 5604 Label is_smi, done;
5572 __ testl(value, Immediate(kSmiTagMask)); 5605 __ testl(value, Immediate(kSmiTagMask));
5573 __ j(ZERO, &is_smi); 5606 __ j(ZERO, &is_smi);
5574 __ CompareClassId(value, kMintCid, temp); 5607 __ CompareClassId(value, kMintCid, result_lo);
5575 __ j(NOT_EQUAL, deopt); 5608 __ j(NOT_EQUAL, deopt);
5576 __ movsd(result, FieldAddress(value, Mint::value_offset())); 5609 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5610 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5577 __ jmp(&done); 5611 __ jmp(&done);
5578 __ Bind(&is_smi); 5612 __ Bind(&is_smi);
5579 __ movl(temp, value); 5613 __ movl(result_lo, value);
5580 __ SmiUntag(temp); 5614 __ SmiUntag(result_lo);
5581 __ movd(result, temp); 5615 // Sign extend into result_hi.
5582 __ pmovsxdq(result, result); 5616 __ cdq();
5583 __ Bind(&done); 5617 __ Bind(&done);
5584 } 5618 }
5585 } 5619 }
5586 5620
5587 5621
5588 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5622 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5589 const intptr_t kNumInputs = 1; 5623 const intptr_t kNumInputs = 1;
5590 const intptr_t kNumTemps = 2; 5624 const intptr_t kNumTemps = 1;
5591 LocationSummary* summary = 5625 LocationSummary* summary =
5592 new LocationSummary(kNumInputs, 5626 new LocationSummary(kNumInputs,
5593 kNumTemps, 5627 kNumTemps,
5594 LocationSummary::kCallOnSlowPath); 5628 LocationSummary::kCallOnSlowPath);
5595 summary->set_in(0, Location::RequiresFpuRegister()); 5629 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX),
5596 summary->set_temp(0, Location::RegisterLocation(EAX)); 5630 Location::RegisterLocation(EDX)));
5597 summary->set_temp(1, Location::RegisterLocation(EDX)); 5631 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()); 5632 summary->set_out(0, Location::RequiresRegister());
5600 return summary; 5633 return summary;
5601 } 5634 }
5602 5635
5603 5636
5604 class BoxIntegerSlowPath : public SlowPathCode { 5637 class BoxIntegerSlowPath : public SlowPathCode {
5605 public: 5638 public:
5606 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5639 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5607 : instruction_(instruction) { } 5640 : instruction_(instruction) { }
5608 5641
(...skipping 21 matching lines...) Expand all
5630 } 5663 }
5631 5664
5632 private: 5665 private:
5633 BoxIntegerInstr* instruction_; 5666 BoxIntegerInstr* instruction_;
5634 }; 5667 };
5635 5668
5636 5669
5637 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5670 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5638 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5671 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5639 compiler->AddSlowPathCode(slow_path); 5672 compiler->AddSlowPathCode(slow_path);
5673 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5674 Register value_lo = value_pair->At(0).reg();
5675 Register value_hi = value_pair->At(1).reg();
5676 Register out_reg = locs()->out(0).reg();
5640 5677
5641 Register out_reg = locs()->out(0).reg(); 5678 ASSERT(value_lo == EAX);
Florian Schneider 2014/05/21 12:50:59 Where is it assumed that value_lo must be EAX? It
Cutch 2014/05/21 17:00:03 Done.
5642 XmmRegister value = locs()->in(0).fpu_reg(); 5679 ASSERT(value_hi == EDX);
Florian Schneider 2014/05/21 12:50:59 Same for value_hi.
Cutch 2014/05/21 17:00:03 Done.
5680
5681 // Copy value_hi into out_reg as a temporary.
5682 // We modify value_lo but restore it before using it.
5683 __ movl(out_reg, value_hi);
5643 5684
5644 // Unboxed operations produce smis or mint-sized values. 5685 // Unboxed operations produce smis or mint-sized values.
5645 // Check if value fits into a smi. 5686 // Check if value fits into a smi.
5646 Label not_smi, done; 5687 Label not_smi, done;
5647 __ pextrd(EDX, value, Immediate(1)); // Upper half. 5688
5648 __ pextrd(EAX, value, Immediate(0)); // Lower half.
5649 // 1. Compute (x + -kMinSmi) which has to be in the range 5689 // 1. Compute (x + -kMinSmi) which has to be in the range
5650 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. 5690 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
5651 __ addl(EAX, Immediate(0x40000000)); 5691 __ addl(value_lo, Immediate(0x40000000));
5652 __ adcl(EDX, Immediate(0)); 5692 __ adcl(out_reg, Immediate(0));
5653 // 2. Unsigned compare to -kMinSmi+kMaxSmi. 5693 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
5654 __ cmpl(EAX, Immediate(0x80000000)); 5694 __ cmpl(value_lo, Immediate(0x80000000));
5655 __ sbbl(EDX, Immediate(0)); 5695 __ sbbl(out_reg, Immediate(0));
5656 __ j(ABOVE_EQUAL, &not_smi); 5696 __ j(ABOVE_EQUAL, &not_smi);
5657 // 3. Restore lower half if result is a smi. 5697 // 3. Restore lower half if result is a smi.
5658 __ subl(EAX, Immediate(0x40000000)); 5698 __ subl(value_lo, Immediate(0x40000000));
5659 5699 __ movl(out_reg, value_lo);
5660 __ SmiTag(EAX); 5700 __ SmiTag(out_reg);
5661 __ movl(out_reg, EAX);
5662 __ jmp(&done); 5701 __ jmp(&done);
5663
5664 __ Bind(&not_smi); 5702 __ Bind(&not_smi);
5665 __ TryAllocate( 5703 __ TryAllocate(
5666 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5704 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5667 slow_path->entry_label(), 5705 slow_path->entry_label(),
5668 Assembler::kFarJump, 5706 Assembler::kFarJump,
5669 out_reg, 5707 out_reg,
5670 kNoRegister); 5708 kNoRegister);
5671 __ Bind(slow_path->exit_label()); 5709 __ Bind(slow_path->exit_label());
5672 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); 5710 // 3. Restore lower half of input before using it.
5711 __ subl(value_lo, Immediate(0x40000000));
5712 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
5713 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
5673 __ Bind(&done); 5714 __ Bind(&done);
5674 } 5715 }
5675 5716
5676 5717
5677 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5718 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5678 const intptr_t kNumInputs = 2; 5719 const intptr_t kNumInputs = 2;
5679 switch (op_kind()) { 5720 switch (op_kind()) {
5680 case Token::kBIT_AND: 5721 case Token::kBIT_AND:
5681 case Token::kBIT_OR: 5722 case Token::kBIT_OR:
5682 case Token::kBIT_XOR: { 5723 case Token::kBIT_XOR: {
5683 const intptr_t kNumTemps = 5724 const intptr_t kNumTemps = 0;
5684 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5685 LocationSummary* summary = 5725 LocationSummary* summary =
5686 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5726 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5687 summary->set_in(0, Location::RequiresFpuRegister()); 5727 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5688 summary->set_in(1, Location::RequiresFpuRegister()); 5728 Location::RequiresRegister()));
5689 if (FLAG_throw_on_javascript_int_overflow) { 5729 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5690 summary->set_temp(0, Location::RequiresRegister()); 5730 Location::RequiresRegister()));
5691 }
5692 summary->set_out(0, Location::SameAsFirstInput()); 5731 summary->set_out(0, Location::SameAsFirstInput());
5693 return summary; 5732 return summary;
5694 } 5733 }
5695 case Token::kADD: 5734 case Token::kADD:
5696 case Token::kSUB: { 5735 case Token::kSUB: {
5697 const intptr_t kNumTemps = 2; 5736 const intptr_t kNumTemps = 0;
5698 LocationSummary* summary = 5737 LocationSummary* summary =
5699 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5738 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5700 summary->set_in(0, Location::RequiresFpuRegister()); 5739 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5701 summary->set_in(1, Location::RequiresFpuRegister()); 5740 Location::RequiresRegister()));
5702 summary->set_temp(0, Location::RequiresRegister()); 5741 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5703 summary->set_temp(1, Location::RequiresRegister()); 5742 Location::RequiresRegister()));
5704 summary->set_out(0, Location::SameAsFirstInput()); 5743 summary->set_out(0, Location::SameAsFirstInput());
5705 return summary; 5744 return summary;
5706 } 5745 }
5707 default: 5746 default:
5708 UNREACHABLE(); 5747 UNREACHABLE();
5709 return NULL; 5748 return NULL;
5710 } 5749 }
5711 } 5750 }
5712 5751
5713 5752
5714 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5753 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5715 XmmRegister left = locs()->in(0).fpu_reg(); 5754 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5716 XmmRegister right = locs()->in(1).fpu_reg(); 5755 Register left_lo = left_pair->At(0).reg();
5717 5756 Register left_hi = left_pair->At(1).reg();
5718 ASSERT(locs()->out(0).fpu_reg() == left); 5757 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5758 Register right_lo = right_pair->At(0).reg();
5759 Register right_hi = right_pair->At(1).reg();
5760 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5761 Register out_lo = out_pair->At(0).reg();
5762 Register out_hi = out_pair->At(1).reg();
5763 ASSERT(out_lo == left_lo);
5764 ASSERT(out_hi == left_hi);
5719 5765
5720 Label* deopt = NULL; 5766 Label* deopt = NULL;
5721 if (FLAG_throw_on_javascript_int_overflow) { 5767 if (FLAG_throw_on_javascript_int_overflow) {
5722 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5768 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5723 } 5769 }
5724 switch (op_kind()) { 5770 switch (op_kind()) {
5725 case Token::kBIT_AND: __ andpd(left, right); break; 5771 case Token::kBIT_AND:
5726 case Token::kBIT_OR: __ orpd(left, right); break; 5772 __ andl(left_lo, right_lo);
5727 case Token::kBIT_XOR: __ xorpd(left, right); break; 5773 __ andl(left_hi, right_hi);
5774 break;
5775 case Token::kBIT_OR:
5776 __ orl(left_lo, right_lo);
5777 __ orl(left_hi, right_hi);
5778 break;
5779 case Token::kBIT_XOR:
5780 __ xorl(left_lo, right_lo);
5781 __ xorl(left_hi, right_hi);
5782 break;
5728 case Token::kADD: 5783 case Token::kADD:
5729 case Token::kSUB: { 5784 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) { 5785 if (!FLAG_throw_on_javascript_int_overflow) {
5733 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5786 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5734 } 5787 }
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) { 5788 if (op_kind() == Token::kADD) {
5742 __ addl(Address(ESP, 0), lo); 5789 __ addl(left_lo, right_lo);
5743 __ adcl(Address(ESP, 1 * kWordSize), hi); 5790 __ adcl(left_hi, right_hi);
5744 } else { 5791 } else {
5745 __ subl(Address(ESP, 0), lo); 5792 __ subl(left_lo, right_lo);
5746 __ sbbl(Address(ESP, 1 * kWordSize), hi); 5793 __ sbbl(left_hi, right_hi);
5747 } 5794 }
5748 __ j(OVERFLOW, &overflow); 5795 __ 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; 5796 break;
5757 } 5797 }
5758 default: UNREACHABLE(); 5798 default: UNREACHABLE();
5759 } 5799 }
5760 if (FLAG_throw_on_javascript_int_overflow) { 5800 if (FLAG_throw_on_javascript_int_overflow) {
5761 Register tmp = locs()->temp(0).reg(); 5801 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5762 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5763 } 5802 }
5764 } 5803 }
5765 5804
5766 5805
5767 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5806 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5768 const intptr_t kNumInputs = 2; 5807 const intptr_t kNumInputs = 2;
5769 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; 5808 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0;
5770 LocationSummary* summary = 5809 LocationSummary* summary =
5771 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5810 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5772 summary->set_in(0, Location::RequiresFpuRegister()); 5811 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5812 Location::RequiresRegister()));
5773 summary->set_in(1, Location::RegisterLocation(ECX)); 5813 summary->set_in(1, Location::RegisterLocation(ECX));
5774 summary->set_temp(0, Location::RequiresRegister());
5775 if (op_kind() == Token::kSHL) { 5814 if (op_kind() == Token::kSHL) {
5815 summary->set_temp(0, Location::RequiresRegister());
5776 summary->set_temp(1, Location::RequiresRegister()); 5816 summary->set_temp(1, Location::RequiresRegister());
5777 } 5817 }
5778 summary->set_out(0, Location::SameAsFirstInput()); 5818 summary->set_out(0, Location::SameAsFirstInput());
5779 return summary; 5819 return summary;
5780 } 5820 }
5781 5821
5782 5822
5783 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5823 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5784 XmmRegister left = locs()->in(0).fpu_reg(); 5824 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5785 ASSERT(locs()->in(1).reg() == ECX); 5825 Register left_lo = left_pair->At(0).reg();
5786 ASSERT(locs()->out(0).fpu_reg() == left); 5826 Register left_hi = left_pair->At(1).reg();
5827 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5828 Register out_lo = out_pair->At(0).reg();
5829 Register out_hi = out_pair->At(1).reg();
5830 ASSERT(out_lo == left_lo);
5831 ASSERT(out_hi == left_hi);
5787 5832
5788 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5833 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5789 Label done; 5834 Label done;
5790 __ testl(ECX, ECX); 5835 __ testl(ECX, ECX);
5791 __ j(ZERO, &done); // Shift by 0 is a nop. 5836 __ 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. 5837 // Deoptimize if shift count is > 31.
5795 // sarl operation masks the count to 5 bits and 5838 // sarl operation masks the count to 5 bits and
5796 // shrd is undefined with count > operand size (32) 5839 // shrd is undefined with count > operand size (32)
5797 // TODO(fschneider): Support shift counts > 31 without deoptimization. 5840 // TODO(fschneider): Support shift counts > 31 without deoptimization.
5798 __ SmiUntag(ECX); 5841 __ SmiUntag(ECX);
5799 const Immediate& kCountLimit = Immediate(31); 5842 const Immediate& kCountLimit = Immediate(31);
5800 __ cmpl(ECX, kCountLimit); 5843 __ cmpl(ECX, kCountLimit);
5801 __ j(ABOVE, deopt); 5844 __ j(ABOVE, deopt);
5802 switch (op_kind()) { 5845 switch (op_kind()) {
5803 case Token::kSHR: { 5846 case Token::kSHR: {
5804 Register temp = locs()->temp(0).reg(); 5847 __ shrd(left_lo, left_hi); // Shift count in CL.
5805 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. 5848 __ 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; 5849 break;
5809 } 5850 }
5810 case Token::kSHL: { 5851 case Token::kSHL: {
5811 Register temp1 = locs()->temp(0).reg(); 5852 Register temp1 = locs()->temp(0).reg();
5812 Register temp2 = locs()->temp(1).reg(); 5853 Register temp2 = locs()->temp(1).reg();
5813 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. 5854 __ movl(temp1, left_lo); // Low 32 bits.
5814 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. 5855 __ movl(temp2, left_hi); // High 32 bits.
5815 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. 5856 __ shll(left_lo, ECX); // Shift count in CL.
5816 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. 5857 __ shld(left_hi, temp1); // Shift count in CL.
5817 // Check for overflow by shifting back the high 32 bits 5858 // Check for overflow by shifting back the high 32 bits
5818 // and comparing with the input. 5859 // and comparing with the input.
5819 __ movl(temp1, temp2); 5860 __ movl(temp1, temp2);
5820 __ movl(temp2, Address(ESP, 1 * kWordSize)); 5861 __ movl(temp2, left_hi);
5821 __ sarl(temp2, ECX); 5862 __ sarl(temp2, ECX);
5822 __ cmpl(temp1, temp2); 5863 __ cmpl(temp1, temp2);
5823 __ j(NOT_EQUAL, deopt); 5864 __ j(NOT_EQUAL, deopt);
5824 break; 5865 break;
5825 } 5866 }
5826 default: 5867 default:
5827 UNREACHABLE(); 5868 UNREACHABLE();
5828 break; 5869 break;
5829 } 5870 }
5830 __ movq(left, Address(ESP, 0));
5831 __ addl(ESP, Immediate(2 * kWordSize));
5832 __ Bind(&done); 5871 __ Bind(&done);
5833 if (FLAG_throw_on_javascript_int_overflow) { 5872 if (FLAG_throw_on_javascript_int_overflow) {
5834 Register tmp = locs()->temp(0).reg(); 5873 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5835 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
5836 } 5874 }
5837 } 5875 }
5838 5876
5839 5877
5840 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5878 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5841 const intptr_t kNumInputs = 1; 5879 const intptr_t kNumInputs = 1;
5842 const intptr_t kNumTemps = 5880 const intptr_t kNumTemps = 0;
5843 FLAG_throw_on_javascript_int_overflow ? 1 : 0;
5844 LocationSummary* summary = 5881 LocationSummary* summary =
5845 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5882 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5846 summary->set_in(0, Location::RequiresFpuRegister()); 5883 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5884 Location::RequiresRegister()));
5847 summary->set_out(0, Location::SameAsFirstInput()); 5885 summary->set_out(0, Location::SameAsFirstInput());
5848 if (FLAG_throw_on_javascript_int_overflow) { 5886 if (FLAG_throw_on_javascript_int_overflow) {
5849 summary->set_temp(0, Location::RequiresRegister()); 5887 summary->set_temp(0, Location::RequiresRegister());
5850 } 5888 }
5851 return summary; 5889 return summary;
5852 } 5890 }
5853 5891
5854 5892
5855 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5893 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5856 ASSERT(op_kind() == Token::kBIT_NOT); 5894 ASSERT(op_kind() == Token::kBIT_NOT);
5857 XmmRegister value = locs()->in(0).fpu_reg(); 5895 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5858 ASSERT(value == locs()->out(0).fpu_reg()); 5896 Register left_lo = left_pair->At(0).reg();
5897 Register left_hi = left_pair->At(1).reg();
5898 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5899 Register out_lo = out_pair->At(0).reg();
5900 Register out_hi = out_pair->At(1).reg();
5901 ASSERT(out_lo == left_lo);
5902 ASSERT(out_hi == left_hi);
5903
5859 Label* deopt = NULL; 5904 Label* deopt = NULL;
5860 if (FLAG_throw_on_javascript_int_overflow) { 5905 if (FLAG_throw_on_javascript_int_overflow) {
5861 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 5906 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
5862 } 5907 }
5863 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 5908
5864 __ pxor(value, XMM0); 5909 __ notl(left_lo);
5910 __ notl(left_hi);
5911
5865 if (FLAG_throw_on_javascript_int_overflow) { 5912 if (FLAG_throw_on_javascript_int_overflow) {
5866 Register tmp = locs()->temp(0).reg(); 5913 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5867 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp);
5868 } 5914 }
5869 } 5915 }
5870 5916
5871 5917
5872 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 5918 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5873 return new LocationSummary(0, 0, LocationSummary::kCall); 5919 return new LocationSummary(0, 0, LocationSummary::kCall);
5874 } 5920 }
5875 5921
5876 5922
5877 5923
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
6192 PcDescriptors::kOther, 6238 PcDescriptors::kOther,
6193 locs()); 6239 locs());
6194 __ Drop(ArgumentCount()); // Discard arguments. 6240 __ Drop(ArgumentCount()); // Discard arguments.
6195 } 6241 }
6196 6242
6197 } // namespace dart 6243 } // namespace dart
6198 6244
6199 #undef __ 6245 #undef __
6200 6246
6201 #endif // defined TARGET_ARCH_IA32 6247 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698