| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 case Token::kBIT_OR: | 1231 case Token::kBIT_OR: |
| 1232 case Token::kBIT_XOR: | 1232 case Token::kBIT_XOR: |
| 1233 return false; | 1233 return false; |
| 1234 case Token::kSHR: { | 1234 case Token::kSHR: { |
| 1235 // Can't deopt if shift-count is known positive. | 1235 // Can't deopt if shift-count is known positive. |
| 1236 Range* right_range = this->right()->definition()->range(); | 1236 Range* right_range = this->right()->definition()->range(); |
| 1237 return (right_range == NULL) || !right_range->IsPositive(); | 1237 return (right_range == NULL) || !right_range->IsPositive(); |
| 1238 } | 1238 } |
| 1239 case Token::kSHL: { | 1239 case Token::kSHL: { |
| 1240 Range* right_range = this->right()->definition()->range(); | 1240 Range* right_range = this->right()->definition()->range(); |
| 1241 if ((right_range != NULL) && is_truncating()) { | 1241 if ((right_range != NULL) && IsTruncating()) { |
| 1242 // Can deoptimize if right can be negative. | 1242 // Can deoptimize if right can be negative. |
| 1243 return !right_range->IsPositive(); | 1243 return !right_range->IsPositive(); |
| 1244 } | 1244 } |
| 1245 return true; | 1245 return true; |
| 1246 } | 1246 } |
| 1247 case Token::kMOD: { | 1247 case Token::kMOD: { |
| 1248 Range* right_range = this->right()->definition()->range(); | 1248 Range* right_range = this->right()->definition()->range(); |
| 1249 return (right_range == NULL) || right_range->Overlaps(0, 0); | 1249 return (right_range == NULL) || right_range->Overlaps(0, 0); |
| 1250 } | 1250 } |
| 1251 default: | 1251 default: |
| (...skipping 1948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3200 // Nothing new. | 3200 // Nothing new. |
| 3201 return; | 3201 return; |
| 3202 } | 3202 } |
| 3203 | 3203 |
| 3204 range_ = possible_range; | 3204 range_ = possible_range; |
| 3205 | 3205 |
| 3206 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown()); | 3206 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown()); |
| 3207 // Calculate overflowed status before clamping. | 3207 // Calculate overflowed status before clamping. |
| 3208 const bool overflowed = range_->min().LowerBound().OverflowedSmi() || | 3208 const bool overflowed = range_->min().LowerBound().OverflowedSmi() || |
| 3209 range_->max().UpperBound().OverflowedSmi(); | 3209 range_->max().UpperBound().OverflowedSmi(); |
| 3210 | |
| 3211 // Clamp value to be within smi range. | 3210 // Clamp value to be within smi range. |
| 3212 range_->Clamp(RangeBoundary::kRangeBoundarySmi); | 3211 range_->Clamp(RangeBoundary::kRangeBoundarySmi); |
| 3213 | 3212 |
| 3214 set_overflow(overflowed); | 3213 set_overflow(overflowed); |
| 3215 } | 3214 } |
| 3216 | 3215 |
| 3217 | 3216 |
| 3218 void BinaryMintOpInstr::InferRange() { | 3217 void BinaryMintOpInstr::InferRange() { |
| 3219 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on | 3218 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on |
| 3220 // the right and a non-constant on the left. | 3219 // the right and a non-constant on the left. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3369 | 3368 |
| 3370 *result_max = RangeBoundary::Shl( | 3369 *result_max = RangeBoundary::Shl( |
| 3371 left_max, | 3370 left_max, |
| 3372 left_max.ConstantValue() > 0 ? right_max : right_min, | 3371 left_max.ConstantValue() > 0 ? right_max : right_min, |
| 3373 left_max.ConstantValue() > 0 | 3372 left_max.ConstantValue() > 0 |
| 3374 ? RangeBoundary::PositiveInfinity() | 3373 ? RangeBoundary::PositiveInfinity() |
| 3375 : RangeBoundary::NegativeInfinity()); | 3374 : RangeBoundary::NegativeInfinity()); |
| 3376 } | 3375 } |
| 3377 | 3376 |
| 3378 | 3377 |
| 3378 void Range::Shr(const Range* left, |
| 3379 const Range* right, |
| 3380 RangeBoundary* result_min, |
| 3381 RangeBoundary* result_max) { |
| 3382 RangeBoundary left_max = Range::ConstantMax(left); |
| 3383 RangeBoundary left_min = Range::ConstantMin(left); |
| 3384 // A negative shift count always deoptimizes (and throws), so the minimum |
| 3385 // shift count is zero. |
| 3386 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(), |
| 3387 static_cast<int64_t>(0)); |
| 3388 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(), |
| 3389 static_cast<int64_t>(0)); |
| 3390 |
| 3391 *result_min = RangeBoundary::Shr( |
| 3392 left_min, |
| 3393 left_min.ConstantValue() > 0 ? right_max : right_min); |
| 3394 |
| 3395 *result_max = RangeBoundary::Shr( |
| 3396 left_max, |
| 3397 left_max.ConstantValue() > 0 ? right_min : right_max); |
| 3398 } |
| 3399 |
| 3400 |
| 3379 bool Range::And(const Range* left_range, | 3401 bool Range::And(const Range* left_range, |
| 3380 const Range* right_range, | 3402 const Range* right_range, |
| 3381 RangeBoundary* result_min, | 3403 RangeBoundary* result_min, |
| 3382 RangeBoundary* result_max) { | 3404 RangeBoundary* result_max) { |
| 3383 ASSERT(left_range != NULL); | 3405 ASSERT(left_range != NULL); |
| 3384 ASSERT(right_range != NULL); | 3406 ASSERT(right_range != NULL); |
| 3385 ASSERT(result_min != NULL); | 3407 ASSERT(result_min != NULL); |
| 3386 ASSERT(result_max != NULL); | 3408 ASSERT(result_max != NULL); |
| 3387 | 3409 |
| 3388 if (Range::ConstantMin(right_range).ConstantValue() >= 0) { | 3410 if (Range::ConstantMin(right_range).ConstantValue() >= 0) { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3540 case Token::kMUL: { | 3562 case Token::kMUL: { |
| 3541 if (!Range::Mul(left_range, right_range, &min, &max)) { | 3563 if (!Range::Mul(left_range, right_range, &min, &max)) { |
| 3542 return NULL; | 3564 return NULL; |
| 3543 } | 3565 } |
| 3544 break; | 3566 break; |
| 3545 } | 3567 } |
| 3546 case Token::kSHL: { | 3568 case Token::kSHL: { |
| 3547 Range::Shl(left_range, right_range, &min, &max); | 3569 Range::Shl(left_range, right_range, &min, &max); |
| 3548 break; | 3570 break; |
| 3549 } | 3571 } |
| 3572 case Token::kSHR: { |
| 3573 Range::Shr(left_range, right_range, &min, &max); |
| 3574 break; |
| 3575 } |
| 3550 case Token::kBIT_AND: | 3576 case Token::kBIT_AND: |
| 3551 if (!Range::And(left_range, right_range, &min, &max)) { | 3577 if (!Range::And(left_range, right_range, &min, &max)) { |
| 3552 return NULL; | 3578 return NULL; |
| 3553 } | 3579 } |
| 3554 break; | 3580 break; |
| 3555 default: | 3581 default: |
| 3556 return NULL; | 3582 return NULL; |
| 3557 break; | 3583 break; |
| 3558 } | 3584 } |
| 3559 | 3585 |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3888 case Token::kTRUNCDIV: return 0; | 3914 case Token::kTRUNCDIV: return 0; |
| 3889 case Token::kMOD: return 1; | 3915 case Token::kMOD: return 1; |
| 3890 default: UNIMPLEMENTED(); return -1; | 3916 default: UNIMPLEMENTED(); return -1; |
| 3891 } | 3917 } |
| 3892 } | 3918 } |
| 3893 | 3919 |
| 3894 | 3920 |
| 3895 #undef __ | 3921 #undef __ |
| 3896 | 3922 |
| 3897 } // namespace dart | 3923 } // namespace dart |
| OLD | NEW |