| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 ASSERT(value.IsStackSlot()); | 63 ASSERT(value.IsStackSlot()); |
| 64 const intptr_t value_offset = value.ToStackSlotOffset(); | 64 const intptr_t value_offset = value.ToStackSlotOffset(); |
| 65 __ LoadFromOffset(TMP, FP, value_offset); | 65 __ LoadFromOffset(TMP, FP, value_offset); |
| 66 __ Push(TMP); | 66 __ Push(TMP); |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 | 71 |
| 72 LocationSummary* ReturnInstr::MakeLocationSummary(Isolate* isolate, | 72 LocationSummary* ReturnInstr::MakeLocationSummary(Isolate* isolate, |
| 73 bool opt) const { | 73 bool opt) const { |
| 74 const intptr_t kNumInputs = 1; | 74 const intptr_t kNumInputs = 1; |
| 75 const intptr_t kNumTemps = 0; | 75 const intptr_t kNumTemps = 0; |
| 76 LocationSummary* locs = new(isolate) LocationSummary( | 76 LocationSummary* locs = new(isolate) LocationSummary( |
| 77 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 77 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 78 locs->set_in(0, Location::RegisterLocation(V0)); | 78 locs->set_in(0, Location::RegisterLocation(V0)); |
| 79 return locs; | 79 return locs; |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 // Attempt optimized compilation at return instruction instead of at the entry. | 83 // Attempt optimized compilation at return instruction instead of at the entry. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 114 | 114 |
| 115 static Condition NegateCondition(Condition condition) { | 115 static Condition NegateCondition(Condition condition) { |
| 116 switch (condition) { | 116 switch (condition) { |
| 117 case EQ: return NE; | 117 case EQ: return NE; |
| 118 case NE: return EQ; | 118 case NE: return EQ; |
| 119 case LT: return GE; | 119 case LT: return GE; |
| 120 case LE: return GT; | 120 case LE: return GT; |
| 121 case GT: return LE; | 121 case GT: return LE; |
| 122 case GE: return LT; | 122 case GE: return LT; |
| 123 default: | 123 default: |
| 124 OS::Print("Error: Condition not recognized: %d\n", condition); | 124 UNREACHABLE(); |
| 125 UNIMPLEMENTED(); | |
| 126 return EQ; | 125 return EQ; |
| 127 } | 126 } |
| 128 } | 127 } |
| 129 | 128 |
| 130 | 129 |
| 131 // Detect pattern when one value is zero and another is a power of 2. | 130 // Detect pattern when one value is zero and another is a power of 2. |
| 132 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 131 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 133 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 132 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 134 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 133 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 135 } | 134 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 return LocationSummary::Make(isolate, | 270 return LocationSummary::Make(isolate, |
| 272 0, | 271 0, |
| 273 Location::RequiresRegister(), | 272 Location::RequiresRegister(), |
| 274 LocationSummary::kNoCall); | 273 LocationSummary::kNoCall); |
| 275 } | 274 } |
| 276 | 275 |
| 277 | 276 |
| 278 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 277 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 279 __ TraceSimMsg("LoadLocalInstr"); | 278 __ TraceSimMsg("LoadLocalInstr"); |
| 280 Register result = locs()->out(0).reg(); | 279 Register result = locs()->out(0).reg(); |
| 281 __ lw(result, Address(FP, local().index() * kWordSize)); | 280 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
| 282 } | 281 } |
| 283 | 282 |
| 284 | 283 |
| 285 LocationSummary* StoreLocalInstr::MakeLocationSummary(Isolate* isolate, | 284 LocationSummary* StoreLocalInstr::MakeLocationSummary(Isolate* isolate, |
| 286 bool opt) const { | 285 bool opt) const { |
| 287 return LocationSummary::Make(isolate, | 286 return LocationSummary::Make(isolate, |
| 288 1, | 287 1, |
| 289 Location::SameAsFirstInput(), | 288 Location::SameAsFirstInput(), |
| 290 LocationSummary::kNoCall); | 289 LocationSummary::kNoCall); |
| 291 } | 290 } |
| 292 | 291 |
| 293 | 292 |
| 294 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 293 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 295 __ TraceSimMsg("StoreLocalInstr"); | 294 __ TraceSimMsg("StoreLocalInstr"); |
| 296 Register value = locs()->in(0).reg(); | 295 Register value = locs()->in(0).reg(); |
| 297 Register result = locs()->out(0).reg(); | 296 Register result = locs()->out(0).reg(); |
| 298 ASSERT(result == value); // Assert that register assignment is correct. | 297 ASSERT(result == value); // Assert that register assignment is correct. |
| 299 __ sw(value, Address(FP, local().index() * kWordSize)); | 298 __ StoreToOffset(value, FP, local().index() * kWordSize); |
| 300 } | 299 } |
| 301 | 300 |
| 302 | 301 |
| 303 LocationSummary* ConstantInstr::MakeLocationSummary(Isolate* isolate, | 302 LocationSummary* ConstantInstr::MakeLocationSummary(Isolate* isolate, |
| 304 bool opt) const { | 303 bool opt) const { |
| 305 return LocationSummary::Make(isolate, | 304 return LocationSummary::Make(isolate, |
| 306 0, | 305 0, |
| 307 Location::RequiresRegister(), | 306 Location::RequiresRegister(), |
| 308 LocationSummary::kNoCall); | 307 LocationSummary::kNoCall); |
| 309 } | 308 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 __ TraceSimMsg("AssertBooleanInstr"); | 420 __ TraceSimMsg("AssertBooleanInstr"); |
| 422 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 421 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 423 ASSERT(obj == result); | 422 ASSERT(obj == result); |
| 424 } | 423 } |
| 425 | 424 |
| 426 | 425 |
| 427 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, | 426 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, |
| 428 bool opt) const { | 427 bool opt) const { |
| 429 const intptr_t kNumInputs = 2; | 428 const intptr_t kNumInputs = 2; |
| 430 if (operation_cid() == kMintCid) { | 429 if (operation_cid() == kMintCid) { |
| 431 const intptr_t kNumTemps = 1; | 430 const intptr_t kNumTemps = 0; |
| 432 LocationSummary* locs = new(isolate) LocationSummary( | 431 LocationSummary* locs = new(isolate) LocationSummary( |
| 433 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 432 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 434 locs->set_in(0, Location::RequiresFpuRegister()); | 433 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 435 locs->set_in(1, Location::RequiresFpuRegister()); | 434 Location::RequiresRegister())); |
| 436 locs->set_temp(0, Location::RequiresRegister()); | 435 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 436 Location::RequiresRegister())); |
| 437 locs->set_out(0, Location::RequiresRegister()); | 437 locs->set_out(0, Location::RequiresRegister()); |
| 438 return locs; | 438 return locs; |
| 439 } | 439 } |
| 440 if (operation_cid() == kDoubleCid) { | 440 if (operation_cid() == kDoubleCid) { |
| 441 const intptr_t kNumTemps = 0; | 441 const intptr_t kNumTemps = 0; |
| 442 LocationSummary* locs = new(isolate) LocationSummary( | 442 LocationSummary* locs = new(isolate) LocationSummary( |
| 443 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 443 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 444 locs->set_in(0, Location::RequiresFpuRegister()); | 444 locs->set_in(0, Location::RequiresFpuRegister()); |
| 445 locs->set_in(1, Location::RequiresFpuRegister()); | 445 locs->set_in(1, Location::RequiresFpuRegister()); |
| 446 locs->set_out(0, Location::RequiresRegister()); | 446 locs->set_out(0, Location::RequiresRegister()); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 // Fall through or jump to the true successor. | 546 // Fall through or jump to the true successor. |
| 547 if (labels.fall_through != labels.true_label) { | 547 if (labels.fall_through != labels.true_label) { |
| 548 __ b(labels.true_label); | 548 __ b(labels.true_label); |
| 549 } | 549 } |
| 550 } | 550 } |
| 551 } | 551 } |
| 552 | 552 |
| 553 | 553 |
| 554 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 554 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 555 const LocationSummary& locs, | 555 const LocationSummary& locs, |
| 556 Token::Kind kind, | 556 Token::Kind kind) { |
| 557 BranchLabels labels) { | |
| 558 __ TraceSimMsg("EmitSmiComparisonOp"); | 557 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 559 __ Comment("EmitSmiComparisonOp"); | 558 __ Comment("EmitSmiComparisonOp"); |
| 560 Location left = locs.in(0); | 559 Location left = locs.in(0); |
| 561 Location right = locs.in(1); | 560 Location right = locs.in(1); |
| 562 ASSERT(!left.IsConstant() || !right.IsConstant()); | 561 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 563 | 562 |
| 564 Condition true_condition = TokenKindToSmiCondition(kind); | 563 Condition true_condition = TokenKindToSmiCondition(kind); |
| 565 | 564 |
| 566 if (left.IsConstant()) { | 565 if (left.IsConstant()) { |
| 567 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); | 566 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
| 568 true_condition = FlipCondition(true_condition); | 567 true_condition = FlipCondition(true_condition); |
| 569 } else if (right.IsConstant()) { | 568 } else if (right.IsConstant()) { |
| 570 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); | 569 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
| 571 } else { | 570 } else { |
| 572 __ slt(CMPRES1, left.reg(), right.reg()); | 571 __ slt(CMPRES1, left.reg(), right.reg()); |
| 573 __ slt(CMPRES2, right.reg(), left.reg()); | 572 __ slt(CMPRES2, right.reg(), left.reg()); |
| 574 } | 573 } |
| 575 return true_condition; | 574 return true_condition; |
| 576 } | 575 } |
| 577 | 576 |
| 578 | 577 |
| 578 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 579 switch (kind) { |
| 580 case Token::kEQ: return EQ; |
| 581 case Token::kNE: return NE; |
| 582 case Token::kLT: return LT; |
| 583 case Token::kGT: return GT; |
| 584 case Token::kLTE: return LE; |
| 585 case Token::kGTE: return GE; |
| 586 default: |
| 587 UNREACHABLE(); |
| 588 return VS; |
| 589 } |
| 590 } |
| 591 |
| 592 |
| 593 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 594 const LocationSummary& locs, |
| 595 Token::Kind kind) { |
| 596 __ TraceSimMsg("EmitUnboxedMintEqualityOp"); |
| 597 __ Comment("EmitUnboxedMintEqualityOp"); |
| 598 ASSERT(Token::IsEqualityOperator(kind)); |
| 599 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 600 Register left_lo = left_pair->At(0).reg(); |
| 601 Register left_hi = left_pair->At(1).reg(); |
| 602 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 603 Register right_lo = right_pair->At(0).reg(); |
| 604 Register right_hi = right_pair->At(1).reg(); |
| 605 |
| 606 __ xor_(CMPRES1, left_lo, right_lo); |
| 607 __ xor_(CMPRES2, left_hi, right_hi); |
| 608 __ or_(CMPRES1, CMPRES1, CMPRES2); |
| 609 __ mov(CMPRES2, ZR); |
| 610 return TokenKindToMintCondition(kind); |
| 611 } |
| 612 |
| 613 |
| 614 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 615 const LocationSummary& locs, |
| 616 Token::Kind kind) { |
| 617 __ TraceSimMsg("EmitUnboxedMintComparisonOp"); |
| 618 __ Comment("EmitUnboxedMintComparisonOp"); |
| 619 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
| 620 Register left_lo = left_pair->At(0).reg(); |
| 621 Register left_hi = left_pair->At(1).reg(); |
| 622 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
| 623 Register right_lo = right_pair->At(0).reg(); |
| 624 Register right_hi = right_pair->At(1).reg(); |
| 625 |
| 626 Label done; |
| 627 // Compare upper halves first. |
| 628 __ slt(CMPRES1, left_hi, right_hi); |
| 629 __ slt(CMPRES2, right_hi, left_hi); |
| 630 // If higher words aren't equal, skip comparing lower words. |
| 631 __ bne(CMPRES1, CMPRES2, &done); |
| 632 |
| 633 __ sltu(CMPRES1, left_lo, right_lo); |
| 634 __ sltu(CMPRES2, right_lo, left_lo); |
| 635 __ Bind(&done); |
| 636 |
| 637 return TokenKindToMintCondition(kind); |
| 638 } |
| 639 |
| 640 |
| 579 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 641 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 580 switch (kind) { | 642 switch (kind) { |
| 581 case Token::kEQ: return EQ; | 643 case Token::kEQ: return EQ; |
| 582 case Token::kNE: return NE; | 644 case Token::kNE: return NE; |
| 583 case Token::kLT: return LT; | 645 case Token::kLT: return LT; |
| 584 case Token::kGT: return GT; | 646 case Token::kGT: return GT; |
| 585 case Token::kLTE: return LE; | 647 case Token::kLTE: return LE; |
| 586 case Token::kGTE: return GE; | 648 case Token::kGTE: return GE; |
| 587 default: | 649 default: |
| 588 UNREACHABLE(); | 650 UNREACHABLE(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 __ movt(CMPRES1, ZR); | 692 __ movt(CMPRES1, ZR); |
| 631 } | 693 } |
| 632 __ mov(CMPRES2, ZR); | 694 __ mov(CMPRES2, ZR); |
| 633 return EQ; | 695 return EQ; |
| 634 } | 696 } |
| 635 | 697 |
| 636 | 698 |
| 637 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 699 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 638 BranchLabels labels) { | 700 BranchLabels labels) { |
| 639 if (operation_cid() == kSmiCid) { | 701 if (operation_cid() == kSmiCid) { |
| 640 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 702 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 703 } else if (operation_cid() == kMintCid) { |
| 704 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind()); |
| 641 } else { | 705 } else { |
| 642 ASSERT(operation_cid() == kDoubleCid); | 706 ASSERT(operation_cid() == kDoubleCid); |
| 643 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 707 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 644 } | 708 } |
| 645 } | 709 } |
| 646 | 710 |
| 647 | 711 |
| 648 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 712 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 649 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 713 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 650 __ Comment("EqualityCompareInstr"); | 714 __ Comment("EqualityCompareInstr"); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 __ LoadObject(result_reg, Bool::True()); | 858 __ LoadObject(result_reg, Bool::True()); |
| 795 __ Bind(&done); | 859 __ Bind(&done); |
| 796 } | 860 } |
| 797 | 861 |
| 798 | 862 |
| 799 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, | 863 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, |
| 800 bool opt) const { | 864 bool opt) const { |
| 801 const intptr_t kNumInputs = 2; | 865 const intptr_t kNumInputs = 2; |
| 802 const intptr_t kNumTemps = 0; | 866 const intptr_t kNumTemps = 0; |
| 803 if (operation_cid() == kMintCid) { | 867 if (operation_cid() == kMintCid) { |
| 804 const intptr_t kNumTemps = 2; | 868 const intptr_t kNumTemps = 0; |
| 805 LocationSummary* locs = new(isolate) LocationSummary( | 869 LocationSummary* locs = new(isolate) LocationSummary( |
| 806 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 870 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 807 locs->set_in(0, Location::RequiresFpuRegister()); | 871 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 808 locs->set_in(1, Location::RequiresFpuRegister()); | 872 Location::RequiresRegister())); |
| 809 locs->set_temp(0, Location::RequiresRegister()); | 873 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 810 locs->set_temp(1, Location::RequiresRegister()); | 874 Location::RequiresRegister())); |
| 811 locs->set_out(0, Location::RequiresRegister()); | 875 locs->set_out(0, Location::RequiresRegister()); |
| 812 return locs; | 876 return locs; |
| 813 } | 877 } |
| 814 if (operation_cid() == kDoubleCid) { | 878 if (operation_cid() == kDoubleCid) { |
| 815 LocationSummary* summary = new(isolate) LocationSummary( | 879 LocationSummary* summary = new(isolate) LocationSummary( |
| 816 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 880 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 817 summary->set_in(0, Location::RequiresFpuRegister()); | 881 summary->set_in(0, Location::RequiresFpuRegister()); |
| 818 summary->set_in(1, Location::RequiresFpuRegister()); | 882 summary->set_in(1, Location::RequiresFpuRegister()); |
| 819 summary->set_out(0, Location::RequiresRegister()); | 883 summary->set_out(0, Location::RequiresRegister()); |
| 820 return summary; | 884 return summary; |
| 821 } | 885 } |
| 822 ASSERT(operation_cid() == kSmiCid); | 886 ASSERT(operation_cid() == kSmiCid); |
| 823 LocationSummary* summary = new(isolate) LocationSummary( | 887 LocationSummary* summary = new(isolate) LocationSummary( |
| 824 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 888 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 825 summary->set_in(0, Location::RegisterOrConstant(left())); | 889 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 826 // Only one input can be a constant operand. The case of two constant | 890 // Only one input can be a constant operand. The case of two constant |
| 827 // operands should be handled by constant propagation. | 891 // operands should be handled by constant propagation. |
| 828 summary->set_in(1, summary->in(0).IsConstant() | 892 summary->set_in(1, summary->in(0).IsConstant() |
| 829 ? Location::RequiresRegister() | 893 ? Location::RequiresRegister() |
| 830 : Location::RegisterOrConstant(right())); | 894 : Location::RegisterOrConstant(right())); |
| 831 summary->set_out(0, Location::RequiresRegister()); | 895 summary->set_out(0, Location::RequiresRegister()); |
| 832 return summary; | 896 return summary; |
| 833 } | 897 } |
| 834 | 898 |
| 835 | 899 |
| 836 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 900 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 837 BranchLabels labels) { | 901 BranchLabels labels) { |
| 838 if (operation_cid() == kSmiCid) { | 902 if (operation_cid() == kSmiCid) { |
| 839 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 903 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 904 } else if (operation_cid() == kMintCid) { |
| 905 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind()); |
| 840 } else { | 906 } else { |
| 841 ASSERT(operation_cid() == kDoubleCid); | 907 ASSERT(operation_cid() == kDoubleCid); |
| 842 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 908 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 843 } | 909 } |
| 844 } | 910 } |
| 845 | 911 |
| 846 | 912 |
| 847 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 913 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 848 __ TraceSimMsg("RelationalOpInstr"); | 914 __ TraceSimMsg("RelationalOpInstr"); |
| 849 | 915 |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 case kTypedDataFloat32x4ArrayCid: | 1255 case kTypedDataFloat32x4ArrayCid: |
| 1190 UNIMPLEMENTED(); | 1256 UNIMPLEMENTED(); |
| 1191 break; | 1257 break; |
| 1192 } | 1258 } |
| 1193 return; | 1259 return; |
| 1194 } | 1260 } |
| 1195 | 1261 |
| 1196 if ((representation() == kUnboxedUint32) || | 1262 if ((representation() == kUnboxedUint32) || |
| 1197 (representation() == kUnboxedInt32)) { | 1263 (representation() == kUnboxedInt32)) { |
| 1198 const Register result = locs()->out(0).reg(); | 1264 const Register result = locs()->out(0).reg(); |
| 1265 if ((index_scale() == 1) && index.IsRegister()) { |
| 1266 __ SmiUntag(index.reg()); |
| 1267 } |
| 1199 switch (class_id()) { | 1268 switch (class_id()) { |
| 1200 case kTypedDataInt32ArrayCid: | 1269 case kTypedDataInt32ArrayCid: |
| 1270 ASSERT(representation() == kUnboxedInt32); |
| 1271 __ lw(result, element_address); |
| 1272 break; |
| 1273 case kTypedDataUint32ArrayCid: |
| 1201 ASSERT(representation() == kUnboxedUint32); | 1274 ASSERT(representation() == kUnboxedUint32); |
| 1202 __ lw(result, element_address); | 1275 __ lw(result, element_address); |
| 1203 break; | 1276 break; |
| 1204 case kTypedDataUint32ArrayCid: | |
| 1205 ASSERT(representation() == kUnboxedInt32); | |
| 1206 __ lw(result, element_address); | |
| 1207 break; | |
| 1208 default: | 1277 default: |
| 1209 UNREACHABLE(); | 1278 UNREACHABLE(); |
| 1210 } | 1279 } |
| 1211 return; | 1280 return; |
| 1212 } | 1281 } |
| 1213 | 1282 |
| 1214 ASSERT(representation() == kTagged); | 1283 ASSERT(representation() == kTagged); |
| 1215 | 1284 |
| 1216 const Register result = locs()->out(0).reg(); | 1285 const Register result = locs()->out(0).reg(); |
| 1217 switch (class_id()) { | 1286 switch (class_id()) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 const Register array = locs()->in(0).reg(); | 1455 const Register array = locs()->in(0).reg(); |
| 1387 const Location index = locs()->in(1); | 1456 const Location index = locs()->in(1); |
| 1388 | 1457 |
| 1389 Address element_address = index.IsRegister() | 1458 Address element_address = index.IsRegister() |
| 1390 ? __ ElementAddressForRegIndex(false, // Store. | 1459 ? __ ElementAddressForRegIndex(false, // Store. |
| 1391 IsExternal(), class_id(), index_scale(), | 1460 IsExternal(), class_id(), index_scale(), |
| 1392 array, index.reg()) | 1461 array, index.reg()) |
| 1393 : __ ElementAddressForIntIndex( | 1462 : __ ElementAddressForIntIndex( |
| 1394 IsExternal(), class_id(), index_scale(), | 1463 IsExternal(), class_id(), index_scale(), |
| 1395 array, Smi::Cast(index.constant()).Value()); | 1464 array, Smi::Cast(index.constant()).Value()); |
| 1465 ASSERT(element_address.base() != TMP); // Allowed for load only. |
| 1396 | 1466 |
| 1397 switch (class_id()) { | 1467 switch (class_id()) { |
| 1398 case kArrayCid: | 1468 case kArrayCid: |
| 1399 if (ShouldEmitStoreBarrier()) { | 1469 if (ShouldEmitStoreBarrier()) { |
| 1400 Register value = locs()->in(2).reg(); | 1470 Register value = locs()->in(2).reg(); |
| 1401 __ StoreIntoObject(array, element_address, value); | 1471 __ StoreIntoObject(array, element_address, value); |
| 1402 } else if (locs()->in(2).IsConstant()) { | 1472 } else if (locs()->in(2).IsConstant()) { |
| 1403 const Object& constant = locs()->in(2).constant(); | 1473 const Object& constant = locs()->in(2).constant(); |
| 1404 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1474 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1405 } else { | 1475 } else { |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1981 | 2051 |
| 1982 // When the parser is building an implicit static getter for optimization, | 2052 // When the parser is building an implicit static getter for optimization, |
| 1983 // it can generate a function body where deoptimization ids do not line up | 2053 // it can generate a function body where deoptimization ids do not line up |
| 1984 // with the unoptimized code. | 2054 // with the unoptimized code. |
| 1985 // | 2055 // |
| 1986 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2056 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1987 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2057 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1988 __ TraceSimMsg("LoadStaticFieldInstr"); | 2058 __ TraceSimMsg("LoadStaticFieldInstr"); |
| 1989 Register field = locs()->in(0).reg(); | 2059 Register field = locs()->in(0).reg(); |
| 1990 Register result = locs()->out(0).reg(); | 2060 Register result = locs()->out(0).reg(); |
| 1991 __ lw(result, FieldAddress(field, Field::value_offset())); | 2061 __ LoadFromOffset(result, field, Field::value_offset() - kHeapObjectTag); |
| 1992 } | 2062 } |
| 1993 | 2063 |
| 1994 | 2064 |
| 1995 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Isolate* isolate, | 2065 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Isolate* isolate, |
| 1996 bool opt) const { | 2066 bool opt) const { |
| 1997 LocationSummary* locs = new(isolate) LocationSummary( | 2067 LocationSummary* locs = new(isolate) LocationSummary( |
| 1998 isolate, 1, 1, LocationSummary::kNoCall); | 2068 isolate, 1, 1, LocationSummary::kNoCall); |
| 1999 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2069 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2000 : Location::RequiresRegister()); | 2070 : Location::RequiresRegister()); |
| 2001 locs->set_temp(0, Location::RequiresRegister()); | 2071 locs->set_temp(0, Location::RequiresRegister()); |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2570 | 2640 |
| 2571 // Restore SP from FP as we are coming from a throw and the code for | 2641 // Restore SP from FP as we are coming from a throw and the code for |
| 2572 // popping arguments has not been run. | 2642 // popping arguments has not been run. |
| 2573 const intptr_t fp_sp_dist = | 2643 const intptr_t fp_sp_dist = |
| 2574 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2644 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 2575 ASSERT(fp_sp_dist <= 0); | 2645 ASSERT(fp_sp_dist <= 0); |
| 2576 __ AddImmediate(SP, FP, fp_sp_dist); | 2646 __ AddImmediate(SP, FP, fp_sp_dist); |
| 2577 | 2647 |
| 2578 // Restore stack and initialize the two exception variables: | 2648 // Restore stack and initialize the two exception variables: |
| 2579 // exception and stack trace variables. | 2649 // exception and stack trace variables. |
| 2580 __ sw(kExceptionObjectReg, | 2650 __ StoreToOffset(kExceptionObjectReg, |
| 2581 Address(FP, exception_var().index() * kWordSize)); | 2651 FP, exception_var().index() * kWordSize); |
| 2582 __ sw(kStackTraceObjectReg, | 2652 __ StoreToOffset(kStackTraceObjectReg, |
| 2583 Address(FP, stacktrace_var().index() * kWordSize)); | 2653 FP, stacktrace_var().index() * kWordSize); |
| 2584 } | 2654 } |
| 2585 | 2655 |
| 2586 | 2656 |
| 2587 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Isolate* isolate, | 2657 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Isolate* isolate, |
| 2588 bool opt) const { | 2658 bool opt) const { |
| 2589 const intptr_t kNumInputs = 0; | 2659 const intptr_t kNumInputs = 0; |
| 2590 const intptr_t kNumTemps = 1; | 2660 const intptr_t kNumTemps = 1; |
| 2591 LocationSummary* summary = new(isolate) LocationSummary( | 2661 LocationSummary* summary = new(isolate) LocationSummary( |
| 2592 isolate, kNumInputs, | 2662 isolate, kNumInputs, |
| 2593 kNumTemps, | 2663 kNumTemps, |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3149 } | 3219 } |
| 3150 | 3220 |
| 3151 | 3221 |
| 3152 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate, | 3222 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate, |
| 3153 bool opt) const { | 3223 bool opt) const { |
| 3154 const intptr_t kNumInputs = 1; | 3224 const intptr_t kNumInputs = 1; |
| 3155 const intptr_t kNumTemps = 0; | 3225 const intptr_t kNumTemps = 0; |
| 3156 LocationSummary* summary = new(isolate) LocationSummary( | 3226 LocationSummary* summary = new(isolate) LocationSummary( |
| 3157 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3227 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3158 summary->set_in(0, Location::RequiresRegister()); | 3228 summary->set_in(0, Location::RequiresRegister()); |
| 3159 summary->set_out(0, Location::RequiresFpuRegister()); | 3229 if (representation() == kUnboxedMint) { |
| 3230 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3231 Location::RequiresRegister())); |
| 3232 } else { |
| 3233 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3234 } |
| 3160 return summary; | 3235 return summary; |
| 3161 } | 3236 } |
| 3162 | 3237 |
| 3163 | 3238 |
| 3164 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3239 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3165 const Register box = locs()->in(0).reg(); | 3240 const Register box = locs()->in(0).reg(); |
| 3166 | 3241 |
| 3167 switch (representation()) { | 3242 switch (representation()) { |
| 3168 case kUnboxedMint: { | 3243 case kUnboxedMint: { |
| 3169 UNIMPLEMENTED(); | 3244 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3245 __ LoadFromOffset(result->At(0).reg(), |
| 3246 box, |
| 3247 ValueOffset() - kHeapObjectTag); |
| 3248 __ LoadFromOffset(result->At(1).reg(), |
| 3249 box, |
| 3250 ValueOffset() - kHeapObjectTag + kWordSize); |
| 3170 break; | 3251 break; |
| 3171 } | 3252 } |
| 3172 | 3253 |
| 3173 case kUnboxedDouble: { | 3254 case kUnboxedDouble: { |
| 3174 const DRegister result = locs()->out(0).fpu_reg(); | 3255 const DRegister result = locs()->out(0).fpu_reg(); |
| 3175 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); | 3256 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); |
| 3176 break; | 3257 break; |
| 3177 } | 3258 } |
| 3178 | 3259 |
| 3179 case kUnboxedFloat32x4: | 3260 case kUnboxedFloat32x4: |
| 3180 case kUnboxedFloat64x2: | 3261 case kUnboxedFloat64x2: |
| 3181 case kUnboxedInt32x4: { | 3262 case kUnboxedInt32x4: { |
| 3182 UNIMPLEMENTED(); | 3263 UNIMPLEMENTED(); |
| 3183 break; | 3264 break; |
| 3184 } | 3265 } |
| 3185 | 3266 |
| 3186 default: | 3267 default: |
| 3187 UNREACHABLE(); | 3268 UNREACHABLE(); |
| 3188 break; | 3269 break; |
| 3189 } | 3270 } |
| 3190 } | 3271 } |
| 3191 | 3272 |
| 3192 | 3273 |
| 3193 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3274 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
| 3194 const Register box = locs()->in(0).reg(); | 3275 const Register box = locs()->in(0).reg(); |
| 3195 | 3276 |
| 3196 switch (representation()) { | 3277 switch (representation()) { |
| 3197 case kUnboxedMint: { | 3278 case kUnboxedMint: { |
| 3198 UNIMPLEMENTED(); | 3279 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3280 __ SmiUntag(result->At(0).reg(), box); |
| 3281 __ sra(result->At(1).reg(), result->At(0).reg(), 31); |
| 3199 break; | 3282 break; |
| 3200 } | 3283 } |
| 3201 | 3284 |
| 3202 case kUnboxedDouble: { | 3285 case kUnboxedDouble: { |
| 3203 const DRegister result = locs()->out(0).fpu_reg(); | 3286 const DRegister result = locs()->out(0).fpu_reg(); |
| 3204 __ SmiUntag(TMP, box); | 3287 __ SmiUntag(TMP, box); |
| 3205 __ mtc1(TMP, STMP1); | 3288 __ mtc1(TMP, STMP1); |
| 3206 __ cvtdw(result, STMP1); | 3289 __ cvtdw(result, STMP1); |
| 3207 break; | 3290 break; |
| 3208 } | 3291 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3264 summary->set_out(0, Location::RequiresRegister()); | 3347 summary->set_out(0, Location::RequiresRegister()); |
| 3265 return summary; | 3348 return summary; |
| 3266 } | 3349 } |
| 3267 | 3350 |
| 3268 | 3351 |
| 3269 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3352 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3270 Register value = locs()->in(0).reg(); | 3353 Register value = locs()->in(0).reg(); |
| 3271 Register out = locs()->out(0).reg(); | 3354 Register out = locs()->out(0).reg(); |
| 3272 ASSERT(value != out); | 3355 ASSERT(value != out); |
| 3273 | 3356 |
| 3274 Label done; | |
| 3275 __ SmiTag(out, value); | 3357 __ SmiTag(out, value); |
| 3276 if (!ValueFitsSmi()) { | 3358 if (!ValueFitsSmi()) { |
| 3277 Register temp = locs()->temp(0).reg(); | 3359 Register temp = locs()->temp(0).reg(); |
| 3360 Label done; |
| 3278 if (from_representation() == kUnboxedInt32) { | 3361 if (from_representation() == kUnboxedInt32) { |
| 3279 __ SmiUntag(CMPRES1, out); | 3362 __ SmiUntag(CMPRES1, out); |
| 3280 __ BranchEqual(CMPRES1, value, &done); | 3363 __ BranchEqual(CMPRES1, value, &done); |
| 3281 } else { | 3364 } else { |
| 3282 ASSERT(from_representation() == kUnboxedUint32); | 3365 ASSERT(from_representation() == kUnboxedUint32); |
| 3283 __ AndImmediate(CMPRES1, value, 0xC0000000); | 3366 __ AndImmediate(CMPRES1, value, 0xC0000000); |
| 3284 __ BranchEqual(CMPRES1, ZR, &done); | 3367 __ BranchEqual(CMPRES1, ZR, &done); |
| 3285 } | 3368 } |
| 3286 BoxAllocationSlowPath::Allocate( | 3369 BoxAllocationSlowPath::Allocate( |
| 3287 compiler, | 3370 compiler, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3301 out, | 3384 out, |
| 3302 Mint::value_offset() - kHeapObjectTag); | 3385 Mint::value_offset() - kHeapObjectTag); |
| 3303 __ StoreToOffset(hi, | 3386 __ StoreToOffset(hi, |
| 3304 out, | 3387 out, |
| 3305 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3388 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3306 __ Bind(&done); | 3389 __ Bind(&done); |
| 3307 } | 3390 } |
| 3308 } | 3391 } |
| 3309 | 3392 |
| 3310 | 3393 |
| 3311 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr); | 3394 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, |
| 3395 bool opt) const { |
| 3396 const intptr_t kNumInputs = 1; |
| 3397 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3398 LocationSummary* summary = new(isolate) LocationSummary( |
| 3399 isolate, |
| 3400 kNumInputs, |
| 3401 kNumTemps, |
| 3402 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3403 : LocationSummary::kCallOnSlowPath); |
| 3404 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3405 Location::RequiresRegister())); |
| 3406 if (!ValueFitsSmi()) { |
| 3407 summary->set_temp(0, Location::RequiresRegister()); |
| 3408 } |
| 3409 summary->set_out(0, Location::RequiresRegister()); |
| 3410 return summary; |
| 3411 } |
| 3412 |
| 3413 |
| 3414 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3415 if (ValueFitsSmi()) { |
| 3416 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 3417 Register value_lo = value_pair->At(0).reg(); |
| 3418 Register out_reg = locs()->out(0).reg(); |
| 3419 __ SmiTag(out_reg, value_lo); |
| 3420 return; |
| 3421 } |
| 3422 |
| 3423 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
| 3424 Register value_lo = value_pair->At(0).reg(); |
| 3425 Register value_hi = value_pair->At(1).reg(); |
| 3426 Register tmp = locs()->temp(0).reg(); |
| 3427 Register out_reg = locs()->out(0).reg(); |
| 3428 |
| 3429 Label not_smi, done; |
| 3430 __ SmiTag(out_reg, value_lo); |
| 3431 __ SmiUntag(tmp, out_reg); |
| 3432 __ bne(tmp, value_lo, ¬_smi); |
| 3433 __ delay_slot()->sra(tmp, out_reg, 31); |
| 3434 __ beq(tmp, value_hi, &done); |
| 3435 |
| 3436 __ Bind(¬_smi); |
| 3437 BoxAllocationSlowPath::Allocate( |
| 3438 compiler, |
| 3439 this, |
| 3440 compiler->mint_class(), |
| 3441 out_reg, |
| 3442 tmp); |
| 3443 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); |
| 3444 __ StoreToOffset(value_hi, |
| 3445 out_reg, |
| 3446 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3447 __ Bind(&done); |
| 3448 } |
| 3449 |
| 3312 | 3450 |
| 3313 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate, | 3451 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate, |
| 3314 bool opt) const { | 3452 bool opt) const { |
| 3315 ASSERT((representation() == kUnboxedInt32) || | 3453 ASSERT((representation() == kUnboxedInt32) || |
| 3316 (representation() == kUnboxedUint32)); | 3454 (representation() == kUnboxedUint32)); |
| 3317 const intptr_t kNumInputs = 1; | 3455 const intptr_t kNumInputs = 1; |
| 3318 const intptr_t kNumTemps = 0; | 3456 const intptr_t kNumTemps = 0; |
| 3319 LocationSummary* summary = new(isolate) LocationSummary( | 3457 LocationSummary* summary = new(isolate) LocationSummary( |
| 3320 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3458 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3321 summary->set_in(0, Location::RequiresRegister()); | 3459 summary->set_in(0, Location::RequiresRegister()); |
| (...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4446 instance_call()->token_pos(), | 4584 instance_call()->token_pos(), |
| 4447 target, | 4585 target, |
| 4448 instance_call()->ArgumentCount(), | 4586 instance_call()->ArgumentCount(), |
| 4449 instance_call()->argument_names(), | 4587 instance_call()->argument_names(), |
| 4450 locs(), | 4588 locs(), |
| 4451 ICData::Handle()); | 4589 ICData::Handle()); |
| 4452 return; | 4590 return; |
| 4453 } | 4591 } |
| 4454 | 4592 |
| 4455 // Load receiver into T0. | 4593 // Load receiver into T0. |
| 4456 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 4594 __ LoadFromOffset(T0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize); |
| 4457 | 4595 |
| 4458 Label* deopt = compiler->AddDeoptStub( | 4596 Label* deopt = compiler->AddDeoptStub( |
| 4459 deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail); | 4597 deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail); |
| 4460 LoadValueCid(compiler, T2, T0, | 4598 LoadValueCid(compiler, T2, T0, |
| 4461 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); | 4599 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); |
| 4462 | 4600 |
| 4463 compiler->EmitTestAndCall(ic_data(), | 4601 compiler->EmitTestAndCall(ic_data(), |
| 4464 T2, // Class id register. | 4602 T2, // Class id register. |
| 4465 instance_call()->ArgumentCount(), | 4603 instance_call()->ArgumentCount(), |
| 4466 instance_call()->argument_names(), | 4604 instance_call()->argument_names(), |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4650 __ BranchUnsignedGreaterEqual( | 4788 __ BranchUnsignedGreaterEqual( |
| 4651 index, Immediate(reinterpret_cast<int32_t>(length.raw())), deopt); | 4789 index, Immediate(reinterpret_cast<int32_t>(length.raw())), deopt); |
| 4652 } | 4790 } |
| 4653 } else { | 4791 } else { |
| 4654 Register length = length_loc.reg(); | 4792 Register length = length_loc.reg(); |
| 4655 Register index = index_loc.reg(); | 4793 Register index = index_loc.reg(); |
| 4656 __ BranchUnsignedGreaterEqual(index, length, deopt); | 4794 __ BranchUnsignedGreaterEqual(index, length, deopt); |
| 4657 } | 4795 } |
| 4658 } | 4796 } |
| 4659 | 4797 |
| 4660 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryMintOpInstr); | 4798 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 4799 bool opt) const { |
| 4800 const intptr_t kNumInputs = 2; |
| 4801 const intptr_t kNumTemps = 0; |
| 4802 LocationSummary* summary = new(isolate) LocationSummary( |
| 4803 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4804 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4805 Location::RequiresRegister())); |
| 4806 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 4807 Location::RequiresRegister())); |
| 4808 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4809 Location::RequiresRegister())); |
| 4810 return summary; |
| 4811 } |
| 4812 |
| 4813 |
| 4814 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4815 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 4816 Register left_lo = left_pair->At(0).reg(); |
| 4817 Register left_hi = left_pair->At(1).reg(); |
| 4818 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
| 4819 Register right_lo = right_pair->At(0).reg(); |
| 4820 Register right_hi = right_pair->At(1).reg(); |
| 4821 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 4822 Register out_lo = out_pair->At(0).reg(); |
| 4823 Register out_hi = out_pair->At(1).reg(); |
| 4824 |
| 4825 Label* deopt = NULL; |
| 4826 if (CanDeoptimize()) { |
| 4827 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 4828 } |
| 4829 switch (op_kind()) { |
| 4830 case Token::kBIT_AND: { |
| 4831 __ and_(out_lo, left_lo, right_lo); |
| 4832 __ and_(out_hi, left_hi, right_hi); |
| 4833 break; |
| 4834 } |
| 4835 case Token::kBIT_OR: { |
| 4836 __ or_(out_lo, left_lo, right_lo); |
| 4837 __ or_(out_hi, left_hi, right_hi); |
| 4838 break; |
| 4839 } |
| 4840 case Token::kBIT_XOR: { |
| 4841 __ xor_(out_lo, left_lo, right_lo); |
| 4842 __ xor_(out_hi, left_hi, right_hi); |
| 4843 break; |
| 4844 } |
| 4845 case Token::kADD: |
| 4846 case Token::kSUB: { |
| 4847 if (op_kind() == Token::kADD) { |
| 4848 __ addu(out_lo, left_lo, right_lo); |
| 4849 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. |
| 4850 __ addu(out_hi, left_hi, right_hi); |
| 4851 __ addu(out_hi, out_hi, TMP); |
| 4852 if (can_overflow()) { |
| 4853 __ xor_(CMPRES1, out_hi, left_hi); |
| 4854 __ xor_(TMP, out_hi, right_hi); |
| 4855 __ and_(CMPRES1, TMP, CMPRES1); |
| 4856 __ bltz(CMPRES1, deopt); |
| 4857 } |
| 4858 } else { |
| 4859 __ subu(out_lo, left_lo, right_lo); |
| 4860 __ sltu(TMP, left_lo, out_lo); // TMP = borrow of left_lo - right_lo. |
| 4861 __ subu(out_hi, left_hi, right_hi); |
| 4862 __ subu(out_hi, out_hi, TMP); |
| 4863 if (can_overflow()) { |
| 4864 __ xor_(CMPRES1, out_hi, left_hi); |
| 4865 __ xor_(TMP, left_hi, right_hi); |
| 4866 __ and_(CMPRES1, TMP, CMPRES1); |
| 4867 __ bltz(CMPRES1, deopt); |
| 4868 } |
| 4869 } |
| 4870 break; |
| 4871 } |
| 4872 case Token::kMUL: { |
| 4873 // The product of two signed 32-bit integers fits in a signed 64-bit |
| 4874 // result without causing overflow. |
| 4875 // We deopt on larger inputs. |
| 4876 // TODO(regis): Range analysis may eliminate the deopt check. |
| 4877 __ sra(CMPRES1, left_lo, 31); |
| 4878 __ bne(CMPRES1, left_hi, deopt); |
| 4879 __ delay_slot()->sra(CMPRES2, right_lo, 31); |
| 4880 __ bne(CMPRES2, right_hi, deopt); |
| 4881 __ delay_slot()->mult(left_lo, right_lo); |
| 4882 __ mflo(out_lo); |
| 4883 __ mfhi(out_hi); |
| 4884 break; |
| 4885 } |
| 4886 default: |
| 4887 UNREACHABLE(); |
| 4888 } |
| 4889 } |
| 4890 |
| 4891 |
| 4892 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 4893 bool opt) const { |
| 4894 const intptr_t kNumInputs = 2; |
| 4895 const intptr_t kNumTemps = 0; |
| 4896 LocationSummary* summary = new(isolate) LocationSummary( |
| 4897 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4898 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4899 Location::RequiresRegister())); |
| 4900 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
| 4901 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4902 Location::RequiresRegister())); |
| 4903 return summary; |
| 4904 } |
| 4905 |
| 4906 |
| 4907 static const intptr_t kMintShiftCountLimit = 63; |
| 4661 | 4908 |
| 4662 bool ShiftMintOpInstr::has_shift_count_check() const { | 4909 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 4663 UNREACHABLE(); | 4910 return !RangeUtils::IsWithin( |
| 4664 return false; | 4911 right()->definition()->range(), 0, kMintShiftCountLimit); |
| 4665 } | 4912 } |
| 4666 | 4913 |
| 4667 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftMintOpInstr); | 4914 |
| 4668 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryMintOpInstr); | 4915 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4916 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 4917 Register left_lo = left_pair->At(0).reg(); |
| 4918 Register left_hi = left_pair->At(1).reg(); |
| 4919 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 4920 Register out_lo = out_pair->At(0).reg(); |
| 4921 Register out_hi = out_pair->At(1).reg(); |
| 4922 |
| 4923 Label* deopt = NULL; |
| 4924 if (CanDeoptimize()) { |
| 4925 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 4926 } |
| 4927 if (locs()->in(1).IsConstant()) { |
| 4928 // Code for a constant shift amount. |
| 4929 ASSERT(locs()->in(1).constant().IsSmi()); |
| 4930 const int32_t shift = |
| 4931 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; |
| 4932 switch (op_kind()) { |
| 4933 case Token::kSHR: { |
| 4934 if (shift < 32) { |
| 4935 __ sll(out_lo, left_hi, 32 - shift); |
| 4936 __ srl(TMP, left_lo, shift); |
| 4937 __ or_(out_lo, out_lo, TMP); |
| 4938 __ sra(out_hi, left_hi, shift); |
| 4939 } else { |
| 4940 __ sra(out_lo, left_hi, shift - 32); |
| 4941 __ sra(out_hi, left_hi, 31); |
| 4942 } |
| 4943 break; |
| 4944 } |
| 4945 case Token::kSHL: { |
| 4946 if (shift < 32) { |
| 4947 __ srl(out_hi, left_lo, 32 - shift); |
| 4948 __ sll(TMP, left_hi, shift); |
| 4949 __ or_(out_hi, out_hi, TMP); |
| 4950 __ sll(out_lo, left_lo, shift); |
| 4951 } else { |
| 4952 __ sll(out_hi, left_lo, shift - 32); |
| 4953 __ mov(out_lo, ZR); |
| 4954 } |
| 4955 // Check for overflow. |
| 4956 if (can_overflow()) { |
| 4957 // Compare high word from input with shifted high word from output. |
| 4958 // Overflow if they aren't equal. |
| 4959 // If shift > 32, also compare low word from input with high word from |
| 4960 // output shifted back shift - 32. |
| 4961 if (shift > 32) { |
| 4962 __ sra(TMP, out_hi, shift - 32); |
| 4963 __ bne(left_lo, TMP, deopt); |
| 4964 __ delay_slot()->sra(TMP, out_hi, 31); |
| 4965 } else if (shift == 32) { |
| 4966 __ sra(TMP, out_hi, 31); |
| 4967 } else { |
| 4968 __ sra(TMP, out_hi, shift); |
| 4969 } |
| 4970 __ bne(left_hi, TMP, deopt); |
| 4971 } |
| 4972 break; |
| 4973 } |
| 4974 default: |
| 4975 UNREACHABLE(); |
| 4976 } |
| 4977 } else { |
| 4978 // Code for a variable shift amount. |
| 4979 Register shift = locs()->in(1).reg(); |
| 4980 |
| 4981 // Deopt if shift is larger than 63 or less than 0. |
| 4982 if (has_shift_count_check()) { |
| 4983 __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1))); |
| 4984 __ beq(CMPRES1, ZR, deopt); |
| 4985 // Untag shift count. |
| 4986 __ delay_slot()->SmiUntag(shift); |
| 4987 } else { |
| 4988 // Untag shift count. |
| 4989 __ SmiUntag(shift); |
| 4990 } |
| 4991 |
| 4992 switch (op_kind()) { |
| 4993 case Token::kSHR: { |
| 4994 Label large_shift, done; |
| 4995 __ sltiu(CMPRES1, shift, Immediate(32)); |
| 4996 __ beq(CMPRES1, ZR, &large_shift); |
| 4997 |
| 4998 // shift < 32. |
| 4999 __ delay_slot()->ori(TMP, ZR, Immediate(32)); |
| 5000 __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31. |
| 5001 __ sllv(out_lo, left_hi, TMP); |
| 5002 __ srlv(TMP, left_lo, shift); |
| 5003 __ or_(out_lo, out_lo, TMP); |
| 5004 __ b(&done); |
| 5005 __ delay_slot()->srav(out_hi, left_hi, shift); |
| 5006 |
| 5007 // shift >= 32. |
| 5008 __ Bind(&large_shift); |
| 5009 __ sra(out_hi, left_hi, 31); |
| 5010 __ srav(out_lo, left_hi, shift); // Only 5 low bits of shift used. |
| 5011 |
| 5012 __ Bind(&done); |
| 5013 break; |
| 5014 } |
| 5015 case Token::kSHL: { |
| 5016 Label large_shift, done; |
| 5017 __ sltiu(CMPRES1, shift, Immediate(32)); |
| 5018 __ beq(CMPRES1, ZR, &large_shift); |
| 5019 |
| 5020 // shift < 32. |
| 5021 __ delay_slot()->ori(TMP, ZR, Immediate(32)); |
| 5022 __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31. |
| 5023 __ srlv(out_hi, left_lo, TMP); |
| 5024 __ sllv(TMP, left_hi, shift); |
| 5025 __ or_(out_hi, out_hi, TMP); |
| 5026 // Check for overflow. |
| 5027 if (can_overflow()) { |
| 5028 // Compare high word from input with shifted high word from output. |
| 5029 __ srav(TMP, out_hi, shift); |
| 5030 __ beq(TMP, left_hi, &done); |
| 5031 __ delay_slot()->sllv(out_lo, left_lo, shift); |
| 5032 __ b(deopt); |
| 5033 } else { |
| 5034 __ b(&done); |
| 5035 __ delay_slot()->sllv(out_lo, left_lo, shift); |
| 5036 } |
| 5037 |
| 5038 // shift >= 32. |
| 5039 __ Bind(&large_shift); |
| 5040 __ sllv(out_hi, left_lo, shift); // Only 5 low bits of shift used. |
| 5041 // Check for overflow. |
| 5042 if (can_overflow()) { |
| 5043 // Compare low word from input with shifted high word from output and |
| 5044 // high word from input to sign of output. |
| 5045 // Overflow if they aren't equal. |
| 5046 __ srav(TMP, out_hi, shift); |
| 5047 __ bne(TMP, left_lo, deopt); |
| 5048 __ delay_slot()->sra(TMP, out_hi, 31); |
| 5049 __ bne(TMP, left_hi, deopt); |
| 5050 __ delay_slot()->mov(out_lo, ZR); |
| 5051 } else { |
| 5052 __ mov(out_lo, ZR); |
| 5053 } |
| 5054 __ Bind(&done); |
| 5055 break; |
| 5056 } |
| 5057 default: |
| 5058 UNREACHABLE(); |
| 5059 } |
| 5060 } |
| 5061 } |
| 5062 |
| 5063 |
| 5064 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5065 bool opt) const { |
| 5066 const intptr_t kNumInputs = 1; |
| 5067 const intptr_t kNumTemps = 0; |
| 5068 LocationSummary* summary = new(isolate) LocationSummary( |
| 5069 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5070 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5071 Location::RequiresRegister())); |
| 5072 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5073 Location::RequiresRegister())); |
| 5074 return summary; |
| 5075 } |
| 5076 |
| 5077 |
| 5078 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5079 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5080 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5081 Register left_lo = left_pair->At(0).reg(); |
| 5082 Register left_hi = left_pair->At(1).reg(); |
| 5083 |
| 5084 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5085 Register out_lo = out_pair->At(0).reg(); |
| 5086 Register out_hi = out_pair->At(1).reg(); |
| 5087 |
| 5088 __ nor(out_lo, ZR, left_lo); |
| 5089 __ nor(out_hi, ZR, left_hi); |
| 5090 } |
| 5091 |
| 4669 | 5092 |
| 4670 CompileType BinaryUint32OpInstr::ComputeType() const { | 5093 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 4671 return CompileType::Int(); | 5094 return CompileType::Int(); |
| 4672 } | 5095 } |
| 4673 | 5096 |
| 4674 | 5097 |
| 4675 CompileType ShiftUint32OpInstr::ComputeType() const { | 5098 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 4676 return CompileType::Int(); | 5099 return CompileType::Int(); |
| 4677 } | 5100 } |
| 4678 | 5101 |
| 4679 | 5102 |
| 4680 CompileType UnaryUint32OpInstr::ComputeType() const { | 5103 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 4681 return CompileType::Int(); | 5104 return CompileType::Int(); |
| 4682 } | 5105 } |
| 4683 | 5106 |
| 4684 | 5107 |
| 4685 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5108 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 4686 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5109 bool opt) const { |
| 4687 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5110 const intptr_t kNumInputs = 2; |
| 5111 const intptr_t kNumTemps = 0; |
| 5112 LocationSummary* summary = new(isolate) LocationSummary( |
| 5113 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5114 summary->set_in(0, Location::RequiresRegister()); |
| 5115 summary->set_in(1, Location::RequiresRegister()); |
| 5116 summary->set_out(0, Location::RequiresRegister()); |
| 5117 return summary; |
| 5118 } |
| 5119 |
| 5120 |
| 5121 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5122 Register left = locs()->in(0).reg(); |
| 5123 Register right = locs()->in(1).reg(); |
| 5124 Register out = locs()->out(0).reg(); |
| 5125 ASSERT(out != left); |
| 5126 switch (op_kind()) { |
| 5127 case Token::kBIT_AND: |
| 5128 __ and_(out, left, right); |
| 5129 break; |
| 5130 case Token::kBIT_OR: |
| 5131 __ or_(out, left, right); |
| 5132 break; |
| 5133 case Token::kBIT_XOR: |
| 5134 __ xor_(out, left, right); |
| 5135 break; |
| 5136 case Token::kADD: |
| 5137 __ addu(out, left, right); |
| 5138 break; |
| 5139 case Token::kSUB: |
| 5140 __ subu(out, left, right); |
| 5141 break; |
| 5142 case Token::kMUL: |
| 5143 __ multu(left, right); |
| 5144 __ mflo(out); |
| 5145 break; |
| 5146 default: |
| 5147 UNREACHABLE(); |
| 5148 } |
| 5149 } |
| 5150 |
| 5151 |
| 5152 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5153 bool opt) const { |
| 5154 const intptr_t kNumInputs = 2; |
| 5155 const intptr_t kNumTemps = 1; |
| 5156 LocationSummary* summary = new(isolate) LocationSummary( |
| 5157 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5158 summary->set_in(0, Location::RequiresRegister()); |
| 5159 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 5160 summary->set_temp(0, Location::RequiresRegister()); |
| 5161 summary->set_out(0, Location::RequiresRegister()); |
| 5162 return summary; |
| 5163 } |
| 5164 |
| 5165 |
| 5166 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5167 const intptr_t kShifterLimit = 31; |
| 5168 |
| 5169 Register left = locs()->in(0).reg(); |
| 5170 Register out = locs()->out(0).reg(); |
| 5171 Register temp = locs()->temp(0).reg(); |
| 5172 |
| 5173 ASSERT(left != out); |
| 5174 |
| 5175 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 5176 |
| 5177 if (locs()->in(1).IsConstant()) { |
| 5178 // Shifter is constant. |
| 5179 |
| 5180 const Object& constant = locs()->in(1).constant(); |
| 5181 ASSERT(constant.IsSmi()); |
| 5182 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 5183 |
| 5184 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 5185 switch (op_kind()) { |
| 5186 case Token::kSHR: |
| 5187 __ srl(out, left, shift_value); |
| 5188 break; |
| 5189 case Token::kSHL: |
| 5190 __ sll(out, left, shift_value); |
| 5191 break; |
| 5192 default: |
| 5193 UNREACHABLE(); |
| 5194 } |
| 5195 return; |
| 5196 } |
| 5197 |
| 5198 // Non constant shift value. |
| 5199 Register shifter = locs()->in(1).reg(); |
| 5200 |
| 5201 __ SmiUntag(temp, shifter); |
| 5202 // If shift value is < 0, deoptimize. |
| 5203 __ bltz(temp, deopt); |
| 5204 __ delay_slot()->mov(out, left); |
| 5205 __ sltiu(CMPRES1, temp, Immediate(kShifterLimit + 1)); |
| 5206 __ movz(out, ZR, CMPRES1); // out = shift > kShifterLimit ? 0 : left. |
| 5207 // Do the shift % 32. |
| 5208 switch (op_kind()) { |
| 5209 case Token::kSHR: |
| 5210 __ srlv(out, out, temp); |
| 5211 break; |
| 5212 case Token::kSHL: |
| 5213 __ sllv(out, out, temp); |
| 5214 break; |
| 5215 default: |
| 5216 UNREACHABLE(); |
| 5217 } |
| 5218 } |
| 5219 |
| 5220 |
| 5221 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5222 bool opt) const { |
| 5223 const intptr_t kNumInputs = 1; |
| 5224 const intptr_t kNumTemps = 0; |
| 5225 LocationSummary* summary = new(isolate) LocationSummary( |
| 5226 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5227 summary->set_in(0, Location::RequiresRegister()); |
| 5228 summary->set_out(0, Location::RequiresRegister()); |
| 5229 return summary; |
| 5230 } |
| 5231 |
| 5232 |
| 5233 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5234 Register left = locs()->in(0).reg(); |
| 5235 Register out = locs()->out(0).reg(); |
| 5236 ASSERT(left != out); |
| 5237 |
| 5238 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5239 |
| 5240 __ nor(out, ZR, left); |
| 5241 } |
| 5242 |
| 5243 |
| 4688 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5244 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 4689 | 5245 |
| 4690 | 5246 |
| 4691 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 5247 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 4692 bool opt) const { | 5248 bool opt) const { |
| 4693 const intptr_t kNumInputs = 1; | 5249 const intptr_t kNumInputs = 1; |
| 4694 const intptr_t kNumTemps = 0; | 5250 const intptr_t kNumTemps = 0; |
| 4695 LocationSummary* summary = new(isolate) LocationSummary( | 5251 LocationSummary* summary = new(isolate) LocationSummary( |
| 4696 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5252 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4697 if (from() == kUnboxedMint) { | 5253 if (from() == kUnboxedMint) { |
| 4698 UNREACHABLE(); | 5254 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5255 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5256 Location::RequiresRegister())); |
| 5257 summary->set_out(0, Location::RequiresRegister()); |
| 4699 } else if (to() == kUnboxedMint) { | 5258 } else if (to() == kUnboxedMint) { |
| 4700 UNREACHABLE(); | 5259 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5260 summary->set_in(0, Location::RequiresRegister()); |
| 5261 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5262 Location::RequiresRegister())); |
| 4701 } else { | 5263 } else { |
| 4702 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5264 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 4703 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5265 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 4704 summary->set_in(0, Location::RequiresRegister()); | 5266 summary->set_in(0, Location::RequiresRegister()); |
| 4705 summary->set_out(0, Location::SameAsFirstInput()); | 5267 summary->set_out(0, Location::SameAsFirstInput()); |
| 4706 } | 5268 } |
| 4707 return summary; | 5269 return summary; |
| 4708 } | 5270 } |
| 4709 | 5271 |
| 4710 | 5272 |
| 4711 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5273 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4712 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 5274 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 4713 const Register out = locs()->out(0).reg(); | 5275 const Register out = locs()->out(0).reg(); |
| 4714 // Representations are bitwise equivalent. | 5276 // Representations are bitwise equivalent. |
| 4715 ASSERT(out == locs()->in(0).reg()); | 5277 ASSERT(out == locs()->in(0).reg()); |
| 4716 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 5278 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
| 4717 const Register out = locs()->out(0).reg(); | 5279 const Register out = locs()->out(0).reg(); |
| 4718 // Representations are bitwise equivalent. | 5280 // Representations are bitwise equivalent. |
| 4719 ASSERT(out == locs()->in(0).reg()); | 5281 ASSERT(out == locs()->in(0).reg()); |
| 4720 if (CanDeoptimize()) { | 5282 if (CanDeoptimize()) { |
| 4721 Label* deopt = | 5283 Label* deopt = |
| 4722 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 5284 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 4723 __ BranchSignedLess(out, Immediate(0), deopt); | 5285 __ BranchSignedLess(out, Immediate(0), deopt); |
| 4724 } | 5286 } |
| 4725 } else if (from() == kUnboxedMint) { | 5287 } else if (from() == kUnboxedMint) { |
| 4726 UNREACHABLE(); | 5288 ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32); |
| 4727 } else if (to() == kUnboxedMint) { | 5289 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
| 4728 ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32); | 5290 Register in_lo = in_pair->At(0).reg(); |
| 4729 UNREACHABLE(); | 5291 Register in_hi = in_pair->At(1).reg(); |
| 5292 Register out = locs()->out(0).reg(); |
| 5293 // Copy low word. |
| 5294 __ mov(out, in_lo); |
| 5295 if (CanDeoptimize()) { |
| 5296 Label* deopt = |
| 5297 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5298 ASSERT(to() == kUnboxedInt32); |
| 5299 __ sra(TMP, in_lo, 31); |
| 5300 __ bne(in_hi, TMP, deopt); |
| 5301 } |
| 5302 } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) { |
| 5303 ASSERT(to() == kUnboxedMint); |
| 5304 Register in = locs()->in(0).reg(); |
| 5305 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5306 Register out_lo = out_pair->At(0).reg(); |
| 5307 Register out_hi = out_pair->At(1).reg(); |
| 5308 // Copy low word. |
| 5309 __ mov(out_lo, in); |
| 5310 if (from() == kUnboxedUint32) { |
| 5311 __ xor_(out_hi, out_hi, out_hi); |
| 5312 } else { |
| 5313 ASSERT(from() == kUnboxedInt32); |
| 5314 __ sra(out_hi, in, 31); |
| 5315 } |
| 4730 } else { | 5316 } else { |
| 4731 UNREACHABLE(); | 5317 UNREACHABLE(); |
| 4732 } | 5318 } |
| 4733 } | 5319 } |
| 4734 | 5320 |
| 4735 | 5321 |
| 4736 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 5322 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 4737 bool opt) const { | 5323 bool opt) const { |
| 4738 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 5324 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 4739 } | 5325 } |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4971 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 5557 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 4972 #if defined(DEBUG) | 5558 #if defined(DEBUG) |
| 4973 __ LoadImmediate(S4, kInvalidObjectPointer); | 5559 __ LoadImmediate(S4, kInvalidObjectPointer); |
| 4974 __ LoadImmediate(S5, kInvalidObjectPointer); | 5560 __ LoadImmediate(S5, kInvalidObjectPointer); |
| 4975 #endif | 5561 #endif |
| 4976 } | 5562 } |
| 4977 | 5563 |
| 4978 } // namespace dart | 5564 } // namespace dart |
| 4979 | 5565 |
| 4980 #endif // defined TARGET_ARCH_MIPS | 5566 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |