| 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 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 return true; | 1226 return true; |
| 1227 } | 1227 } |
| 1228 switch (op_kind()) { | 1228 switch (op_kind()) { |
| 1229 case Token::kBIT_AND: | 1229 case Token::kBIT_AND: |
| 1230 case Token::kBIT_OR: | 1230 case Token::kBIT_OR: |
| 1231 case Token::kBIT_XOR: | 1231 case Token::kBIT_XOR: |
| 1232 return false; | 1232 return false; |
| 1233 case Token::kSHR: { | 1233 case Token::kSHR: { |
| 1234 // Can't deopt if shift-count is known positive. | 1234 // Can't deopt if shift-count is known positive. |
| 1235 Range* right_range = this->right()->definition()->range(); | 1235 Range* right_range = this->right()->definition()->range(); |
| 1236 return (right_range == NULL) | 1236 return (right_range == NULL) || right_range->IsNegative(); |
| 1237 || !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); | |
| 1238 } | 1237 } |
| 1239 case Token::kSHL: { | 1238 case Token::kSHL: { |
| 1240 Range* right_range = this->right()->definition()->range(); | 1239 Range* right_range = this->right()->definition()->range(); |
| 1241 if ((right_range != NULL) && is_truncating()) { | 1240 if ((right_range != NULL) && is_truncating()) { |
| 1242 // Can deoptimize if right can be negative. | 1241 // Can deoptimize if right can be negative. |
| 1243 return !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); | 1242 return right_range->IsNegative(); |
| 1244 } | 1243 } |
| 1245 return true; | 1244 return true; |
| 1246 } | 1245 } |
| 1247 case Token::kMOD: { | 1246 case Token::kMOD: { |
| 1248 Range* right_range = this->right()->definition()->range(); | 1247 Range* right_range = this->right()->definition()->range(); |
| 1249 return (right_range == NULL) || right_range->Overlaps(0, 0); | 1248 return (right_range == NULL) || right_range->Overlaps(0, 0); |
| 1250 } | 1249 } |
| 1251 default: | 1250 default: |
| 1252 return overflow_; | 1251 return overflow_; |
| 1253 } | 1252 } |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2458 | 2457 |
| 2459 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { | 2458 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { |
| 2460 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { | 2459 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { |
| 2461 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); | 2460 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); |
| 2462 } | 2461 } |
| 2463 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); | 2462 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); |
| 2464 } | 2463 } |
| 2465 | 2464 |
| 2466 | 2465 |
| 2467 RangeBoundary RangeBoundary::LowerBound() const { | 2466 RangeBoundary RangeBoundary::LowerBound() const { |
| 2467 if (IsNegativeInfinity()) return *this; |
| 2468 if (IsConstant()) return *this; | 2468 if (IsConstant()) return *this; |
| 2469 return Add(Range::ConstantMin(symbol()->range()), | 2469 return Add(Range::ConstantMin(symbol()->range()), |
| 2470 RangeBoundary::FromConstant(offset_), | 2470 RangeBoundary::FromConstant(offset_), |
| 2471 OverflowedMinSmi()); | 2471 NegativeInfinity()); |
| 2472 } | 2472 } |
| 2473 | 2473 |
| 2474 | 2474 |
| 2475 RangeBoundary RangeBoundary::UpperBound() const { | 2475 RangeBoundary RangeBoundary::UpperBound() const { |
| 2476 if (IsPositiveInfinity()) return *this; |
| 2476 if (IsConstant()) return *this; | 2477 if (IsConstant()) return *this; |
| 2477 return Add(Range::ConstantMax(symbol()->range()), | 2478 return Add(Range::ConstantMax(symbol()->range()), |
| 2478 RangeBoundary::FromConstant(offset_), | 2479 RangeBoundary::FromConstant(offset_), |
| 2479 OverflowedMaxSmi()); | 2480 PositiveInfinity()); |
| 2480 } | 2481 } |
| 2481 | 2482 |
| 2482 | 2483 |
| 2483 static Definition* UnwrapConstraint(Definition* defn) { | 2484 static Definition* UnwrapConstraint(Definition* defn) { |
| 2484 while (defn->IsConstraint()) { | 2485 while (defn->IsConstraint()) { |
| 2485 defn = defn->AsConstraint()->value()->definition(); | 2486 defn = defn->AsConstraint()->value()->definition(); |
| 2486 } | 2487 } |
| 2487 return defn; | 2488 return defn; |
| 2488 } | 2489 } |
| 2489 | 2490 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2530 } else if (a.IsSymbol() && b.IsSymbol()) { | 2531 } else if (a.IsSymbol() && b.IsSymbol()) { |
| 2531 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); | 2532 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); |
| 2532 } else { | 2533 } else { |
| 2533 return false; | 2534 return false; |
| 2534 } | 2535 } |
| 2535 } | 2536 } |
| 2536 | 2537 |
| 2537 | 2538 |
| 2538 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, | 2539 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, |
| 2539 const RangeBoundary& overflow) { | 2540 const RangeBoundary& overflow) { |
| 2540 if (a.IsConstant()) return a; | 2541 if (a.IsConstant() || a.IsNegativeInfinity() || a.IsPositiveInfinity()) { |
| 2542 return a; |
| 2543 } |
| 2541 | 2544 |
| 2542 intptr_t offset = a.offset(); | 2545 intptr_t offset = a.offset(); |
| 2543 Definition* symbol = a.symbol(); | 2546 Definition* symbol = a.symbol(); |
| 2544 | 2547 |
| 2545 bool changed; | 2548 bool changed; |
| 2546 do { | 2549 do { |
| 2547 changed = false; | 2550 changed = false; |
| 2548 if (symbol->IsConstraint()) { | 2551 if (symbol->IsConstraint()) { |
| 2549 symbol = symbol->AsConstraint()->value()->definition(); | 2552 symbol = symbol->AsConstraint()->value()->definition(); |
| 2550 changed = true; | 2553 changed = true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2587 | 2590 |
| 2588 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { | 2591 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { |
| 2589 if (!a->IsSymbol()) return false; | 2592 if (!a->IsSymbol()) return false; |
| 2590 | 2593 |
| 2591 Range* range = a->symbol()->range(); | 2594 Range* range = a->symbol()->range(); |
| 2592 if ((range == NULL) || !range->max().IsSymbol()) return false; | 2595 if ((range == NULL) || !range->max().IsSymbol()) return false; |
| 2593 | 2596 |
| 2594 const intptr_t offset = range->max().offset() + a->offset(); | 2597 const intptr_t offset = range->max().offset() + a->offset(); |
| 2595 | 2598 |
| 2596 if (!Smi::IsValid(offset)) { | 2599 if (!Smi::IsValid(offset)) { |
| 2597 *a = RangeBoundary::OverflowedMaxSmi(); | 2600 *a = RangeBoundary::PositiveInfinity(); |
| 2598 return true; | 2601 return true; |
| 2599 } | 2602 } |
| 2600 | 2603 |
| 2601 *a = CanonicalizeBoundary( | 2604 *a = CanonicalizeBoundary( |
| 2602 RangeBoundary::FromDefinition(range->max().symbol(), offset), | 2605 RangeBoundary::FromDefinition(range->max().symbol(), offset), |
| 2603 RangeBoundary::OverflowedMaxSmi()); | 2606 RangeBoundary::PositiveInfinity()); |
| 2604 | 2607 |
| 2605 return true; | 2608 return true; |
| 2606 } | 2609 } |
| 2607 | 2610 |
| 2608 | 2611 |
| 2609 static bool CanonicalizeMinBoundary(RangeBoundary* a) { | 2612 static bool CanonicalizeMinBoundary(RangeBoundary* a) { |
| 2610 if (!a->IsSymbol()) return false; | 2613 if (!a->IsSymbol()) return false; |
| 2611 | 2614 |
| 2612 Range* range = a->symbol()->range(); | 2615 Range* range = a->symbol()->range(); |
| 2613 if ((range == NULL) || !range->min().IsSymbol()) return false; | 2616 if ((range == NULL) || !range->min().IsSymbol()) return false; |
| 2614 | 2617 |
| 2615 const intptr_t offset = range->min().offset() + a->offset(); | 2618 const intptr_t offset = range->min().offset() + a->offset(); |
| 2616 if (!Smi::IsValid(offset)) { | 2619 if (!Smi::IsValid(offset)) { |
| 2617 *a = RangeBoundary::OverflowedMinSmi(); | 2620 *a = RangeBoundary::NegativeInfinity(); |
| 2618 return true; | 2621 return true; |
| 2619 } | 2622 } |
| 2620 | 2623 |
| 2621 *a = CanonicalizeBoundary( | 2624 *a = CanonicalizeBoundary( |
| 2622 RangeBoundary::FromDefinition(range->min().symbol(), offset), | 2625 RangeBoundary::FromDefinition(range->min().symbol(), offset), |
| 2623 RangeBoundary::OverflowedMinSmi()); | 2626 RangeBoundary::NegativeInfinity()); |
| 2624 | 2627 |
| 2625 return true; | 2628 return true; |
| 2626 } | 2629 } |
| 2627 | 2630 |
| 2628 | 2631 |
| 2629 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { | 2632 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { |
| 2630 if (DependOnSameSymbol(a, b)) { | 2633 if (DependOnSameSymbol(a, b)) { |
| 2631 return (a.offset() <= b.offset()) ? a : b; | 2634 return (a.offset() <= b.offset()) ? a : b; |
| 2632 } | 2635 } |
| 2633 | 2636 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2678 min = constraint()->min(); | 2681 min = constraint()->min(); |
| 2679 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { | 2682 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { |
| 2680 min = value_range->min(); | 2683 min = value_range->min(); |
| 2681 } else if ((value_range != NULL) && | 2684 } else if ((value_range != NULL) && |
| 2682 IsEqual(constraint()->min(), value_range->min())) { | 2685 IsEqual(constraint()->min(), value_range->min())) { |
| 2683 min = constraint()->min(); | 2686 min = constraint()->min(); |
| 2684 } else { | 2687 } else { |
| 2685 if (value_range != NULL) { | 2688 if (value_range != NULL) { |
| 2686 RangeBoundary canonical_a = | 2689 RangeBoundary canonical_a = |
| 2687 CanonicalizeBoundary(constraint()->min(), | 2690 CanonicalizeBoundary(constraint()->min(), |
| 2688 RangeBoundary::OverflowedMinSmi()); | 2691 RangeBoundary::NegativeInfinity()); |
| 2689 RangeBoundary canonical_b = | 2692 RangeBoundary canonical_b = |
| 2690 CanonicalizeBoundary(value_range->min(), | 2693 CanonicalizeBoundary(value_range->min(), |
| 2691 RangeBoundary::OverflowedMinSmi()); | 2694 RangeBoundary::NegativeInfinity()); |
| 2692 | 2695 |
| 2693 do { | 2696 do { |
| 2694 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2697 if (DependOnSameSymbol(canonical_a, canonical_b)) { |
| 2695 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b | 2698 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b |
| 2696 : canonical_a; | 2699 : canonical_a; |
| 2697 } | 2700 } |
| 2698 } while (CanonicalizeMinBoundary(&canonical_a) || | 2701 } while (CanonicalizeMinBoundary(&canonical_a) || |
| 2699 CanonicalizeMinBoundary(&canonical_b)); | 2702 CanonicalizeMinBoundary(&canonical_b)); |
| 2700 } | 2703 } |
| 2701 | 2704 |
| 2702 if (min.IsUnknown()) { | 2705 if (min.IsUnknown()) { |
| 2703 min = RangeBoundary::Max(Range::ConstantMin(value_range), | 2706 min = RangeBoundary::Max(Range::ConstantMin(value_range), |
| 2704 Range::ConstantMin(constraint())); | 2707 Range::ConstantMin(constraint())); |
| 2705 } | 2708 } |
| 2706 } | 2709 } |
| 2707 | 2710 |
| 2708 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { | 2711 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { |
| 2709 max = constraint()->max(); | 2712 max = constraint()->max(); |
| 2710 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { | 2713 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { |
| 2711 max = value_range->max(); | 2714 max = value_range->max(); |
| 2712 } else if ((value_range != NULL) && | 2715 } else if ((value_range != NULL) && |
| 2713 IsEqual(constraint()->max(), value_range->max())) { | 2716 IsEqual(constraint()->max(), value_range->max())) { |
| 2714 max = constraint()->max(); | 2717 max = constraint()->max(); |
| 2715 } else { | 2718 } else { |
| 2716 if (value_range != NULL) { | 2719 if (value_range != NULL) { |
| 2717 RangeBoundary canonical_b = | 2720 RangeBoundary canonical_b = |
| 2718 CanonicalizeBoundary(value_range->max(), | 2721 CanonicalizeBoundary(value_range->max(), |
| 2719 RangeBoundary::OverflowedMaxSmi()); | 2722 RangeBoundary::PositiveInfinity()); |
| 2720 RangeBoundary canonical_a = | 2723 RangeBoundary canonical_a = |
| 2721 CanonicalizeBoundary(constraint()->max(), | 2724 CanonicalizeBoundary(constraint()->max(), |
| 2722 RangeBoundary::OverflowedMaxSmi()); | 2725 RangeBoundary::PositiveInfinity()); |
| 2723 | 2726 |
| 2724 do { | 2727 do { |
| 2725 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2728 if (DependOnSameSymbol(canonical_a, canonical_b)) { |
| 2726 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a | 2729 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a |
| 2727 : canonical_b; | 2730 : canonical_b; |
| 2728 break; | 2731 break; |
| 2729 } | 2732 } |
| 2730 } while (CanonicalizeMaxBoundary(&canonical_a) || | 2733 } while (CanonicalizeMaxBoundary(&canonical_a) || |
| 2731 CanonicalizeMaxBoundary(&canonical_b)); | 2734 CanonicalizeMaxBoundary(&canonical_b)); |
| 2732 } | 2735 } |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3053 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | 3056 RangeBoundary::FromDefinition(left_defn) : left_range->max(); |
| 3054 | 3057 |
| 3055 RangeBoundary min; | 3058 RangeBoundary min; |
| 3056 RangeBoundary max; | 3059 RangeBoundary max; |
| 3057 switch (op_kind()) { | 3060 switch (op_kind()) { |
| 3058 case Token::kADD: | 3061 case Token::kADD: |
| 3059 if (!SymbolicAdd(left_min, right_range->min(), &min)) { | 3062 if (!SymbolicAdd(left_min, right_range->min(), &min)) { |
| 3060 min = | 3063 min = |
| 3061 RangeBoundary::Add(Range::ConstantMin(left_range), | 3064 RangeBoundary::Add(Range::ConstantMin(left_range), |
| 3062 Range::ConstantMin(right_range), | 3065 Range::ConstantMin(right_range), |
| 3063 RangeBoundary::OverflowedMinSmi()); | 3066 RangeBoundary::NegativeInfinity()); |
| 3064 } | 3067 } |
| 3065 | 3068 |
| 3066 if (!SymbolicAdd(left_max, right_range->max(), &max)) { | 3069 if (!SymbolicAdd(left_max, right_range->max(), &max)) { |
| 3067 max = | 3070 max = |
| 3068 RangeBoundary::Add(Range::ConstantMax(right_range), | 3071 RangeBoundary::Add(Range::ConstantMax(right_range), |
| 3069 Range::ConstantMax(left_range), | 3072 Range::ConstantMax(left_range), |
| 3070 RangeBoundary::OverflowedMaxSmi()); | 3073 RangeBoundary::PositiveInfinity()); |
| 3071 } | 3074 } |
| 3072 break; | 3075 break; |
| 3073 | 3076 |
| 3074 case Token::kSUB: | 3077 case Token::kSUB: |
| 3075 if (!SymbolicSub(left_min, right_range->max(), &min)) { | 3078 if (!SymbolicSub(left_min, right_range->max(), &min)) { |
| 3076 min = | 3079 min = |
| 3077 RangeBoundary::Sub(Range::ConstantMin(left_range), | 3080 RangeBoundary::Sub(Range::ConstantMin(left_range), |
| 3078 Range::ConstantMax(right_range), | 3081 Range::ConstantMax(right_range), |
| 3079 RangeBoundary::OverflowedMinSmi()); | 3082 RangeBoundary::NegativeInfinity()); |
| 3080 } | 3083 } |
| 3081 | 3084 |
| 3082 if (!SymbolicSub(left_max, right_range->min(), &max)) { | 3085 if (!SymbolicSub(left_max, right_range->min(), &max)) { |
| 3083 max = | 3086 max = |
| 3084 RangeBoundary::Sub(Range::ConstantMax(left_range), | 3087 RangeBoundary::Sub(Range::ConstantMax(left_range), |
| 3085 Range::ConstantMin(right_range), | 3088 Range::ConstantMin(right_range), |
| 3086 RangeBoundary::OverflowedMaxSmi()); | 3089 RangeBoundary::PositiveInfinity()); |
| 3087 } | 3090 } |
| 3088 break; | 3091 break; |
| 3089 | 3092 |
| 3090 case Token::kMUL: { | 3093 case Token::kMUL: { |
| 3091 const int64_t left_max = ConstantAbsMax(left_range); | 3094 const int64_t left_max = ConstantAbsMax(left_range); |
| 3092 const int64_t right_max = ConstantAbsMax(right_range); | 3095 const int64_t right_max = ConstantAbsMax(right_range); |
| 3093 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { | 3096 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { |
| 3094 // Product of left and right max values stays in 64 bit range. | 3097 // Product of left and right max values stays in 64 bit range. |
| 3095 const int64_t result_max = left_max * right_max; | 3098 const int64_t result_max = left_max * right_max; |
| 3096 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | 3099 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3135 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | 3138 ASSERT(!min.IsUnknown() && !max.IsUnknown()); |
| 3136 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); | 3139 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); |
| 3137 | 3140 |
| 3138 if (min.IsConstant()) min.Clamp(); | 3141 if (min.IsConstant()) min.Clamp(); |
| 3139 if (max.IsConstant()) max.Clamp(); | 3142 if (max.IsConstant()) max.Clamp(); |
| 3140 | 3143 |
| 3141 range_ = new Range(min, max); | 3144 range_ = new Range(min, max); |
| 3142 } | 3145 } |
| 3143 | 3146 |
| 3144 | 3147 |
| 3148 bool Range::IsPositive() const { |
| 3149 if (min().IsNegativeInfinity()) { |
| 3150 return false; |
| 3151 } |
| 3152 if (min().LowerBound().value() < 0) { |
| 3153 return false; |
| 3154 } |
| 3155 if (max().IsPositiveInfinity()) { |
| 3156 return true; |
| 3157 } |
| 3158 return max().UpperBound().value() >= 0; |
| 3159 } |
| 3160 |
| 3161 |
| 3162 bool Range::IsNegative() const { |
| 3163 if (max().IsPositiveInfinity()) { |
| 3164 return false; |
| 3165 } |
| 3166 if (max().UpperBound().value() >= 0) { |
| 3167 return false; |
| 3168 } |
| 3169 if (min().IsNegativeInfinity()) { |
| 3170 return true; |
| 3171 } |
| 3172 return min().LowerBound().value() < 0; |
| 3173 } |
| 3174 |
| 3175 |
| 3176 bool Range::OnlyLessThanOrEqualTo(intptr_t val) const { |
| 3177 if (max().IsPositiveInfinity()) { |
| 3178 // Cannot be true. |
| 3179 return false; |
| 3180 } |
| 3181 if (max().UpperBound().value() > val) { |
| 3182 // Not true. |
| 3183 return false; |
| 3184 } |
| 3185 if (!min().IsNegativeInfinity()) { |
| 3186 if (min().LowerBound().value() > val) { |
| 3187 // Lower bound is > value. |
| 3188 return false; |
| 3189 } |
| 3190 } |
| 3191 return true; |
| 3192 } |
| 3193 |
| 3194 |
| 3145 // Inclusive. | 3195 // Inclusive. |
| 3146 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { | 3196 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { |
| 3147 if (min().LowerBound().value() < min_int) return false; | 3197 RangeBoundary lower_min = min().LowerBound(); |
| 3148 if (max().UpperBound().value() > max_int) return false; | 3198 if (lower_min.IsNegativeInfinity() || (lower_min.value() < min_int)) { |
| 3199 return false; |
| 3200 } |
| 3201 RangeBoundary upper_max = max().UpperBound(); |
| 3202 if (upper_max.IsPositiveInfinity() || (upper_max.value() > max_int)) { |
| 3203 return false; |
| 3204 } |
| 3149 return true; | 3205 return true; |
| 3150 } | 3206 } |
| 3151 | 3207 |
| 3152 | 3208 |
| 3153 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { | 3209 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { |
| 3154 const intptr_t this_min = min().LowerBound().value(); | 3210 const intptr_t this_min = min().IsNegativeInfinity() ? |
| 3155 const intptr_t this_max = max().UpperBound().value(); | 3211 kIntptrMin : min().LowerBound().value(); |
| 3212 const intptr_t this_max = max().IsPositiveInfinity() ? |
| 3213 kIntptrMax : max().UpperBound().value(); |
| 3156 if ((this_min <= min_int) && (min_int <= this_max)) return true; | 3214 if ((this_min <= min_int) && (min_int <= this_max)) return true; |
| 3157 if ((this_min <= max_int) && (max_int <= this_max)) return true; | 3215 if ((this_min <= max_int) && (max_int <= this_max)) return true; |
| 3158 if ((min_int < this_min) && (max_int > this_max)) return true; | 3216 if ((min_int < this_min) && (max_int > this_max)) return true; |
| 3159 return false; | 3217 return false; |
| 3160 } | 3218 } |
| 3161 | 3219 |
| 3162 | 3220 |
| 3163 bool Range::IsUnsatisfiable() const { | 3221 bool Range::IsUnsatisfiable() const { |
| 3222 // Infinity case: [+inf, ...] || [..., -inf] |
| 3223 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { |
| 3224 return true; |
| 3225 } |
| 3164 // Constant case: For example [0, -1]. | 3226 // Constant case: For example [0, -1]. |
| 3165 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { | 3227 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { |
| 3166 return true; | 3228 return true; |
| 3167 } | 3229 } |
| 3168 // Symbol case: For example [v+1, v]. | 3230 // Symbol case: For example [v+1, v]. |
| 3169 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { | 3231 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { |
| 3170 return true; | 3232 return true; |
| 3171 } | 3233 } |
| 3172 return false; | 3234 return false; |
| 3173 } | 3235 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3185 if (index_range == NULL) { | 3247 if (index_range == NULL) { |
| 3186 return false; | 3248 return false; |
| 3187 } | 3249 } |
| 3188 | 3250 |
| 3189 // Range of the index is not positive. Check can't be redundant. | 3251 // Range of the index is not positive. Check can't be redundant. |
| 3190 if (Range::ConstantMin(index_range).value() < 0) { | 3252 if (Range::ConstantMin(index_range).value() < 0) { |
| 3191 return false; | 3253 return false; |
| 3192 } | 3254 } |
| 3193 | 3255 |
| 3194 RangeBoundary max = CanonicalizeBoundary(index_range->max(), | 3256 RangeBoundary max = CanonicalizeBoundary(index_range->max(), |
| 3195 RangeBoundary::OverflowedMaxSmi()); | 3257 RangeBoundary::PositiveInfinity()); |
| 3196 | 3258 |
| 3197 if (max.Overflowed()) { | 3259 if (max.Overflowed()) { |
| 3198 return false; | 3260 return false; |
| 3199 } | 3261 } |
| 3200 | 3262 |
| 3263 |
| 3264 RangeBoundary max_upper = max.UpperBound(); |
| 3265 RangeBoundary length_lower = length.LowerBound(); |
| 3266 |
| 3267 if (max_upper.Overflowed() || length_lower.Overflowed()) { |
| 3268 return false; |
| 3269 } |
| 3270 |
| 3201 // Try to compare constant boundaries. | 3271 // Try to compare constant boundaries. |
| 3202 if (max.UpperBound().value() < length.LowerBound().value()) { | 3272 if (max_upper.value() < length_lower.value()) { |
| 3203 return true; | 3273 return true; |
| 3204 } | 3274 } |
| 3205 | 3275 |
| 3206 length = CanonicalizeBoundary(length, RangeBoundary::OverflowedMaxSmi()); | 3276 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); |
| 3207 if (length.Overflowed()) { | 3277 if (length.Overflowed()) { |
| 3208 return false; | 3278 return false; |
| 3209 } | 3279 } |
| 3210 | 3280 |
| 3211 // Try symbolic comparison. | 3281 // Try symbolic comparison. |
| 3212 do { | 3282 do { |
| 3213 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); | 3283 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); |
| 3214 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); | 3284 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); |
| 3215 | 3285 |
| 3216 // Failed to prove that maximum is bounded with array length. | 3286 // Failed to prove that maximum is bounded with array length. |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3490 case Token::kTRUNCDIV: return 0; | 3560 case Token::kTRUNCDIV: return 0; |
| 3491 case Token::kMOD: return 1; | 3561 case Token::kMOD: return 1; |
| 3492 default: UNIMPLEMENTED(); return -1; | 3562 default: UNIMPLEMENTED(); return -1; |
| 3493 } | 3563 } |
| 3494 } | 3564 } |
| 3495 | 3565 |
| 3496 | 3566 |
| 3497 #undef __ | 3567 #undef __ |
| 3498 | 3568 |
| 3499 } // namespace dart | 3569 } // namespace dart |
| OLD | NEW |