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

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 670263007: IR refactoring: consolidate all boxing and unboxing instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 3545 matching lines...) Expand 10 before | Expand all | Expand 10 after
3556 } else if (right_cid == kSmiCid) { 3556 } else if (right_cid == kSmiCid) {
3557 __ tst(left, Operand(kSmiTagMask)); 3557 __ tst(left, Operand(kSmiTagMask));
3558 } else { 3558 } else {
3559 __ orr(IP, left, Operand(right)); 3559 __ orr(IP, left, Operand(right));
3560 __ tst(IP, Operand(kSmiTagMask)); 3560 __ tst(IP, Operand(kSmiTagMask));
3561 } 3561 }
3562 __ b(deopt, EQ); 3562 __ b(deopt, EQ);
3563 } 3563 }
3564 3564
3565 3565
3566 LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate, 3566 LocationSummary* BoxInstr::MakeLocationSummary(Isolate* isolate,
3567 bool opt) const { 3567 bool opt) const {
3568 const intptr_t kNumInputs = 1; 3568 const intptr_t kNumInputs = 1;
3569 const intptr_t kNumTemps = 1; 3569 const intptr_t kNumTemps = 1;
3570 LocationSummary* summary = new(isolate) LocationSummary( 3570 LocationSummary* summary = new(isolate) LocationSummary(
3571 isolate, kNumInputs, 3571 isolate, kNumInputs,
3572 kNumTemps, 3572 kNumTemps,
3573 LocationSummary::kCallOnSlowPath); 3573 LocationSummary::kCallOnSlowPath);
3574 summary->set_in(0, Location::RequiresFpuRegister()); 3574 summary->set_in(0, Location::RequiresFpuRegister());
3575 summary->set_temp(0, Location::RequiresRegister()); 3575 summary->set_temp(0, Location::RequiresRegister());
3576 summary->set_out(0, Location::RequiresRegister()); 3576 summary->set_out(0, Location::RequiresRegister());
3577 return summary; 3577 return summary;
3578 } 3578 }
3579 3579
3580 3580
3581 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3581 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3582 const Register out_reg = locs()->out(0).reg(); 3582 const Register out_reg = locs()->out(0).reg();
3583 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); 3583 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg());
3584 3584
3585 BoxAllocationSlowPath::Allocate( 3585 BoxAllocationSlowPath::Allocate(
3586 compiler, 3586 compiler,
3587 this, 3587 this,
3588 compiler->double_class(), 3588 compiler->BoxClassFor(from_representation()),
3589 out_reg, 3589 out_reg,
3590 locs()->temp(0).reg()); 3590 locs()->temp(0).reg());
3591 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); 3591
3592 } 3592 switch (from_representation()) {
3593 3593 case kUnboxedDouble:
3594 3594 __ StoreDToOffset(
3595 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, 3595 value, out_reg, ValueOffset() - kHeapObjectTag);
3596 break;
3597 case kUnboxedFloat32x4:
3598 case kUnboxedFloat64x2:
3599 case kUnboxedInt32x4:
3600 __ StoreMultipleDToOffset(
3601 value, 2, out_reg, ValueOffset() - kHeapObjectTag);
3602 break;
3603 default:
3604 UNREACHABLE();
3605 break;
3606 }
3607 }
3608
3609
3610 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate,
3596 bool opt) const { 3611 bool opt) const {
3612 const bool needs_temp = CanDeoptimize();
3597 const intptr_t kNumInputs = 1; 3613 const intptr_t kNumInputs = 1;
3598 const intptr_t value_cid = value()->Type()->ToCid();
3599 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
3600 const intptr_t kNumTemps = needs_temp ? 1 : 0; 3614 const intptr_t kNumTemps = needs_temp ? 1 : 0;
3601 LocationSummary* summary = new(isolate) LocationSummary( 3615 LocationSummary* summary = new(isolate) LocationSummary(
3602 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3616 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3603 summary->set_in(0, Location::RequiresRegister()); 3617 summary->set_in(0, Location::RequiresRegister());
3604 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); 3618 if (needs_temp) {
3605 summary->set_out(0, Location::RequiresFpuRegister()); 3619 summary->set_temp(0, Location::RequiresRegister());
3620 }
3621 if (representation() == kUnboxedMint) {
3622 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
3623 Location::RequiresRegister()));
3624 } else {
3625 summary->set_out(0, Location::RequiresFpuRegister());
3626 }
3606 return summary; 3627 return summary;
3607 } 3628 }
3608 3629
3609 3630
3610 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3631 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) {
3611 CompileType* value_type = value()->Type(); 3632 const Register box = locs()->in(0).reg();
3612 const intptr_t value_cid = value_type->ToCid(); 3633
3613 const Register value = locs()->in(0).reg(); 3634 switch (representation()) {
3614 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); 3635 case kUnboxedMint: {
3615 3636 PairLocation* result = locs()->out(0).AsPairLocation();
3616 if (value_cid == kDoubleCid) { 3637 __ LoadFromOffset(kWord,
3617 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); 3638 result->At(0).reg(),
3618 } else if (value_cid == kSmiCid) { 3639 box,
3619 __ SmiUntag(IP, value); 3640 ValueOffset() - kHeapObjectTag);
3620 __ vmovdr(DTMP, 0, IP); 3641 __ LoadFromOffset(kWord,
3621 __ vcvtdi(result, STMP); 3642 result->At(1).reg(),
3643 box,
3644 ValueOffset() - kHeapObjectTag + kWordSize);
3645 break;
3646 }
3647
3648 case kUnboxedDouble: {
3649 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
3650 __ LoadDFromOffset(
3651 result, box, ValueOffset() - kHeapObjectTag);
3652 break;
3653 }
3654
3655 case kUnboxedFloat32x4:
3656 case kUnboxedFloat64x2:
3657 case kUnboxedInt32x4: {
3658 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
3659 __ LoadMultipleDFromOffset(
3660 result, 2, box, ValueOffset() - kHeapObjectTag);
3661 break;
3662 }
3663
3664 default:
3665 UNREACHABLE();
3666 break;
3667 }
3668 }
3669
3670
3671 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) {
3672 const Register box = locs()->in(0).reg();
3673
3674 switch (representation()) {
3675 case kUnboxedMint: {
3676 PairLocation* result = locs()->out(0).AsPairLocation();
3677 __ SmiUntag(result->At(0).reg(), box);
3678 __ SignFill(result->At(1).reg(), result->At(0).reg());
3679 break;
3680 }
3681
3682 case kUnboxedDouble: {
3683 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
3684 __ SmiUntag(IP, box);
3685 __ vmovdr(DTMP, 0, IP);
3686 __ vcvtdi(result, STMP);
3687 break;
3688 }
3689
3690 default:
3691 UNREACHABLE();
3692 break;
3693 }
3694 }
3695
3696
3697 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3698 const intptr_t value_cid = value()->Type()->ToCid();
3699 const intptr_t box_cid = BoxCid();
3700
3701 if (value_cid == box_cid) {
3702 EmitLoadFromBox(compiler);
3703 } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
3704 EmitSmiConversion(compiler);
3622 } else { 3705 } else {
3623 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3706 const Register box = locs()->in(0).reg();
3624 ICData::kDeoptBinaryDoubleOp);
3625 const Register temp = locs()->temp(0).reg(); 3707 const Register temp = locs()->temp(0).reg();
3626 if (value_type->is_nullable() && 3708 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
3627 (value_type->ToNullableCid() == kDoubleCid)) { 3709 ICData::kDeoptCheckClass);
3628 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); 3710 Label is_smi;
3711
3712 if ((value()->Type()->ToNullableCid() == box_cid) &&
3713 value()->Type()->is_nullable()) {
3714 __ CompareImmediate(box, reinterpret_cast<intptr_t>(Object::null()));
3629 __ b(deopt, EQ); 3715 __ b(deopt, EQ);
3630 // It must be double now.
3631 __ LoadDFromOffset(result, value,
3632 Double::value_offset() - kHeapObjectTag);
3633 } else { 3716 } else {
3634 Label is_smi, done; 3717 __ tst(box, Operand(kSmiTagMask));
3635 __ tst(value, Operand(kSmiTagMask)); 3718 __ b(CanConvertSmi() ? &is_smi : deopt, EQ);
3636 __ b(&is_smi, EQ); 3719 __ CompareClassId(box, box_cid, temp);
3637 __ CompareClassId(value, kDoubleCid, temp);
3638 __ b(deopt, NE); 3720 __ b(deopt, NE);
3639 __ LoadDFromOffset(result, value, 3721 }
3640 Double::value_offset() - kHeapObjectTag); 3722
3723 EmitLoadFromBox(compiler);
3724
3725 if (is_smi.IsLinked()) {
3726 Label done;
3641 __ b(&done); 3727 __ b(&done);
3642 __ Bind(&is_smi); 3728 __ Bind(&is_smi);
3643 __ SmiUntag(IP, value); 3729 EmitSmiConversion(compiler);
3644 __ vmovdr(DTMP, 0, IP);
3645 __ vcvtdi(result, STMP);
3646 __ Bind(&done); 3730 __ Bind(&done);
3647 } 3731 }
3648 } 3732 }
3649 } 3733 }
3650 3734
3651 3735
3652 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, 3736 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Isolate* isolate,
3653 bool opt) const { 3737 bool opt) const {
3738 ASSERT((from_representation() == kUnboxedInt32) ||
3739 (from_representation() == kUnboxedUint32));
3654 const intptr_t kNumInputs = 1; 3740 const intptr_t kNumInputs = 1;
3655 const intptr_t kNumTemps = 1; 3741 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
3656 LocationSummary* summary = new(isolate) LocationSummary( 3742 LocationSummary* summary = new(isolate) LocationSummary(
3657 isolate, kNumInputs, 3743 isolate,
3658 kNumTemps, 3744 kNumInputs,
3659 LocationSummary::kCallOnSlowPath); 3745 kNumTemps,
3660 summary->set_in(0, Location::RequiresFpuRegister()); 3746 ValueFitsSmi() ? LocationSummary::kNoCall
3661 summary->set_temp(0, Location::RequiresRegister()); 3747 : LocationSummary::kCallOnSlowPath);
3748 summary->set_in(0, Location::RequiresRegister());
3749 if (!ValueFitsSmi()) {
3750 summary->set_temp(0, Location::RequiresRegister());
3751 }
3662 summary->set_out(0, Location::RequiresRegister()); 3752 summary->set_out(0, Location::RequiresRegister());
3663 return summary; 3753 return summary;
3664 } 3754 }
3665 3755
3666 3756
3667 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3757 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3668 const Register out_reg = locs()->out(0).reg(); 3758 Register value = locs()->in(0).reg();
3669 const QRegister value = locs()->in(0).fpu_reg(); 3759 Register out = locs()->out(0).reg();
3670 const DRegister dvalue0 = EvenDRegisterOf(value); 3760 ASSERT(value != out);
3761
3762 __ SmiTag(out, value);
3763 if (!ValueFitsSmi()) {
3764 Register temp = locs()->temp(0).reg();
3765 Label done;
3766 if (from_representation() == kUnboxedInt32) {
3767 __ cmp(value, Operand(out, ASR, 1));
3768 } else {
3769 ASSERT(from_representation() == kUnboxedUint32);
3770 // Note: better to test upper bits instead of comparing with
3771 // kSmiMax as kSmiMax does not fit into immediate operand.
3772 __ TestImmediate(value, 0xC0000000);
3773 }
3774 __ b(&done, EQ);
3775 BoxAllocationSlowPath::Allocate(
3776 compiler,
3777 this,
3778 compiler->mint_class(),
3779 out,
3780 temp);
3781 if (from_representation() == kUnboxedInt32) {
3782 __ Asr(temp, value, Operand(kBitsPerWord - 1));
3783 } else {
3784 ASSERT(from_representation() == kUnboxedUint32);
3785 __ eor(temp, temp, Operand(temp));
3786 }
3787 __ StoreToOffset(kWord,
3788 value,
3789 out,
3790 Mint::value_offset() - kHeapObjectTag);
3791 __ StoreToOffset(kWord,
3792 temp,
3793 out,
3794 Mint::value_offset() - kHeapObjectTag + kWordSize);
3795 __ Bind(&done);
3796 }
3797 }
3798
3799
3800 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate,
3801 bool opt) const {
3802 const intptr_t kNumInputs = 1;
3803 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
3804 LocationSummary* summary = new(isolate) LocationSummary(
3805 isolate,
3806 kNumInputs,
3807 kNumTemps,
3808 ValueFitsSmi() ? LocationSummary::kNoCall
3809 : LocationSummary::kCallOnSlowPath);
3810 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
3811 Location::RequiresRegister()));
3812 if (!ValueFitsSmi()) {
3813 summary->set_temp(0, Location::RequiresRegister());
3814 }
3815 summary->set_out(0, Location::RequiresRegister());
3816 return summary;
3817 }
3818
3819
3820 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3821 if (ValueFitsSmi()) {
3822 PairLocation* value_pair = locs()->in(0).AsPairLocation();
3823 Register value_lo = value_pair->At(0).reg();
3824 Register out_reg = locs()->out(0).reg();
3825 __ SmiTag(out_reg, value_lo);
3826 return;
3827 }
3828
3829 PairLocation* value_pair = locs()->in(0).AsPairLocation();
3830 Register value_lo = value_pair->At(0).reg();
3831 Register value_hi = value_pair->At(1).reg();
3832 Register tmp = locs()->temp(0).reg();
3833 Register out_reg = locs()->out(0).reg();
3834
3835 Label done;
3836 __ SmiTag(out_reg, value_lo);
3837 __ cmp(value_lo, Operand(out_reg, ASR, kSmiTagSize));
3838 __ cmp(value_hi, Operand(out_reg, ASR, 31), EQ);
3839 __ b(&done, EQ);
3671 3840
3672 BoxAllocationSlowPath::Allocate( 3841 BoxAllocationSlowPath::Allocate(
3673 compiler, 3842 compiler,
3674 this, 3843 this,
3675 compiler->float32x4_class(), 3844 compiler->mint_class(),
3676 out_reg, 3845 out_reg,
3677 locs()->temp(0).reg()); 3846 tmp);
3678 __ StoreMultipleDToOffset(dvalue0, 2, out_reg, 3847 __ StoreToOffset(kWord,
3679 Float32x4::value_offset() - kHeapObjectTag); 3848 value_lo,
3680 } 3849 out_reg,
3681 3850 Mint::value_offset() - kHeapObjectTag);
3682 3851 __ StoreToOffset(kWord,
3683 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, 3852 value_hi,
3684 bool opt) const { 3853 out_reg,
3685 const intptr_t value_cid = value()->Type()->ToCid(); 3854 Mint::value_offset() - kHeapObjectTag + kWordSize);
3855 __ Bind(&done);
3856 }
3857
3858
3859 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
3860 Register mint,
3861 Register result,
3862 Register temp,
3863 Label* deopt) {
3864 __ LoadFromOffset(kWord,
3865 result,
3866 mint,
3867 Mint::value_offset() - kHeapObjectTag);
3868 if (deopt != NULL) {
3869 __ LoadFromOffset(kWord,
3870 temp,
3871 mint,
3872 Mint::value_offset() - kHeapObjectTag + kWordSize);
3873 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1));
3874 __ b(deopt, NE);
3875 }
3876 }
3877
3878
3879 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate,
3880 bool opt) const {
Florian Schneider 2014/10/30 15:43:23 Indentation.
Vyacheslav Egorov (Google) 2014/10/30 17:57:39 Done.
3881 ASSERT((representation() == kUnboxedInt32) ||
3882 (representation() == kUnboxedUint32));
3883 ASSERT((representation() != kUnboxedUint32) || is_truncating());
3686 const intptr_t kNumInputs = 1; 3884 const intptr_t kNumInputs = 1;
3687 const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1; 3885 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
3688 LocationSummary* summary = new(isolate) LocationSummary( 3886 LocationSummary* summary = new(isolate) LocationSummary(
3689 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3887 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3690 summary->set_in(0, Location::RequiresRegister()); 3888 summary->set_in(0, Location::RequiresRegister());
3691 if (kNumTemps > 0) { 3889 if (kNumTemps > 0) {
3692 ASSERT(kNumTemps == 1);
3693 summary->set_temp(0, Location::RequiresRegister()); 3890 summary->set_temp(0, Location::RequiresRegister());
3694 } 3891 }
3695 summary->set_out(0, Location::RequiresFpuRegister()); 3892 summary->set_out(0, Location::RequiresRegister());
3696 return summary; 3893 return summary;
3697 } 3894 }
3698 3895
3699 3896
3700 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3897 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3701 const intptr_t value_cid = value()->Type()->ToCid(); 3898 const intptr_t value_cid = value()->Type()->ToCid();
3702 const Register value = locs()->in(0).reg(); 3899 const Register value = locs()->in(0).reg();
3703 const QRegister result = locs()->out(0).fpu_reg(); 3900 const Register out = locs()->out(0).reg();
3704 3901 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
3705 if (value_cid != kFloat32x4Cid) { 3902 Label* deopt = CanDeoptimize() ?
3706 const Register temp = locs()->temp(0).reg(); 3903 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL;
3707 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); 3904 Label* out_of_range = !is_truncating() ? deopt : NULL;
3708 __ tst(value, Operand(kSmiTagMask)); 3905 ASSERT(value != out);
3709 __ b(deopt, EQ); 3906
3710 __ CompareClassId(value, kFloat32x4Cid, temp); 3907 if (value_cid == kSmiCid) {
3908 __ SmiUntag(out, value);
3909 } else if (value_cid == kMintCid) {
3910 LoadInt32FromMint(compiler, value, out, temp, out_of_range);
3911 } else {
3912 Label done;
3913 __ SmiUntag(out, value, &done);
3914 __ CompareClassId(value, kMintCid, temp);
3711 __ b(deopt, NE); 3915 __ b(deopt, NE);
3712 } 3916 LoadInt32FromMint(compiler, value, out, temp, out_of_range);
3713 3917 __ Bind(&done);
3714 const DRegister dresult0 = EvenDRegisterOf(result); 3918 }
3715 __ LoadMultipleDFromOffset(dresult0, 2, value, 3919 }
3716 Float32x4::value_offset() - kHeapObjectTag); 3920
3717 } 3921
3718
3719
3720 LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
3721 bool opt) const {
3722 const intptr_t kNumInputs = 1;
3723 const intptr_t kNumTemps = 1;
3724 LocationSummary* summary = new(isolate) LocationSummary(
3725 isolate, kNumInputs,
3726 kNumTemps,
3727 LocationSummary::kCallOnSlowPath);
3728 summary->set_in(0, Location::RequiresFpuRegister());
3729 summary->set_temp(0, Location::RequiresRegister());
3730 summary->set_out(0, Location::RequiresRegister());
3731 return summary;
3732 }
3733
3734
3735 void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3736 const Register out_reg = locs()->out(0).reg();
3737 const QRegister value = locs()->in(0).fpu_reg();
3738 const DRegister dvalue0 = EvenDRegisterOf(value);
3739
3740 BoxAllocationSlowPath::Allocate(
3741 compiler,
3742 this,
3743 compiler->float64x2_class(),
3744 out_reg,
3745 locs()->temp(0).reg());
3746 __ StoreMultipleDToOffset(dvalue0, 2, out_reg,
3747 Float64x2::value_offset() - kHeapObjectTag);
3748 }
3749
3750
3751 LocationSummary* UnboxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
3752 bool opt) const {
3753 const intptr_t value_cid = value()->Type()->ToCid();
3754 const intptr_t kNumInputs = 1;
3755 const intptr_t kNumTemps = value_cid == kFloat64x2Cid ? 0 : 1;
3756 LocationSummary* summary = new(isolate) LocationSummary(
3757 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3758 summary->set_in(0, Location::RequiresRegister());
3759 if (kNumTemps > 0) {
3760 ASSERT(kNumTemps == 1);
3761 summary->set_temp(0, Location::RequiresRegister());
3762 }
3763 summary->set_out(0, Location::RequiresFpuRegister());
3764 return summary;
3765 }
3766
3767
3768 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3769 const intptr_t value_cid = value()->Type()->ToCid();
3770 const Register value = locs()->in(0).reg();
3771 const QRegister result = locs()->out(0).fpu_reg();
3772
3773 if (value_cid != kFloat64x2Cid) {
3774 const Register temp = locs()->temp(0).reg();
3775 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
3776 ICData::kDeoptCheckClass);
3777 __ tst(value, Operand(kSmiTagMask));
3778 __ b(deopt, EQ);
3779 __ CompareClassId(value, kFloat64x2Cid, temp);
3780 __ b(deopt, NE);
3781 }
3782
3783 const DRegister dresult0 = EvenDRegisterOf(result);
3784 __ LoadMultipleDFromOffset(dresult0, 2, value,
3785 Float64x2::value_offset() - kHeapObjectTag);
3786 }
3787
3788
3789 LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
3790 bool opt) const {
3791 const intptr_t kNumInputs = 1;
3792 const intptr_t kNumTemps = 1;
3793 LocationSummary* summary = new(isolate) LocationSummary(
3794 isolate, kNumInputs,
3795 kNumTemps,
3796 LocationSummary::kCallOnSlowPath);
3797 summary->set_in(0, Location::RequiresFpuRegister());
3798 summary->set_temp(0, Location::RequiresRegister());
3799 summary->set_out(0, Location::RequiresRegister());
3800 return summary;
3801 }
3802
3803
3804 void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3805 const Register out_reg = locs()->out(0).reg();
3806 const QRegister value = locs()->in(0).fpu_reg();
3807 const DRegister dvalue0 = EvenDRegisterOf(value);
3808
3809 BoxAllocationSlowPath::Allocate(
3810 compiler,
3811 this,
3812 compiler->int32x4_class(),
3813 out_reg,
3814 locs()->temp(0).reg());
3815 __ StoreMultipleDToOffset(dvalue0, 2, out_reg,
3816 Int32x4::value_offset() - kHeapObjectTag);
3817 }
3818
3819
3820 LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
3821 bool opt) const {
3822 const intptr_t value_cid = value()->Type()->ToCid();
3823 const intptr_t kNumInputs = 1;
3824 const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1;
3825 LocationSummary* summary = new(isolate) LocationSummary(
3826 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3827 summary->set_in(0, Location::RequiresRegister());
3828 if (kNumTemps > 0) {
3829 ASSERT(kNumTemps == 1);
3830 summary->set_temp(0, Location::RequiresRegister());
3831 }
3832 summary->set_out(0, Location::RequiresFpuRegister());
3833 return summary;
3834 }
3835
3836
3837 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3838 const intptr_t value_cid = value()->Type()->ToCid();
3839 const Register value = locs()->in(0).reg();
3840 const QRegister result = locs()->out(0).fpu_reg();
3841
3842 if (value_cid != kInt32x4Cid) {
3843 const Register temp = locs()->temp(0).reg();
3844 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
3845 ICData::kDeoptCheckClass);
3846 __ tst(value, Operand(kSmiTagMask));
3847 __ b(deopt, EQ);
3848 __ CompareClassId(value, kInt32x4Cid, temp);
3849 __ b(deopt, NE);
3850 }
3851
3852 const DRegister dresult0 = EvenDRegisterOf(result);
3853 __ LoadMultipleDFromOffset(dresult0, 2, value,
3854 Int32x4::value_offset() - kHeapObjectTag);
3855 }
3856
3857
3858 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, 3922 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate,
3859 bool opt) const { 3923 bool opt) const {
3860 const intptr_t kNumInputs = 2; 3924 const intptr_t kNumInputs = 2;
3861 const intptr_t kNumTemps = 0; 3925 const intptr_t kNumTemps = 0;
3862 LocationSummary* summary = new(isolate) LocationSummary( 3926 LocationSummary* summary = new(isolate) LocationSummary(
3863 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3927 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3864 summary->set_in(0, Location::RequiresFpuRegister()); 3928 summary->set_in(0, Location::RequiresFpuRegister());
3865 summary->set_in(1, Location::RequiresFpuRegister()); 3929 summary->set_in(1, Location::RequiresFpuRegister());
3866 summary->set_out(0, Location::RequiresFpuRegister()); 3930 summary->set_out(0, Location::RequiresFpuRegister());
3867 return summary; 3931 return summary;
(...skipping 2119 matching lines...) Expand 10 before | Expand all | Expand 10 after
5987 __ b(overflow, HI); 6051 __ b(overflow, HI);
5988 6052
5989 __ Bind(&check_lower); 6053 __ Bind(&check_lower);
5990 __ CompareImmediate(result_hi, -0x00200000); 6054 __ CompareImmediate(result_hi, -0x00200000);
5991 __ b(overflow, LT); 6055 __ b(overflow, LT);
5992 // Anything in the lower part would make the number bigger than the lower 6056 // Anything in the lower part would make the number bigger than the lower
5993 // bound, so we are done. 6057 // bound, so we are done.
5994 } 6058 }
5995 6059
5996 6060
5997 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate,
5998 bool opt) const {
5999 const intptr_t kNumInputs = 1;
6000 const intptr_t kNumTemps = 1;
6001 LocationSummary* summary = new(isolate) LocationSummary(
6002 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6003 summary->set_in(0, Location::RequiresRegister());
6004 summary->set_temp(0, Location::RequiresRegister());
6005 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6006 Location::RequiresRegister()));
6007 return summary;
6008 }
6009
6010
6011 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6012 const intptr_t value_cid = value()->Type()->ToCid();
6013 const Register value = locs()->in(0).reg();
6014 PairLocation* result_pair = locs()->out(0).AsPairLocation();
6015 Register result_lo = result_pair->At(0).reg();
6016 Register result_hi = result_pair->At(1).reg();
6017 ASSERT(value != result_lo);
6018 ASSERT(value != result_hi);
6019
6020 __ Comment("UnboxIntegerInstr");
6021 if (value_cid == kMintCid) {
6022 // Load low word.
6023 __ LoadFromOffset(kWord,
6024 result_lo,
6025 value,
6026 Mint::value_offset() - kHeapObjectTag);
6027 // Load high word.
6028 __ LoadFromOffset(kWord,
6029 result_hi,
6030 value,
6031 Mint::value_offset() - kHeapObjectTag + kWordSize);
6032 } else if (value_cid == kSmiCid) {
6033 // Load Smi into result_lo.
6034 __ mov(result_lo, Operand(value));
6035 // Untag.
6036 __ SmiUntag(result_lo);
6037 __ SignFill(result_hi, result_lo);
6038 } else {
6039 const Register temp = locs()->temp(0).reg();
6040 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
6041 ICData::kDeoptUnboxInteger);
6042 Label is_smi, done;
6043 __ tst(value, Operand(kSmiTagMask));
6044 __ b(&is_smi, EQ);
6045 __ CompareClassId(value, kMintCid, temp);
6046 __ b(deopt, NE);
6047
6048 // It's a Mint.
6049 // Load low word.
6050 __ LoadFromOffset(kWord,
6051 result_lo,
6052 value,
6053 Mint::value_offset() - kHeapObjectTag);
6054 // Load high word.
6055 __ LoadFromOffset(kWord,
6056 result_hi,
6057 value,
6058 Mint::value_offset() - kHeapObjectTag + kWordSize);
6059 __ b(&done);
6060
6061 // It's a Smi.
6062 __ Bind(&is_smi);
6063 // Load Smi into result_lo.
6064 __ mov(result_lo, Operand(value));
6065 // Untag.
6066 __ SmiUntag(result_lo);
6067 // Sign extend result_lo into result_hi.
6068 __ SignFill(result_hi, result_lo);
6069 __ Bind(&done);
6070 }
6071 }
6072
6073
6074 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate,
6075 bool opt) const {
6076 const intptr_t kNumInputs = 1;
6077 const intptr_t kNumTemps = is_smi() ? 0 : 1;
6078 LocationSummary* summary = new(isolate) LocationSummary(
6079 isolate, kNumInputs,
6080 kNumTemps,
6081 is_smi()
6082 ? LocationSummary::kNoCall
6083 : LocationSummary::kCallOnSlowPath);
6084 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6085 Location::RequiresRegister()));
6086 if (!is_smi()) {
6087 summary->set_temp(0, Location::RequiresRegister());
6088 }
6089 summary->set_out(0, Location::RequiresRegister());
6090 return summary;
6091 }
6092
6093
6094 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6095 if (is_smi()) {
6096 PairLocation* value_pair = locs()->in(0).AsPairLocation();
6097 Register value_lo = value_pair->At(0).reg();
6098 Register out_reg = locs()->out(0).reg();
6099 __ mov(out_reg, Operand(value_lo));
6100 __ SmiTag(out_reg);
6101 return;
6102 }
6103
6104 PairLocation* value_pair = locs()->in(0).AsPairLocation();
6105 Register value_lo = value_pair->At(0).reg();
6106 Register value_hi = value_pair->At(1).reg();
6107 Register tmp = locs()->temp(0).reg();
6108 Register out_reg = locs()->out(0).reg();
6109
6110 // Unboxed operations produce smis or mint-sized values.
6111 // Check if value fits into a smi.
6112 __ Comment("BoxIntegerInstr");
6113 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
6114 // Check high word.
6115 __ CompareImmediate(value_hi, 0);
6116 __ b(&maybe_pos_smi, EQ);
6117
6118 __ CompareImmediate(value_hi, -1);
6119 __ b(&maybe_neg_smi, EQ);
6120 __ b(&not_smi);
6121
6122 __ Bind(&maybe_pos_smi);
6123 __ CompareImmediate(value_lo, kSmiMax);
6124 __ b(&is_smi, LS); // unsigned lower or same.
6125 __ b(&not_smi);
6126
6127 __ Bind(&maybe_neg_smi);
6128 __ CompareImmediate(value_lo, 0);
6129 __ b(&not_smi, GE);
6130 __ CompareImmediate(value_lo, kSmiMin);
6131 __ b(&not_smi, LT);
6132
6133 // lo is a Smi. Tag it and return.
6134 __ Bind(&is_smi);
6135 __ mov(out_reg, Operand(value_lo));
6136 __ SmiTag(out_reg);
6137 __ b(&done);
6138
6139 // Not a smi. Box it.
6140 __ Bind(&not_smi);
6141 BoxAllocationSlowPath::Allocate(
6142 compiler,
6143 this,
6144 compiler->mint_class(),
6145 out_reg,
6146 tmp);
6147 __ StoreToOffset(kWord,
6148 value_lo,
6149 out_reg,
6150 Mint::value_offset() - kHeapObjectTag);
6151 __ StoreToOffset(kWord,
6152 value_hi,
6153 out_reg,
6154 Mint::value_offset() - kHeapObjectTag + kWordSize);
6155 __ Bind(&done);
6156 }
6157
6158
6159 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, 6061 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
6160 bool opt) const { 6062 bool opt) const {
6161 const intptr_t kNumInputs = 2; 6063 const intptr_t kNumInputs = 2;
6162 const intptr_t kNumTemps = 0; 6064 const intptr_t kNumTemps = 0;
6163 LocationSummary* summary = new(isolate) LocationSummary( 6065 LocationSummary* summary = new(isolate) LocationSummary(
6164 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6066 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6165 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6067 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6166 Location::RequiresRegister())); 6068 Location::RequiresRegister()));
6167 summary->set_in(1, Location::Pair(Location::RequiresRegister(), 6069 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
6168 Location::RequiresRegister())); 6070 Location::RequiresRegister()));
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
6570 Register left = locs()->in(0).reg(); 6472 Register left = locs()->in(0).reg();
6571 Register out = locs()->out(0).reg(); 6473 Register out = locs()->out(0).reg();
6572 ASSERT(left != out); 6474 ASSERT(left != out);
6573 6475
6574 ASSERT(op_kind() == Token::kBIT_NOT); 6476 ASSERT(op_kind() == Token::kBIT_NOT);
6575 6477
6576 __ mvn(out, Operand(left)); 6478 __ mvn(out, Operand(left));
6577 } 6479 }
6578 6480
6579 6481
6580 LocationSummary* BoxIntNInstr::MakeLocationSummary(Isolate* isolate,
6581 bool opt) const {
6582 ASSERT((from_representation() == kUnboxedInt32) ||
6583 (from_representation() == kUnboxedUint32));
6584 const intptr_t kNumInputs = 1;
6585 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
6586 LocationSummary* summary = new(isolate) LocationSummary(
6587 isolate,
6588 kNumInputs,
6589 kNumTemps,
6590 ValueFitsSmi() ? LocationSummary::kNoCall
6591 : LocationSummary::kCallOnSlowPath);
6592 summary->set_in(0, Location::RequiresRegister());
6593 if (!ValueFitsSmi()) {
6594 summary->set_temp(0, Location::RequiresRegister());
6595 }
6596 summary->set_out(0, Location::RequiresRegister());
6597 return summary;
6598 }
6599
6600
6601 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6602 Register value = locs()->in(0).reg();
6603 Register out = locs()->out(0).reg();
6604 ASSERT(value != out);
6605
6606 __ SmiTag(out, value);
6607 if (!ValueFitsSmi()) {
6608 Register temp = locs()->temp(0).reg();
6609 Label done;
6610 if (from_representation() == kUnboxedInt32) {
6611 __ cmp(value, Operand(out, ASR, 1));
6612 } else {
6613 ASSERT(from_representation() == kUnboxedUint32);
6614 // Note: better to test upper bits instead of comparing with
6615 // kSmiMax as kSmiMax does not fit into immediate operand.
6616 __ TestImmediate(value, 0xC0000000);
6617 }
6618 __ b(&done, EQ);
6619 BoxAllocationSlowPath::Allocate(
6620 compiler,
6621 this,
6622 compiler->mint_class(),
6623 out,
6624 temp);
6625 if (from_representation() == kUnboxedInt32) {
6626 __ Asr(temp, value, Operand(kBitsPerWord - 1));
6627 } else {
6628 ASSERT(from_representation() == kUnboxedUint32);
6629 __ eor(temp, temp, Operand(temp));
6630 }
6631 __ StoreToOffset(kWord,
6632 value,
6633 out,
6634 Mint::value_offset() - kHeapObjectTag);
6635 __ StoreToOffset(kWord,
6636 temp,
6637 out,
6638 Mint::value_offset() - kHeapObjectTag + kWordSize);
6639 __ Bind(&done);
6640 }
6641 }
6642
6643
6644 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
6645 Register mint,
6646 Register result,
6647 Register temp,
6648 Label* deopt) {
6649 __ LoadFromOffset(kWord,
6650 result,
6651 mint,
6652 Mint::value_offset() - kHeapObjectTag);
6653 if (deopt != NULL) {
6654 __ LoadFromOffset(kWord,
6655 temp,
6656 mint,
6657 Mint::value_offset() - kHeapObjectTag + kWordSize);
6658 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1));
6659 __ b(deopt, NE);
6660 }
6661 }
6662
6663
6664 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate,
6665 bool opt) const {
6666 ASSERT((representation() == kUnboxedInt32) ||
6667 (representation() == kUnboxedUint32));
6668 ASSERT((representation() != kUnboxedUint32) || is_truncating());
6669 const intptr_t kNumInputs = 1;
6670 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
6671 LocationSummary* summary = new(isolate) LocationSummary(
6672 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6673 summary->set_in(0, Location::RequiresRegister());
6674 if (kNumTemps > 0) {
6675 summary->set_temp(0, Location::RequiresRegister());
6676 }
6677 summary->set_out(0, Location::RequiresRegister());
6678 return summary;
6679 }
6680
6681
6682 void UnboxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6683 const intptr_t value_cid = value()->Type()->ToCid();
6684 const Register value = locs()->in(0).reg();
6685 const Register out = locs()->out(0).reg();
6686 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
6687 Label* deopt = CanDeoptimize() ?
6688 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL;
6689 Label* out_of_range = !is_truncating() ? deopt : NULL;
6690 ASSERT(value != out);
6691
6692 if (value_cid == kSmiCid) {
6693 __ SmiUntag(out, value);
6694 } else if (value_cid == kMintCid) {
6695 LoadInt32FromMint(compiler, value, out, temp, out_of_range);
6696 } else {
6697 Label done;
6698 __ SmiUntag(out, value, &done);
6699 __ CompareClassId(value, kMintCid, temp);
6700 __ b(deopt, NE);
6701 LoadInt32FromMint(compiler, value, out, temp, out_of_range);
6702 __ Bind(&done);
6703 }
6704 }
6705
6706
6707 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, 6482 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate,
6708 bool opt) const { 6483 bool opt) const {
6709 const intptr_t kNumInputs = 1; 6484 const intptr_t kNumInputs = 1;
6710 const intptr_t kNumTemps = 0; 6485 const intptr_t kNumTemps = 0;
6711 LocationSummary* summary = new(isolate) LocationSummary( 6486 LocationSummary* summary = new(isolate) LocationSummary(
6712 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6487 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6713 if (from() == kUnboxedMint) { 6488 if (from() == kUnboxedMint) {
6714 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); 6489 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
6715 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6490 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6716 Location::RequiresRegister())); 6491 Location::RequiresRegister()));
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
6987 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); 6762 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
6988 #if defined(DEBUG) 6763 #if defined(DEBUG)
6989 __ LoadImmediate(R4, kInvalidObjectPointer); 6764 __ LoadImmediate(R4, kInvalidObjectPointer);
6990 __ LoadImmediate(R5, kInvalidObjectPointer); 6765 __ LoadImmediate(R5, kInvalidObjectPointer);
6991 #endif 6766 #endif
6992 } 6767 }
6993 6768
6994 } // namespace dart 6769 } // namespace dart
6995 6770
6996 #endif // defined TARGET_ARCH_ARM 6771 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698