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 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
| 1026 Location::RegisterLocation(EDX))); |
1023 } else { | 1027 } else { |
| 1028 ASSERT(representation() == kTagged); |
1024 locs->set_out(0, Location::RequiresRegister()); | 1029 locs->set_out(0, Location::RequiresRegister()); |
1025 } | 1030 } |
1026 return locs; | 1031 return locs; |
1027 } | 1032 } |
1028 | 1033 |
1029 | 1034 |
1030 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1035 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1031 Register array = locs()->in(0).reg(); | 1036 Register array = locs()->in(0).reg(); |
1032 Location index = locs()->in(1); | 1037 Location index = locs()->in(1); |
1033 | 1038 |
1034 Address element_address(kNoRegister, 0); | 1039 Address element_address(kNoRegister, 0); |
1035 if (IsExternal()) { | 1040 if (IsExternal()) { |
1036 element_address = index.IsRegister() | 1041 element_address = index.IsRegister() |
1037 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1042 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1038 index_scale(), array, index.reg()) | 1043 index_scale(), array, index.reg()) |
1039 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1044 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1040 index_scale(), array, Smi::Cast(index.constant()).Value()); | 1045 index_scale(), array, Smi::Cast(index.constant()).Value()); |
1041 } else { | 1046 } else { |
1042 ASSERT(this->array()->definition()->representation() == kTagged); | 1047 ASSERT(this->array()->definition()->representation() == kTagged); |
1043 element_address = index.IsRegister() | 1048 element_address = index.IsRegister() |
1044 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1049 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1045 class_id(), index_scale(), array, index.reg()) | 1050 class_id(), index_scale(), array, index.reg()) |
1046 : FlowGraphCompiler::ElementAddressForIntIndex( | 1051 : FlowGraphCompiler::ElementAddressForIntIndex( |
1047 class_id(), index_scale(), array, | 1052 class_id(), index_scale(), array, |
1048 Smi::Cast(index.constant()).Value()); | 1053 Smi::Cast(index.constant()).Value()); |
1049 } | 1054 } |
1050 | 1055 |
1051 if ((representation() == kUnboxedDouble) || | 1056 if ((representation() == kUnboxedDouble) || |
1052 (representation() == kUnboxedMint) || | |
1053 (representation() == kUnboxedFloat32x4) || | 1057 (representation() == kUnboxedFloat32x4) || |
1054 (representation() == kUnboxedInt32x4) || | 1058 (representation() == kUnboxedInt32x4) || |
1055 (representation() == kUnboxedFloat64x2)) { | 1059 (representation() == kUnboxedFloat64x2)) { |
1056 XmmRegister result = locs()->out(0).fpu_reg(); | 1060 XmmRegister result = locs()->out(0).fpu_reg(); |
1057 if ((index_scale() == 1) && index.IsRegister()) { | 1061 if ((index_scale() == 1) && index.IsRegister()) { |
1058 __ SmiUntag(index.reg()); | 1062 __ SmiUntag(index.reg()); |
1059 } | 1063 } |
1060 switch (class_id()) { | 1064 switch (class_id()) { |
1061 case kTypedDataInt32ArrayCid: | |
1062 __ movss(result, element_address); | |
1063 __ pmovsxdq(result, result); | |
1064 break; | |
1065 case kTypedDataUint32ArrayCid: | |
1066 __ xorpd(result, result); | |
1067 __ movss(result, element_address); | |
1068 break; | |
1069 case kTypedDataFloat32ArrayCid: | 1065 case kTypedDataFloat32ArrayCid: |
1070 __ movss(result, element_address); | 1066 __ movss(result, element_address); |
1071 break; | 1067 break; |
1072 case kTypedDataFloat64ArrayCid: | 1068 case kTypedDataFloat64ArrayCid: |
1073 __ movsd(result, element_address); | 1069 __ movsd(result, element_address); |
1074 break; | 1070 break; |
1075 case kTypedDataInt32x4ArrayCid: | 1071 case kTypedDataInt32x4ArrayCid: |
1076 case kTypedDataFloat32x4ArrayCid: | 1072 case kTypedDataFloat32x4ArrayCid: |
1077 case kTypedDataFloat64x2ArrayCid: | 1073 case kTypedDataFloat64x2ArrayCid: |
1078 __ movups(result, element_address); | 1074 __ movups(result, element_address); |
1079 break; | 1075 break; |
| 1076 default: |
| 1077 UNREACHABLE(); |
1080 } | 1078 } |
1081 return; | 1079 return; |
1082 } | 1080 } |
1083 | 1081 |
| 1082 if (representation() == kUnboxedMint) { |
| 1083 ASSERT(locs()->out(0).IsPairLocation()); |
| 1084 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 1085 Register result1 = result_pair->At(0).reg(); |
| 1086 Register result2 = result_pair->At(1).reg(); |
| 1087 ASSERT(result1 == EAX); |
| 1088 ASSERT(result2 == EDX); |
| 1089 if ((index_scale() == 1) && index.IsRegister()) { |
| 1090 __ SmiUntag(index.reg()); |
| 1091 } |
| 1092 switch (class_id()) { |
| 1093 case kTypedDataInt32ArrayCid: |
| 1094 __ movl(result1, element_address); |
| 1095 __ cdq(); |
| 1096 break; |
| 1097 case kTypedDataUint32ArrayCid: |
| 1098 __ movl(result1, element_address); |
| 1099 __ xorl(result2, result2); |
| 1100 break; |
| 1101 default: |
| 1102 UNREACHABLE(); |
| 1103 } |
| 1104 return; |
| 1105 } |
| 1106 |
| 1107 ASSERT(representation() == kTagged); |
| 1108 |
1084 Register result = locs()->out(0).reg(); | 1109 Register result = locs()->out(0).reg(); |
1085 if ((index_scale() == 1) && index.IsRegister()) { | 1110 if ((index_scale() == 1) && index.IsRegister()) { |
1086 __ SmiUntag(index.reg()); | 1111 __ SmiUntag(index.reg()); |
1087 } | 1112 } |
1088 switch (class_id()) { | 1113 switch (class_id()) { |
1089 case kTypedDataInt8ArrayCid: | 1114 case kTypedDataInt8ArrayCid: |
1090 ASSERT(index_scale() == 1); | 1115 ASSERT(index_scale() == 1); |
1091 __ movsxb(result, element_address); | 1116 __ movsxb(result, element_address); |
1092 __ SmiTag(result); | 1117 __ SmiTag(result); |
1093 break; | 1118 break; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
1326 } | 1356 } |
1327 case kTypedDataInt32ArrayCid: | 1357 case kTypedDataInt32ArrayCid: |
1328 case kTypedDataUint32ArrayCid: | 1358 case kTypedDataUint32ArrayCid: |
1329 if (value()->IsSmiValue()) { | 1359 if (value()->IsSmiValue()) { |
1330 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1360 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1331 Register value = locs()->in(2).reg(); | 1361 Register value = locs()->in(2).reg(); |
1332 __ SmiUntag(value); | 1362 __ SmiUntag(value); |
1333 __ movl(element_address, value); | 1363 __ movl(element_address, value); |
1334 } else { | 1364 } else { |
1335 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1365 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1336 __ movss(element_address, locs()->in(2).fpu_reg()); | 1366 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
| 1367 Register value1 = value_pair->At(0).reg(); |
| 1368 __ movl(element_address, value1); |
1337 } | 1369 } |
1338 break; | 1370 break; |
1339 case kTypedDataFloat32ArrayCid: | 1371 case kTypedDataFloat32ArrayCid: |
1340 __ movss(element_address, locs()->in(2).fpu_reg()); | 1372 __ movss(element_address, locs()->in(2).fpu_reg()); |
1341 break; | 1373 break; |
1342 case kTypedDataFloat64ArrayCid: | 1374 case kTypedDataFloat64ArrayCid: |
1343 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1375 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1344 break; | 1376 break; |
1345 case kTypedDataInt32x4ArrayCid: | 1377 case kTypedDataInt32x4ArrayCid: |
1346 case kTypedDataFloat32x4ArrayCid: | 1378 case kTypedDataFloat32x4ArrayCid: |
(...skipping 4080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5427 Register length = length_loc.reg(); | 5459 Register length = length_loc.reg(); |
5428 Register index = index_loc.reg(); | 5460 Register index = index_loc.reg(); |
5429 __ cmpl(index, length); | 5461 __ cmpl(index, length); |
5430 __ j(ABOVE_EQUAL, deopt); | 5462 __ j(ABOVE_EQUAL, deopt); |
5431 } | 5463 } |
5432 } | 5464 } |
5433 | 5465 |
5434 | 5466 |
5435 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { | 5467 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { |
5436 const intptr_t kNumInputs = 1; | 5468 const intptr_t kNumInputs = 1; |
5437 const intptr_t value_cid = value()->Type()->ToCid(); | 5469 const intptr_t kNumTemps = 0; |
5438 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid)); | |
5439 const bool needs_writable_input = (value_cid == kSmiCid); | |
5440 const intptr_t kNumTemps = needs_temp ? 1 : 0; | |
5441 LocationSummary* summary = | 5470 LocationSummary* summary = |
5442 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5471 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5443 summary->set_in(0, needs_writable_input | 5472 summary->set_in(0, Location::RequiresRegister()); |
5444 ? Location::WritableRegister() | 5473 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5445 : Location::RequiresRegister()); | 5474 Location::RegisterLocation(EDX))); |
5446 if (needs_temp) { | |
5447 summary->set_temp(0, Location::RequiresRegister()); | |
5448 } | |
5449 summary->set_out(0, Location::RequiresFpuRegister()); | |
5450 return summary; | 5475 return summary; |
5451 } | 5476 } |
5452 | 5477 |
5453 | 5478 |
5454 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5479 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5455 const intptr_t value_cid = value()->Type()->ToCid(); | 5480 const intptr_t value_cid = value()->Type()->ToCid(); |
5456 const Register value = locs()->in(0).reg(); | 5481 const Register value = locs()->in(0).reg(); |
5457 const XmmRegister result = locs()->out(0).fpu_reg(); | 5482 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 5483 Register result1 = result_pair->At(0).reg(); |
| 5484 Register result2 = result_pair->At(1).reg(); |
| 5485 |
| 5486 ASSERT(value != result1); |
| 5487 ASSERT(value != result2); |
| 5488 ASSERT(result1 == EAX); |
| 5489 ASSERT(result2 == EDX); |
5458 | 5490 |
5459 if (value_cid == kMintCid) { | 5491 if (value_cid == kMintCid) { |
5460 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5492 __ movl(result1, FieldAddress(value, Mint::value_offset())); |
| 5493 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize)); |
5461 } else if (value_cid == kSmiCid) { | 5494 } else if (value_cid == kSmiCid) { |
5462 __ SmiUntag(value); // Untag input before conversion. | 5495 __ movl(result1, value); |
5463 __ movd(result, value); | 5496 __ SmiUntag(result1); |
5464 __ pmovsxdq(result, result); | 5497 // Sign extend into result2. |
| 5498 __ cdq(); |
5465 } else { | 5499 } else { |
5466 Register temp = locs()->temp(0).reg(); | |
5467 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5500 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
5468 ICData::kDeoptUnboxInteger); | 5501 ICData::kDeoptUnboxInteger); |
5469 Label is_smi, done; | 5502 Label is_smi, done; |
5470 __ testl(value, Immediate(kSmiTagMask)); | 5503 __ testl(value, Immediate(kSmiTagMask)); |
5471 __ j(ZERO, &is_smi); | 5504 __ j(ZERO, &is_smi); |
5472 __ CompareClassId(value, kMintCid, temp); | 5505 __ CompareClassId(value, kMintCid, result1); |
5473 __ j(NOT_EQUAL, deopt); | 5506 __ j(NOT_EQUAL, deopt); |
5474 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5507 __ movl(result1, FieldAddress(value, Mint::value_offset())); |
| 5508 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize)); |
5475 __ jmp(&done); | 5509 __ jmp(&done); |
5476 __ Bind(&is_smi); | 5510 __ Bind(&is_smi); |
5477 __ movl(temp, value); | 5511 __ movl(result1, value); |
5478 __ SmiUntag(temp); | 5512 __ SmiUntag(result1); |
5479 __ movd(result, temp); | 5513 // Sign extend into result2. |
5480 __ pmovsxdq(result, result); | 5514 __ cdq(); |
5481 __ Bind(&done); | 5515 __ Bind(&done); |
5482 } | 5516 } |
5483 } | 5517 } |
5484 | 5518 |
5485 | 5519 |
5486 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { | 5520 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { |
5487 const intptr_t kNumInputs = 1; | 5521 const intptr_t kNumInputs = 1; |
5488 const intptr_t kNumTemps = 2; | 5522 const intptr_t kNumTemps = 1; |
5489 LocationSummary* summary = | 5523 LocationSummary* summary = |
5490 new LocationSummary(kNumInputs, | 5524 new LocationSummary(kNumInputs, |
5491 kNumTemps, | 5525 kNumTemps, |
5492 LocationSummary::kCallOnSlowPath); | 5526 LocationSummary::kCallOnSlowPath); |
5493 summary->set_in(0, Location::RequiresFpuRegister()); | 5527 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX), |
5494 summary->set_temp(0, Location::RegisterLocation(EAX)); | 5528 Location::RegisterLocation(EDX))); |
5495 summary->set_temp(1, Location::RegisterLocation(EDX)); | 5529 summary->set_temp(0, Location::RequiresRegister()); |
5496 // TODO(fschneider): Save one temp by using result register as a temp. | |
5497 summary->set_out(0, Location::RequiresRegister()); | 5530 summary->set_out(0, Location::RequiresRegister()); |
5498 return summary; | 5531 return summary; |
5499 } | 5532 } |
5500 | 5533 |
5501 | 5534 |
5502 class BoxIntegerSlowPath : public SlowPathCode { | 5535 class BoxIntegerSlowPath : public SlowPathCode { |
5503 public: | 5536 public: |
5504 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5537 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
5505 : instruction_(instruction) { } | 5538 : instruction_(instruction) { } |
5506 | 5539 |
(...skipping 21 matching lines...) Expand all Loading... |
5528 } | 5561 } |
5529 | 5562 |
5530 private: | 5563 private: |
5531 BoxIntegerInstr* instruction_; | 5564 BoxIntegerInstr* instruction_; |
5532 }; | 5565 }; |
5533 | 5566 |
5534 | 5567 |
5535 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5568 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5536 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5569 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
5537 compiler->AddSlowPathCode(slow_path); | 5570 compiler->AddSlowPathCode(slow_path); |
| 5571 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 5572 Register value1 = value_pair->At(0).reg(); |
| 5573 Register value2 = value_pair->At(1).reg(); |
| 5574 Register out_reg = locs()->out(0).reg(); |
5538 | 5575 |
5539 Register out_reg = locs()->out(0).reg(); | 5576 ASSERT(value1 == EAX); |
5540 XmmRegister value = locs()->in(0).fpu_reg(); | 5577 ASSERT(value2 == EDX); |
| 5578 |
| 5579 // Copy value2 into out_reg as a temporary. |
| 5580 // We modify value1 but restore it before using it. |
| 5581 __ movl(out_reg, value2); |
5541 | 5582 |
5542 // Unboxed operations produce smis or mint-sized values. | 5583 // Unboxed operations produce smis or mint-sized values. |
5543 // Check if value fits into a smi. | 5584 // Check if value fits into a smi. |
5544 Label not_smi, done; | 5585 Label not_smi, done; |
5545 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 5586 |
5546 __ pextrd(EAX, value, Immediate(0)); // Lower half. | |
5547 // 1. Compute (x + -kMinSmi) which has to be in the range | 5587 // 1. Compute (x + -kMinSmi) which has to be in the range |
5548 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 5588 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
5549 __ addl(EAX, Immediate(0x40000000)); | 5589 __ addl(value1, Immediate(0x40000000)); |
5550 __ adcl(EDX, Immediate(0)); | 5590 __ adcl(out_reg, Immediate(0)); |
5551 // 2. Unsigned compare to -kMinSmi+kMaxSmi. | 5591 // 2. Unsigned compare to -kMinSmi+kMaxSmi. |
5552 __ cmpl(EAX, Immediate(0x80000000)); | 5592 __ cmpl(value1, Immediate(0x80000000)); |
5553 __ sbbl(EDX, Immediate(0)); | 5593 __ sbbl(out_reg, Immediate(0)); |
5554 __ j(ABOVE_EQUAL, ¬_smi); | 5594 __ j(ABOVE_EQUAL, ¬_smi); |
5555 // 3. Restore lower half if result is a smi. | 5595 // 3. Restore lower half if result is a smi. |
5556 __ subl(EAX, Immediate(0x40000000)); | 5596 __ subl(value1, Immediate(0x40000000)); |
5557 | 5597 __ movl(out_reg, value1); |
5558 __ SmiTag(EAX); | 5598 __ SmiTag(out_reg); |
5559 __ movl(out_reg, EAX); | |
5560 __ jmp(&done); | 5599 __ jmp(&done); |
5561 | |
5562 __ Bind(¬_smi); | 5600 __ Bind(¬_smi); |
5563 __ TryAllocate( | 5601 __ TryAllocate( |
5564 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | 5602 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
5565 slow_path->entry_label(), | 5603 slow_path->entry_label(), |
5566 Assembler::kFarJump, | 5604 Assembler::kFarJump, |
5567 out_reg, | 5605 out_reg, |
5568 kNoRegister); | 5606 kNoRegister); |
5569 __ Bind(slow_path->exit_label()); | 5607 __ Bind(slow_path->exit_label()); |
5570 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); | 5608 // 3. Restore lower half of input before using it. |
| 5609 __ subl(value1, Immediate(0x40000000)); |
| 5610 __ movl(FieldAddress(out_reg, Mint::value_offset()), value1); |
| 5611 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value2); |
5571 __ Bind(&done); | 5612 __ Bind(&done); |
5572 } | 5613 } |
5573 | 5614 |
5574 | 5615 |
5575 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5616 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5576 const intptr_t kNumInputs = 2; | 5617 const intptr_t kNumInputs = 2; |
5577 switch (op_kind()) { | 5618 switch (op_kind()) { |
5578 case Token::kBIT_AND: | 5619 case Token::kBIT_AND: |
5579 case Token::kBIT_OR: | 5620 case Token::kBIT_OR: |
5580 case Token::kBIT_XOR: { | 5621 case Token::kBIT_XOR: { |
5581 const intptr_t kNumTemps = | 5622 const intptr_t kNumTemps = 0; |
5582 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
5583 LocationSummary* summary = | 5623 LocationSummary* summary = |
5584 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5624 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5585 summary->set_in(0, Location::RequiresFpuRegister()); | 5625 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5586 summary->set_in(1, Location::RequiresFpuRegister()); | 5626 Location::RequiresRegister())); |
5587 if (FLAG_throw_on_javascript_int_overflow) { | 5627 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5588 summary->set_temp(0, Location::RequiresRegister()); | 5628 Location::RequiresRegister())); |
5589 } | |
5590 summary->set_out(0, Location::SameAsFirstInput()); | 5629 summary->set_out(0, Location::SameAsFirstInput()); |
5591 return summary; | 5630 return summary; |
5592 } | 5631 } |
5593 case Token::kADD: | 5632 case Token::kADD: |
5594 case Token::kSUB: { | 5633 case Token::kSUB: { |
5595 const intptr_t kNumTemps = 2; | 5634 const intptr_t kNumTemps = 0; |
5596 LocationSummary* summary = | 5635 LocationSummary* summary = |
5597 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5636 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5598 summary->set_in(0, Location::RequiresFpuRegister()); | 5637 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5599 summary->set_in(1, Location::RequiresFpuRegister()); | 5638 Location::RequiresRegister())); |
5600 summary->set_temp(0, Location::RequiresRegister()); | 5639 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5601 summary->set_temp(1, Location::RequiresRegister()); | 5640 Location::RequiresRegister())); |
5602 summary->set_out(0, Location::SameAsFirstInput()); | 5641 summary->set_out(0, Location::SameAsFirstInput()); |
5603 return summary; | 5642 return summary; |
5604 } | 5643 } |
5605 default: | 5644 default: |
5606 UNREACHABLE(); | 5645 UNREACHABLE(); |
5607 return NULL; | 5646 return NULL; |
5608 } | 5647 } |
5609 } | 5648 } |
5610 | 5649 |
5611 | 5650 |
5612 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5651 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5613 XmmRegister left = locs()->in(0).fpu_reg(); | 5652 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5614 XmmRegister right = locs()->in(1).fpu_reg(); | 5653 Register left1 = left_pair->At(0).reg(); |
5615 | 5654 Register left2 = left_pair->At(1).reg(); |
5616 ASSERT(locs()->out(0).fpu_reg() == left); | 5655 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
| 5656 Register right1 = right_pair->At(0).reg(); |
| 5657 Register right2 = right_pair->At(1).reg(); |
| 5658 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5659 Register out1 = out_pair->At(0).reg(); |
| 5660 Register out2 = out_pair->At(1).reg(); |
| 5661 ASSERT(out1 == left1); |
| 5662 ASSERT(out2 == left2); |
5617 | 5663 |
5618 Label* deopt = NULL; | 5664 Label* deopt = NULL; |
5619 if (FLAG_throw_on_javascript_int_overflow) { | 5665 if (FLAG_throw_on_javascript_int_overflow) { |
5620 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5666 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5621 } | 5667 } |
5622 switch (op_kind()) { | 5668 switch (op_kind()) { |
5623 case Token::kBIT_AND: __ andpd(left, right); break; | 5669 case Token::kBIT_AND: |
5624 case Token::kBIT_OR: __ orpd(left, right); break; | 5670 __ andl(left1, right1); |
5625 case Token::kBIT_XOR: __ xorpd(left, right); break; | 5671 __ andl(left2, right2); |
| 5672 break; |
| 5673 case Token::kBIT_OR: |
| 5674 __ orl(left1, right1); |
| 5675 __ orl(left2, right2); |
| 5676 break; |
| 5677 case Token::kBIT_XOR: |
| 5678 __ xorl(left1, right1); |
| 5679 __ xorl(left2, right2); |
| 5680 break; |
5626 case Token::kADD: | 5681 case Token::kADD: |
5627 case Token::kSUB: { | 5682 case Token::kSUB: { |
5628 Register lo = locs()->temp(0).reg(); | |
5629 Register hi = locs()->temp(1).reg(); | |
5630 if (!FLAG_throw_on_javascript_int_overflow) { | 5683 if (!FLAG_throw_on_javascript_int_overflow) { |
5631 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5684 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5632 } | 5685 } |
5633 | |
5634 Label done, overflow; | |
5635 __ pextrd(lo, right, Immediate(0)); // Lower half | |
5636 __ pextrd(hi, right, Immediate(1)); // Upper half | |
5637 __ subl(ESP, Immediate(2 * kWordSize)); | |
5638 __ movq(Address(ESP, 0), left); | |
5639 if (op_kind() == Token::kADD) { | 5686 if (op_kind() == Token::kADD) { |
5640 __ addl(Address(ESP, 0), lo); | 5687 __ addl(left1, right1); |
5641 __ adcl(Address(ESP, 1 * kWordSize), hi); | 5688 __ adcl(left2, right2); |
5642 } else { | 5689 } else { |
5643 __ subl(Address(ESP, 0), lo); | 5690 __ subl(left1, right1); |
5644 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 5691 __ sbbl(left2, right2); |
5645 } | 5692 } |
5646 __ j(OVERFLOW, &overflow); | 5693 __ j(OVERFLOW, deopt); |
5647 __ movq(left, Address(ESP, 0)); | |
5648 __ addl(ESP, Immediate(2 * kWordSize)); | |
5649 __ jmp(&done); | |
5650 __ Bind(&overflow); | |
5651 __ addl(ESP, Immediate(2 * kWordSize)); | |
5652 __ jmp(deopt); | |
5653 __ Bind(&done); | |
5654 break; | 5694 break; |
5655 } | 5695 } |
5656 default: UNREACHABLE(); | 5696 default: UNREACHABLE(); |
5657 } | 5697 } |
5658 if (FLAG_throw_on_javascript_int_overflow) { | 5698 if (FLAG_throw_on_javascript_int_overflow) { |
5659 Register tmp = locs()->temp(0).reg(); | 5699 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2); |
5660 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
5661 } | 5700 } |
5662 } | 5701 } |
5663 | 5702 |
5664 | 5703 |
5665 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { | 5704 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { |
5666 const intptr_t kNumInputs = 2; | 5705 const intptr_t kNumInputs = 2; |
5667 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 5706 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0; |
5668 LocationSummary* summary = | 5707 LocationSummary* summary = |
5669 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5708 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5670 summary->set_in(0, Location::RequiresFpuRegister()); | 5709 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5710 Location::RequiresRegister())); |
5671 summary->set_in(1, Location::RegisterLocation(ECX)); | 5711 summary->set_in(1, Location::RegisterLocation(ECX)); |
5672 summary->set_temp(0, Location::RequiresRegister()); | |
5673 if (op_kind() == Token::kSHL) { | 5712 if (op_kind() == Token::kSHL) { |
| 5713 summary->set_temp(0, Location::RequiresRegister()); |
5674 summary->set_temp(1, Location::RequiresRegister()); | 5714 summary->set_temp(1, Location::RequiresRegister()); |
5675 } | 5715 } |
5676 summary->set_out(0, Location::SameAsFirstInput()); | 5716 summary->set_out(0, Location::SameAsFirstInput()); |
5677 return summary; | 5717 return summary; |
5678 } | 5718 } |
5679 | 5719 |
5680 | 5720 |
5681 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5721 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5682 XmmRegister left = locs()->in(0).fpu_reg(); | 5722 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5683 ASSERT(locs()->in(1).reg() == ECX); | 5723 Register left1 = left_pair->At(0).reg(); |
5684 ASSERT(locs()->out(0).fpu_reg() == left); | 5724 Register left2 = left_pair->At(1).reg(); |
| 5725 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5726 Register out1 = out_pair->At(0).reg(); |
| 5727 Register out2 = out_pair->At(1).reg(); |
| 5728 ASSERT(out1 == left1); |
| 5729 ASSERT(out2 == left2); |
5685 | 5730 |
5686 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 5731 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
5687 Label done; | 5732 Label done; |
5688 __ testl(ECX, ECX); | 5733 __ testl(ECX, ECX); |
5689 __ j(ZERO, &done); // Shift by 0 is a nop. | 5734 __ j(ZERO, &done); // Shift by 0 is a nop. |
5690 __ subl(ESP, Immediate(2 * kWordSize)); | |
5691 __ movq(Address(ESP, 0), left); | |
5692 // Deoptimize if shift count is > 31. | 5735 // Deoptimize if shift count is > 31. |
5693 // sarl operation masks the count to 5 bits and | 5736 // sarl operation masks the count to 5 bits and |
5694 // shrd is undefined with count > operand size (32) | 5737 // shrd is undefined with count > operand size (32) |
5695 // TODO(fschneider): Support shift counts > 31 without deoptimization. | 5738 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
5696 __ SmiUntag(ECX); | 5739 __ SmiUntag(ECX); |
5697 const Immediate& kCountLimit = Immediate(31); | 5740 const Immediate& kCountLimit = Immediate(31); |
5698 __ cmpl(ECX, kCountLimit); | 5741 __ cmpl(ECX, kCountLimit); |
5699 __ j(ABOVE, deopt); | 5742 __ j(ABOVE, deopt); |
5700 switch (op_kind()) { | 5743 switch (op_kind()) { |
5701 case Token::kSHR: { | 5744 case Token::kSHR: { |
5702 Register temp = locs()->temp(0).reg(); | 5745 __ shrd(left1, left2); // Shift count in CL. |
5703 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. | 5746 __ sarl(left2, ECX); // Shift count in CL. |
5704 __ shrd(Address(ESP, 0), temp); // Shift count in CL. | |
5705 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. | |
5706 break; | 5747 break; |
5707 } | 5748 } |
5708 case Token::kSHL: { | 5749 case Token::kSHL: { |
5709 Register temp1 = locs()->temp(0).reg(); | 5750 Register temp1 = locs()->temp(0).reg(); |
5710 Register temp2 = locs()->temp(1).reg(); | 5751 Register temp2 = locs()->temp(1).reg(); |
5711 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. | 5752 __ movl(temp1, left1); // Low 32 bits. |
5712 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. | 5753 __ movl(temp2, left2); // High 32 bits. |
5713 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. | 5754 __ shll(left1, ECX); // Shift count in CL. |
5714 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. | 5755 __ shld(left2, temp1); // Shift count in CL. |
5715 // Check for overflow by shifting back the high 32 bits | 5756 // Check for overflow by shifting back the high 32 bits |
5716 // and comparing with the input. | 5757 // and comparing with the input. |
5717 __ movl(temp1, temp2); | 5758 __ movl(temp1, temp2); |
5718 __ movl(temp2, Address(ESP, 1 * kWordSize)); | 5759 __ movl(temp2, left2); |
5719 __ sarl(temp2, ECX); | 5760 __ sarl(temp2, ECX); |
5720 __ cmpl(temp1, temp2); | 5761 __ cmpl(temp1, temp2); |
5721 __ j(NOT_EQUAL, deopt); | 5762 __ j(NOT_EQUAL, deopt); |
5722 break; | 5763 break; |
5723 } | 5764 } |
5724 default: | 5765 default: |
5725 UNREACHABLE(); | 5766 UNREACHABLE(); |
5726 break; | 5767 break; |
5727 } | 5768 } |
5728 __ movq(left, Address(ESP, 0)); | |
5729 __ addl(ESP, Immediate(2 * kWordSize)); | |
5730 __ Bind(&done); | 5769 __ Bind(&done); |
5731 if (FLAG_throw_on_javascript_int_overflow) { | 5770 if (FLAG_throw_on_javascript_int_overflow) { |
5732 Register tmp = locs()->temp(0).reg(); | 5771 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2); |
5733 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
5734 } | 5772 } |
5735 } | 5773 } |
5736 | 5774 |
5737 | 5775 |
5738 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5776 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5739 const intptr_t kNumInputs = 1; | 5777 const intptr_t kNumInputs = 1; |
5740 const intptr_t kNumTemps = | 5778 const intptr_t kNumTemps = 0; |
5741 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
5742 LocationSummary* summary = | 5779 LocationSummary* summary = |
5743 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5780 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5744 summary->set_in(0, Location::RequiresFpuRegister()); | 5781 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5782 Location::RequiresRegister())); |
5745 summary->set_out(0, Location::SameAsFirstInput()); | 5783 summary->set_out(0, Location::SameAsFirstInput()); |
5746 if (FLAG_throw_on_javascript_int_overflow) { | 5784 if (FLAG_throw_on_javascript_int_overflow) { |
5747 summary->set_temp(0, Location::RequiresRegister()); | 5785 summary->set_temp(0, Location::RequiresRegister()); |
5748 } | 5786 } |
5749 return summary; | 5787 return summary; |
5750 } | 5788 } |
5751 | 5789 |
5752 | 5790 |
5753 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5791 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5754 ASSERT(op_kind() == Token::kBIT_NOT); | 5792 ASSERT(op_kind() == Token::kBIT_NOT); |
5755 XmmRegister value = locs()->in(0).fpu_reg(); | 5793 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5756 ASSERT(value == locs()->out(0).fpu_reg()); | 5794 Register left1 = left_pair->At(0).reg(); |
| 5795 Register left2 = left_pair->At(1).reg(); |
| 5796 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5797 Register out1 = out_pair->At(0).reg(); |
| 5798 Register out2 = out_pair->At(1).reg(); |
| 5799 ASSERT(out1 == left1); |
| 5800 ASSERT(out2 == left2); |
| 5801 |
5757 Label* deopt = NULL; | 5802 Label* deopt = NULL; |
5758 if (FLAG_throw_on_javascript_int_overflow) { | 5803 if (FLAG_throw_on_javascript_int_overflow) { |
5759 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 5804 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
5760 } | 5805 } |
5761 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 5806 |
5762 __ pxor(value, XMM0); | 5807 __ notl(left1); |
| 5808 __ notl(left2); |
| 5809 |
5763 if (FLAG_throw_on_javascript_int_overflow) { | 5810 if (FLAG_throw_on_javascript_int_overflow) { |
5764 Register tmp = locs()->temp(0).reg(); | 5811 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2); |
5765 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); | |
5766 } | 5812 } |
5767 } | 5813 } |
5768 | 5814 |
5769 | 5815 |
5770 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { | 5816 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { |
5771 return new LocationSummary(0, 0, LocationSummary::kCall); | 5817 return new LocationSummary(0, 0, LocationSummary::kCall); |
5772 } | 5818 } |
5773 | 5819 |
5774 | 5820 |
5775 | 5821 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6090 PcDescriptors::kOther, | 6136 PcDescriptors::kOther, |
6091 locs()); | 6137 locs()); |
6092 __ Drop(ArgumentCount()); // Discard arguments. | 6138 __ Drop(ArgumentCount()); // Discard arguments. |
6093 } | 6139 } |
6094 | 6140 |
6095 } // namespace dart | 6141 } // namespace dart |
6096 | 6142 |
6097 #undef __ | 6143 #undef __ |
6098 | 6144 |
6099 #endif // defined TARGET_ARCH_IA32 | 6145 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |