OLD | NEW |
1 | 1 |
2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
7 #if defined(TARGET_ARCH_ARM) | 7 #if defined(TARGET_ARCH_ARM) |
8 | 8 |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 | 10 |
(...skipping 3053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3064 __ cmp(left, Operand(IP, ASR, value)); | 3064 __ cmp(left, Operand(IP, ASR, value)); |
3065 __ b(deopt, NE); // Overflow. | 3065 __ b(deopt, NE); // Overflow. |
3066 } | 3066 } |
3067 // Shift for result now we know there is no overflow. | 3067 // Shift for result now we know there is no overflow. |
3068 __ Lsl(result, left, Operand(value)); | 3068 __ Lsl(result, left, Operand(value)); |
3069 return; | 3069 return; |
3070 } | 3070 } |
3071 | 3071 |
3072 // Right (locs.in(1)) is not constant. | 3072 // Right (locs.in(1)) is not constant. |
3073 const Register right = locs.in(1).reg(); | 3073 const Register right = locs.in(1).reg(); |
3074 Range* right_range = shift_left->right()->definition()->range(); | 3074 Range* right_range = shift_left->right_range(); |
3075 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 3075 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
3076 // TODO(srdjan): Implement code below for is_truncating(). | 3076 // TODO(srdjan): Implement code below for is_truncating(). |
3077 // If left is constant, we know the maximal allowed size for right. | 3077 // If left is constant, we know the maximal allowed size for right. |
3078 const Object& obj = shift_left->left()->BoundConstant(); | 3078 const Object& obj = shift_left->left()->BoundConstant(); |
3079 if (obj.IsSmi()) { | 3079 if (obj.IsSmi()) { |
3080 const intptr_t left_int = Smi::Cast(obj).Value(); | 3080 const intptr_t left_int = Smi::Cast(obj).Value(); |
3081 if (left_int == 0) { | 3081 if (left_int == 0) { |
3082 __ cmp(right, Operand(0)); | 3082 __ cmp(right, Operand(0)); |
3083 __ b(deopt, MI); | 3083 __ b(deopt, MI); |
3084 __ mov(result, Operand(0)); | 3084 __ mov(result, Operand(0)); |
3085 return; | 3085 return; |
3086 } | 3086 } |
3087 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 3087 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
3088 const bool right_needs_check = | 3088 const bool right_needs_check = |
3089 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 3089 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
3090 if (right_needs_check) { | 3090 if (right_needs_check) { |
3091 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); | 3091 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
3092 __ b(deopt, CS); | 3092 __ b(deopt, CS); |
3093 } | 3093 } |
3094 __ SmiUntag(IP, right); | 3094 __ SmiUntag(IP, right); |
3095 __ Lsl(result, left, IP); | 3095 __ Lsl(result, left, IP); |
3096 } | 3096 } |
3097 return; | 3097 return; |
3098 } | 3098 } |
3099 | 3099 |
3100 const bool right_needs_check = | 3100 const bool right_needs_check = |
3101 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 3101 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
3102 if (!shift_left->can_overflow()) { | 3102 if (!shift_left->can_overflow()) { |
3103 if (right_needs_check) { | 3103 if (right_needs_check) { |
3104 const bool right_may_be_negative = | 3104 if (!RangeUtils::IsPositive(right_range)) { |
3105 (right_range == NULL) || !right_range->IsPositive(); | |
3106 if (right_may_be_negative) { | |
3107 ASSERT(shift_left->CanDeoptimize()); | 3105 ASSERT(shift_left->CanDeoptimize()); |
3108 __ cmp(right, Operand(0)); | 3106 __ cmp(right, Operand(0)); |
3109 __ b(deopt, MI); | 3107 __ b(deopt, MI); |
3110 } | 3108 } |
3111 | 3109 |
3112 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 3110 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
3113 __ mov(result, Operand(0), CS); | 3111 __ mov(result, Operand(0), CS); |
3114 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC. | 3112 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC. |
3115 __ Lsl(result, left, IP, CC); | 3113 __ Lsl(result, left, IP, CC); |
3116 } else { | 3114 } else { |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3575 } | 3573 } |
3576 | 3574 |
3577 default: | 3575 default: |
3578 UNREACHABLE(); | 3576 UNREACHABLE(); |
3579 break; | 3577 break; |
3580 } | 3578 } |
3581 return; | 3579 return; |
3582 } | 3580 } |
3583 | 3581 |
3584 const Register right = locs()->in(1).reg(); | 3582 const Register right = locs()->in(1).reg(); |
3585 Range* right_range = this->right()->definition()->range(); | |
3586 switch (op_kind()) { | 3583 switch (op_kind()) { |
3587 case Token::kADD: { | 3584 case Token::kADD: { |
3588 if (deopt == NULL) { | 3585 if (deopt == NULL) { |
3589 __ add(result, left, Operand(right)); | 3586 __ add(result, left, Operand(right)); |
3590 } else { | 3587 } else { |
3591 __ adds(result, left, Operand(right)); | 3588 __ adds(result, left, Operand(right)); |
3592 __ b(deopt, VS); | 3589 __ b(deopt, VS); |
3593 } | 3590 } |
3594 break; | 3591 break; |
3595 } | 3592 } |
(...skipping 28 matching lines...) Expand all Loading... |
3624 __ orr(result, left, Operand(right)); | 3621 __ orr(result, left, Operand(right)); |
3625 break; | 3622 break; |
3626 } | 3623 } |
3627 case Token::kBIT_XOR: { | 3624 case Token::kBIT_XOR: { |
3628 // No overflow check. | 3625 // No overflow check. |
3629 __ eor(result, left, Operand(right)); | 3626 __ eor(result, left, Operand(right)); |
3630 break; | 3627 break; |
3631 } | 3628 } |
3632 case Token::kTRUNCDIV: { | 3629 case Token::kTRUNCDIV: { |
3633 ASSERT(TargetCPUFeatures::can_divide()); | 3630 ASSERT(TargetCPUFeatures::can_divide()); |
3634 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3631 if (RangeUtils::CanBeZero(right_range())) { |
3635 // Handle divide by zero in runtime. | 3632 // Handle divide by zero in runtime. |
3636 __ cmp(right, Operand(0)); | 3633 __ cmp(right, Operand(0)); |
3637 __ b(deopt, EQ); | 3634 __ b(deopt, EQ); |
3638 } | 3635 } |
3639 const Register temp = locs()->temp(0).reg(); | 3636 const Register temp = locs()->temp(0).reg(); |
3640 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3637 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
3641 __ SmiUntag(temp, left); | 3638 __ SmiUntag(temp, left); |
3642 __ SmiUntag(IP, right); | 3639 __ SmiUntag(IP, right); |
3643 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3640 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
3644 | 3641 |
3645 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3642 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
3646 // case we cannot tag the result. | 3643 // case we cannot tag the result. |
3647 __ CompareImmediate(result, 0x40000000); | 3644 __ CompareImmediate(result, 0x40000000); |
3648 __ b(deopt, EQ); | 3645 __ b(deopt, EQ); |
3649 __ SmiTag(result); | 3646 __ SmiTag(result); |
3650 break; | 3647 break; |
3651 } | 3648 } |
3652 case Token::kMOD: { | 3649 case Token::kMOD: { |
3653 ASSERT(TargetCPUFeatures::can_divide()); | 3650 ASSERT(TargetCPUFeatures::can_divide()); |
3654 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3651 if (RangeUtils::CanBeZero(right_range())) { |
3655 // Handle divide by zero in runtime. | 3652 // Handle divide by zero in runtime. |
3656 __ cmp(right, Operand(0)); | 3653 __ cmp(right, Operand(0)); |
3657 __ b(deopt, EQ); | 3654 __ b(deopt, EQ); |
3658 } | 3655 } |
3659 const Register temp = locs()->temp(0).reg(); | 3656 const Register temp = locs()->temp(0).reg(); |
3660 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3657 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
3661 __ SmiUntag(temp, left); | 3658 __ SmiUntag(temp, left); |
3662 __ SmiUntag(IP, right); | 3659 __ SmiUntag(IP, right); |
3663 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3660 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
3664 __ SmiUntag(IP, right); | 3661 __ SmiUntag(IP, right); |
(...skipping 18 matching lines...) Expand all Loading... |
3683 break; | 3680 break; |
3684 } | 3681 } |
3685 case Token::kSHR: { | 3682 case Token::kSHR: { |
3686 if (CanDeoptimize()) { | 3683 if (CanDeoptimize()) { |
3687 __ CompareImmediate(right, 0); | 3684 __ CompareImmediate(right, 0); |
3688 __ b(deopt, LT); | 3685 __ b(deopt, LT); |
3689 } | 3686 } |
3690 __ SmiUntag(IP, right); | 3687 __ SmiUntag(IP, right); |
3691 // sarl operation masks the count to 5 bits. | 3688 // sarl operation masks the count to 5 bits. |
3692 const intptr_t kCountLimit = 0x1F; | 3689 const intptr_t kCountLimit = 0x1F; |
3693 if ((right_range == NULL) || | 3690 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) { |
3694 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) { | |
3695 __ CompareImmediate(IP, kCountLimit); | 3691 __ CompareImmediate(IP, kCountLimit); |
3696 __ LoadImmediate(IP, kCountLimit, GT); | 3692 __ LoadImmediate(IP, kCountLimit, GT); |
3697 } | 3693 } |
3698 const Register temp = locs()->temp(0).reg(); | 3694 const Register temp = locs()->temp(0).reg(); |
3699 __ SmiUntag(temp, left); | 3695 __ SmiUntag(temp, left); |
3700 __ Asr(result, temp, IP); | 3696 __ Asr(result, temp, IP); |
3701 __ SmiTag(result); | 3697 __ SmiTag(result); |
3702 break; | 3698 break; |
3703 } | 3699 } |
3704 case Token::kDIV: { | 3700 case Token::kDIV: { |
(...skipping 2491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6196 __ vmovq(out, in); | 6192 __ vmovq(out, in); |
6197 } else { | 6193 } else { |
6198 ASSERT(representation() == kTagged); | 6194 ASSERT(representation() == kTagged); |
6199 const Register out = locs()->out(0).reg(); | 6195 const Register out = locs()->out(0).reg(); |
6200 const Register in = in_loc.reg(); | 6196 const Register in = in_loc.reg(); |
6201 __ mov(out, Operand(in)); | 6197 __ mov(out, Operand(in)); |
6202 } | 6198 } |
6203 } | 6199 } |
6204 | 6200 |
6205 | 6201 |
6206 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 6202 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
6207 bool opt) const { | 6203 bool opt) const { |
6208 if (kind() == MergedMathInstr::kTruncDivMod) { | 6204 const intptr_t kNumInputs = 2; |
6209 const intptr_t kNumInputs = 2; | 6205 const intptr_t kNumTemps = 2; |
6210 const intptr_t kNumTemps = 2; | 6206 LocationSummary* summary = new (zone) |
6211 LocationSummary* summary = new (zone) | 6207 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6212 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6208 summary->set_in(0, Location::RequiresRegister()); |
6213 summary->set_in(0, Location::RequiresRegister()); | 6209 summary->set_in(1, Location::RequiresRegister()); |
6214 summary->set_in(1, Location::RequiresRegister()); | 6210 summary->set_temp(0, Location::RequiresRegister()); |
6215 summary->set_temp(0, Location::RequiresRegister()); | 6211 summary->set_temp(1, Location::RequiresFpuRegister()); |
6216 summary->set_temp(1, Location::RequiresFpuRegister()); | 6212 // Output is a pair of registers. |
6217 // Output is a pair of registers. | 6213 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6218 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6214 Location::RequiresRegister())); |
6219 Location::RequiresRegister())); | 6215 return summary; |
6220 return summary; | |
6221 } | |
6222 UNIMPLEMENTED(); | |
6223 return NULL; | |
6224 } | 6216 } |
6225 | 6217 |
6226 | 6218 |
6227 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6219 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6228 Label* deopt = NULL; | 6220 ASSERT(CanDeoptimize()); |
6229 if (CanDeoptimize()) { | 6221 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
6230 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 6222 |
| 6223 ASSERT(TargetCPUFeatures::can_divide()); |
| 6224 const Register left = locs()->in(0).reg(); |
| 6225 const Register right = locs()->in(1).reg(); |
| 6226 ASSERT(locs()->out(0).IsPairLocation()); |
| 6227 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 6228 const Register result_div = pair->At(0).reg(); |
| 6229 const Register result_mod = pair->At(1).reg(); |
| 6230 if (RangeUtils::CanBeZero(divisor_range())) { |
| 6231 // Handle divide by zero in runtime. |
| 6232 __ cmp(right, Operand(0)); |
| 6233 __ b(deopt, EQ); |
6231 } | 6234 } |
6232 if (kind() == MergedMathInstr::kTruncDivMod) { | 6235 const Register temp = locs()->temp(0).reg(); |
6233 ASSERT(TargetCPUFeatures::can_divide()); | 6236 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
6234 const Register left = locs()->in(0).reg(); | 6237 __ SmiUntag(temp, left); |
6235 const Register right = locs()->in(1).reg(); | 6238 __ SmiUntag(IP, right); |
6236 ASSERT(locs()->out(0).IsPairLocation()); | 6239 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); |
6237 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
6238 const Register result_div = pair->At(0).reg(); | |
6239 const Register result_mod = pair->At(1).reg(); | |
6240 Range* right_range = InputAt(1)->definition()->range(); | |
6241 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | |
6242 // Handle divide by zero in runtime. | |
6243 __ cmp(right, Operand(0)); | |
6244 __ b(deopt, EQ); | |
6245 } | |
6246 const Register temp = locs()->temp(0).reg(); | |
6247 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | |
6248 __ SmiUntag(temp, left); | |
6249 __ SmiUntag(IP, right); | |
6250 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); | |
6251 | 6240 |
6252 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 6241 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
6253 // case we cannot tag the result. | 6242 // case we cannot tag the result. |
6254 __ CompareImmediate(result_div, 0x40000000); | 6243 __ CompareImmediate(result_div, 0x40000000); |
6255 __ b(deopt, EQ); | 6244 __ b(deopt, EQ); |
6256 __ SmiUntag(IP, right); | 6245 __ SmiUntag(IP, right); |
6257 // result_mod <- left - right * result_div. | 6246 // result_mod <- left - right * result_div. |
6258 __ mls(result_mod, IP, result_div, temp); | 6247 __ mls(result_mod, IP, result_div, temp); |
6259 __ SmiTag(result_div); | 6248 __ SmiTag(result_div); |
6260 __ SmiTag(result_mod); | 6249 __ SmiTag(result_mod); |
6261 // Correct MOD result: | 6250 // Correct MOD result: |
6262 // res = left % right; | 6251 // res = left % right; |
6263 // if (res < 0) { | 6252 // if (res < 0) { |
6264 // if (right < 0) { | 6253 // if (right < 0) { |
6265 // res = res - right; | 6254 // res = res - right; |
6266 // } else { | 6255 // } else { |
6267 // res = res + right; | 6256 // res = res + right; |
6268 // } | 6257 // } |
6269 // } | 6258 // } |
6270 Label done; | 6259 Label done; |
6271 __ cmp(result_mod, Operand(0)); | 6260 __ cmp(result_mod, Operand(0)); |
6272 __ b(&done, GE); | 6261 __ b(&done, GE); |
6273 // Result is negative, adjust it. | 6262 // Result is negative, adjust it. |
6274 __ cmp(right, Operand(0)); | 6263 __ cmp(right, Operand(0)); |
6275 __ sub(result_mod, result_mod, Operand(right), LT); | 6264 __ sub(result_mod, result_mod, Operand(right), LT); |
6276 __ add(result_mod, result_mod, Operand(right), GE); | 6265 __ add(result_mod, result_mod, Operand(right), GE); |
6277 __ Bind(&done); | 6266 __ Bind(&done); |
6278 | |
6279 return; | |
6280 } | |
6281 UNIMPLEMENTED(); | |
6282 } | 6267 } |
6283 | 6268 |
6284 | 6269 |
6285 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 6270 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
6286 Zone* zone, | 6271 Zone* zone, |
6287 bool opt) const { | 6272 bool opt) const { |
6288 return MakeCallSummary(zone); | 6273 return MakeCallSummary(zone); |
6289 } | 6274 } |
6290 | 6275 |
6291 | 6276 |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6626 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6611 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6627 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6612 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6628 Location::RequiresRegister())); | 6613 Location::RequiresRegister())); |
6629 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); | 6614 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
6630 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6615 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6631 Location::RequiresRegister())); | 6616 Location::RequiresRegister())); |
6632 return summary; | 6617 return summary; |
6633 } | 6618 } |
6634 | 6619 |
6635 | 6620 |
6636 static const intptr_t kMintShiftCountLimit = 63; | |
6637 | |
6638 bool ShiftMintOpInstr::has_shift_count_check() const { | |
6639 return !RangeUtils::IsWithin(right()->definition()->range(), 0, | |
6640 kMintShiftCountLimit); | |
6641 } | |
6642 | |
6643 | |
6644 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6621 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6645 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6622 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6646 Register left_lo = left_pair->At(0).reg(); | 6623 Register left_lo = left_pair->At(0).reg(); |
6647 Register left_hi = left_pair->At(1).reg(); | 6624 Register left_hi = left_pair->At(1).reg(); |
6648 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6625 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6649 Register out_lo = out_pair->At(0).reg(); | 6626 Register out_lo = out_pair->At(0).reg(); |
6650 Register out_hi = out_pair->At(1).reg(); | 6627 Register out_hi = out_pair->At(1).reg(); |
6651 | 6628 |
6652 Label* deopt = NULL; | 6629 Label* deopt = NULL; |
6653 if (CanDeoptimize()) { | 6630 if (CanDeoptimize()) { |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7269 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 7246 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
7270 kGrowRegExpStackRuntimeEntry, 1, locs()); | 7247 kGrowRegExpStackRuntimeEntry, 1, locs()); |
7271 __ Drop(1); | 7248 __ Drop(1); |
7272 __ Pop(result); | 7249 __ Pop(result); |
7273 } | 7250 } |
7274 | 7251 |
7275 | 7252 |
7276 } // namespace dart | 7253 } // namespace dart |
7277 | 7254 |
7278 #endif // defined TARGET_ARCH_ARM | 7255 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |