OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_smi); | 5699 __ j(ABOVE_EQUAL, ¬_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(¬_smi); | 5705 __ Bind(¬_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 Loading... |
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 |
OLD | NEW |