| 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 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 | 2436 |
| 2438 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { | 2437 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { |
| 2439 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { | 2438 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { |
| 2440 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); | 2439 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); |
| 2441 } | 2440 } |
| 2442 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); | 2441 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); |
| 2443 } | 2442 } |
| 2444 | 2443 |
| 2445 | 2444 |
| 2446 RangeBoundary RangeBoundary::LowerBound() const { | 2445 RangeBoundary RangeBoundary::LowerBound() const { |
| 2446 if (IsNegativeInfinity()) return *this; |
| 2447 if (IsConstant()) return *this; | 2447 if (IsConstant()) return *this; |
| 2448 return Add(Range::ConstantMin(symbol()->range()), | 2448 return Add(Range::ConstantMin(symbol()->range()), |
| 2449 RangeBoundary::FromConstant(offset_), | 2449 RangeBoundary::FromConstant(offset_), |
| 2450 OverflowedMinSmi()); | 2450 NegativeInfinity()); |
| 2451 } | 2451 } |
| 2452 | 2452 |
| 2453 | 2453 |
| 2454 RangeBoundary RangeBoundary::UpperBound() const { | 2454 RangeBoundary RangeBoundary::UpperBound() const { |
| 2455 if (IsPositiveInfinity()) return *this; |
| 2455 if (IsConstant()) return *this; | 2456 if (IsConstant()) return *this; |
| 2456 return Add(Range::ConstantMax(symbol()->range()), | 2457 return Add(Range::ConstantMax(symbol()->range()), |
| 2457 RangeBoundary::FromConstant(offset_), | 2458 RangeBoundary::FromConstant(offset_), |
| 2458 OverflowedMaxSmi()); | 2459 PositiveInfinity()); |
| 2459 } | 2460 } |
| 2460 | 2461 |
| 2461 | 2462 |
| 2462 static Definition* UnwrapConstraint(Definition* defn) { | 2463 static Definition* UnwrapConstraint(Definition* defn) { |
| 2463 while (defn->IsConstraint()) { | 2464 while (defn->IsConstraint()) { |
| 2464 defn = defn->AsConstraint()->value()->definition(); | 2465 defn = defn->AsConstraint()->value()->definition(); |
| 2465 } | 2466 } |
| 2466 return defn; | 2467 return defn; |
| 2467 } | 2468 } |
| 2468 | 2469 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2509 } else if (a.IsSymbol() && b.IsSymbol()) { | 2510 } else if (a.IsSymbol() && b.IsSymbol()) { |
| 2510 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); | 2511 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); |
| 2511 } else { | 2512 } else { |
| 2512 return false; | 2513 return false; |
| 2513 } | 2514 } |
| 2514 } | 2515 } |
| 2515 | 2516 |
| 2516 | 2517 |
| 2517 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, | 2518 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, |
| 2518 const RangeBoundary& overflow) { | 2519 const RangeBoundary& overflow) { |
| 2519 if (a.IsConstant()) return a; | 2520 if (a.IsConstant() || a.IsNegativeInfinity() || a.IsPositiveInfinity()) { |
| 2521 return a; |
| 2522 } |
| 2520 | 2523 |
| 2521 intptr_t offset = a.offset(); | 2524 intptr_t offset = a.offset(); |
| 2522 Definition* symbol = a.symbol(); | 2525 Definition* symbol = a.symbol(); |
| 2523 | 2526 |
| 2524 bool changed; | 2527 bool changed; |
| 2525 do { | 2528 do { |
| 2526 changed = false; | 2529 changed = false; |
| 2527 if (symbol->IsConstraint()) { | 2530 if (symbol->IsConstraint()) { |
| 2528 symbol = symbol->AsConstraint()->value()->definition(); | 2531 symbol = symbol->AsConstraint()->value()->definition(); |
| 2529 changed = true; | 2532 changed = true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2566 | 2569 |
| 2567 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { | 2570 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { |
| 2568 if (!a->IsSymbol()) return false; | 2571 if (!a->IsSymbol()) return false; |
| 2569 | 2572 |
| 2570 Range* range = a->symbol()->range(); | 2573 Range* range = a->symbol()->range(); |
| 2571 if ((range == NULL) || !range->max().IsSymbol()) return false; | 2574 if ((range == NULL) || !range->max().IsSymbol()) return false; |
| 2572 | 2575 |
| 2573 const intptr_t offset = range->max().offset() + a->offset(); | 2576 const intptr_t offset = range->max().offset() + a->offset(); |
| 2574 | 2577 |
| 2575 if (!Smi::IsValid(offset)) { | 2578 if (!Smi::IsValid(offset)) { |
| 2576 *a = RangeBoundary::OverflowedMaxSmi(); | 2579 *a = RangeBoundary::PositiveInfinity(); |
| 2577 return true; | 2580 return true; |
| 2578 } | 2581 } |
| 2579 | 2582 |
| 2580 *a = CanonicalizeBoundary( | 2583 *a = CanonicalizeBoundary( |
| 2581 RangeBoundary::FromDefinition(range->max().symbol(), offset), | 2584 RangeBoundary::FromDefinition(range->max().symbol(), offset), |
| 2582 RangeBoundary::OverflowedMaxSmi()); | 2585 RangeBoundary::PositiveInfinity()); |
| 2583 | 2586 |
| 2584 return true; | 2587 return true; |
| 2585 } | 2588 } |
| 2586 | 2589 |
| 2587 | 2590 |
| 2588 static bool CanonicalizeMinBoundary(RangeBoundary* a) { | 2591 static bool CanonicalizeMinBoundary(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->min().IsSymbol()) return false; | 2595 if ((range == NULL) || !range->min().IsSymbol()) return false; |
| 2593 | 2596 |
| 2594 const intptr_t offset = range->min().offset() + a->offset(); | 2597 const intptr_t offset = range->min().offset() + a->offset(); |
| 2595 if (!Smi::IsValid(offset)) { | 2598 if (!Smi::IsValid(offset)) { |
| 2596 *a = RangeBoundary::OverflowedMinSmi(); | 2599 *a = RangeBoundary::NegativeInfinity(); |
| 2597 return true; | 2600 return true; |
| 2598 } | 2601 } |
| 2599 | 2602 |
| 2600 *a = CanonicalizeBoundary( | 2603 *a = CanonicalizeBoundary( |
| 2601 RangeBoundary::FromDefinition(range->min().symbol(), offset), | 2604 RangeBoundary::FromDefinition(range->min().symbol(), offset), |
| 2602 RangeBoundary::OverflowedMinSmi()); | 2605 RangeBoundary::NegativeInfinity()); |
| 2603 | 2606 |
| 2604 return true; | 2607 return true; |
| 2605 } | 2608 } |
| 2606 | 2609 |
| 2607 | 2610 |
| 2608 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { | 2611 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { |
| 2609 if (DependOnSameSymbol(a, b)) { | 2612 if (DependOnSameSymbol(a, b)) { |
| 2610 return (a.offset() <= b.offset()) ? a : b; | 2613 return (a.offset() <= b.offset()) ? a : b; |
| 2611 } | 2614 } |
| 2612 | 2615 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2657 min = constraint()->min(); | 2660 min = constraint()->min(); |
| 2658 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { | 2661 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { |
| 2659 min = value_range->min(); | 2662 min = value_range->min(); |
| 2660 } else if ((value_range != NULL) && | 2663 } else if ((value_range != NULL) && |
| 2661 IsEqual(constraint()->min(), value_range->min())) { | 2664 IsEqual(constraint()->min(), value_range->min())) { |
| 2662 min = constraint()->min(); | 2665 min = constraint()->min(); |
| 2663 } else { | 2666 } else { |
| 2664 if (value_range != NULL) { | 2667 if (value_range != NULL) { |
| 2665 RangeBoundary canonical_a = | 2668 RangeBoundary canonical_a = |
| 2666 CanonicalizeBoundary(constraint()->min(), | 2669 CanonicalizeBoundary(constraint()->min(), |
| 2667 RangeBoundary::OverflowedMinSmi()); | 2670 RangeBoundary::NegativeInfinity()); |
| 2668 RangeBoundary canonical_b = | 2671 RangeBoundary canonical_b = |
| 2669 CanonicalizeBoundary(value_range->min(), | 2672 CanonicalizeBoundary(value_range->min(), |
| 2670 RangeBoundary::OverflowedMinSmi()); | 2673 RangeBoundary::NegativeInfinity()); |
| 2671 | 2674 |
| 2672 do { | 2675 do { |
| 2673 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2676 if (DependOnSameSymbol(canonical_a, canonical_b)) { |
| 2674 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b | 2677 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b |
| 2675 : canonical_a; | 2678 : canonical_a; |
| 2676 } | 2679 } |
| 2677 } while (CanonicalizeMinBoundary(&canonical_a) || | 2680 } while (CanonicalizeMinBoundary(&canonical_a) || |
| 2678 CanonicalizeMinBoundary(&canonical_b)); | 2681 CanonicalizeMinBoundary(&canonical_b)); |
| 2679 } | 2682 } |
| 2680 | 2683 |
| 2681 if (min.IsUnknown()) { | 2684 if (min.IsUnknown()) { |
| 2682 min = RangeBoundary::Max(Range::ConstantMin(value_range), | 2685 min = RangeBoundary::Max(Range::ConstantMin(value_range), |
| 2683 Range::ConstantMin(constraint())); | 2686 Range::ConstantMin(constraint())); |
| 2684 } | 2687 } |
| 2685 } | 2688 } |
| 2686 | 2689 |
| 2687 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { | 2690 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { |
| 2688 max = constraint()->max(); | 2691 max = constraint()->max(); |
| 2689 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { | 2692 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { |
| 2690 max = value_range->max(); | 2693 max = value_range->max(); |
| 2691 } else if ((value_range != NULL) && | 2694 } else if ((value_range != NULL) && |
| 2692 IsEqual(constraint()->max(), value_range->max())) { | 2695 IsEqual(constraint()->max(), value_range->max())) { |
| 2693 max = constraint()->max(); | 2696 max = constraint()->max(); |
| 2694 } else { | 2697 } else { |
| 2695 if (value_range != NULL) { | 2698 if (value_range != NULL) { |
| 2696 RangeBoundary canonical_b = | 2699 RangeBoundary canonical_b = |
| 2697 CanonicalizeBoundary(value_range->max(), | 2700 CanonicalizeBoundary(value_range->max(), |
| 2698 RangeBoundary::OverflowedMaxSmi()); | 2701 RangeBoundary::PositiveInfinity()); |
| 2699 RangeBoundary canonical_a = | 2702 RangeBoundary canonical_a = |
| 2700 CanonicalizeBoundary(constraint()->max(), | 2703 CanonicalizeBoundary(constraint()->max(), |
| 2701 RangeBoundary::OverflowedMaxSmi()); | 2704 RangeBoundary::PositiveInfinity()); |
| 2702 | 2705 |
| 2703 do { | 2706 do { |
| 2704 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2707 if (DependOnSameSymbol(canonical_a, canonical_b)) { |
| 2705 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a | 2708 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a |
| 2706 : canonical_b; | 2709 : canonical_b; |
| 2707 break; | 2710 break; |
| 2708 } | 2711 } |
| 2709 } while (CanonicalizeMaxBoundary(&canonical_a) || | 2712 } while (CanonicalizeMaxBoundary(&canonical_a) || |
| 2710 CanonicalizeMaxBoundary(&canonical_b)); | 2713 CanonicalizeMaxBoundary(&canonical_b)); |
| 2711 } | 2714 } |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3032 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | 3035 RangeBoundary::FromDefinition(left_defn) : left_range->max(); |
| 3033 | 3036 |
| 3034 RangeBoundary min; | 3037 RangeBoundary min; |
| 3035 RangeBoundary max; | 3038 RangeBoundary max; |
| 3036 switch (op_kind()) { | 3039 switch (op_kind()) { |
| 3037 case Token::kADD: | 3040 case Token::kADD: |
| 3038 if (!SymbolicAdd(left_min, right_range->min(), &min)) { | 3041 if (!SymbolicAdd(left_min, right_range->min(), &min)) { |
| 3039 min = | 3042 min = |
| 3040 RangeBoundary::Add(Range::ConstantMin(left_range), | 3043 RangeBoundary::Add(Range::ConstantMin(left_range), |
| 3041 Range::ConstantMin(right_range), | 3044 Range::ConstantMin(right_range), |
| 3042 RangeBoundary::OverflowedMinSmi()); | 3045 RangeBoundary::NegativeInfinity()); |
| 3043 } | 3046 } |
| 3044 | 3047 |
| 3045 if (!SymbolicAdd(left_max, right_range->max(), &max)) { | 3048 if (!SymbolicAdd(left_max, right_range->max(), &max)) { |
| 3046 max = | 3049 max = |
| 3047 RangeBoundary::Add(Range::ConstantMax(right_range), | 3050 RangeBoundary::Add(Range::ConstantMax(right_range), |
| 3048 Range::ConstantMax(left_range), | 3051 Range::ConstantMax(left_range), |
| 3049 RangeBoundary::OverflowedMaxSmi()); | 3052 RangeBoundary::PositiveInfinity()); |
| 3050 } | 3053 } |
| 3051 break; | 3054 break; |
| 3052 | 3055 |
| 3053 case Token::kSUB: | 3056 case Token::kSUB: |
| 3054 if (!SymbolicSub(left_min, right_range->max(), &min)) { | 3057 if (!SymbolicSub(left_min, right_range->max(), &min)) { |
| 3055 min = | 3058 min = |
| 3056 RangeBoundary::Sub(Range::ConstantMin(left_range), | 3059 RangeBoundary::Sub(Range::ConstantMin(left_range), |
| 3057 Range::ConstantMax(right_range), | 3060 Range::ConstantMax(right_range), |
| 3058 RangeBoundary::OverflowedMinSmi()); | 3061 RangeBoundary::NegativeInfinity()); |
| 3059 } | 3062 } |
| 3060 | 3063 |
| 3061 if (!SymbolicSub(left_max, right_range->min(), &max)) { | 3064 if (!SymbolicSub(left_max, right_range->min(), &max)) { |
| 3062 max = | 3065 max = |
| 3063 RangeBoundary::Sub(Range::ConstantMax(left_range), | 3066 RangeBoundary::Sub(Range::ConstantMax(left_range), |
| 3064 Range::ConstantMin(right_range), | 3067 Range::ConstantMin(right_range), |
| 3065 RangeBoundary::OverflowedMaxSmi()); | 3068 RangeBoundary::PositiveInfinity()); |
| 3066 } | 3069 } |
| 3067 break; | 3070 break; |
| 3068 | 3071 |
| 3069 case Token::kMUL: { | 3072 case Token::kMUL: { |
| 3070 const int64_t left_max = ConstantAbsMax(left_range); | 3073 const int64_t left_max = ConstantAbsMax(left_range); |
| 3071 const int64_t right_max = ConstantAbsMax(right_range); | 3074 const int64_t right_max = ConstantAbsMax(right_range); |
| 3072 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { | 3075 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { |
| 3073 // Product of left and right max values stays in 64 bit range. | 3076 // Product of left and right max values stays in 64 bit range. |
| 3074 const int64_t result_max = left_max * right_max; | 3077 const int64_t result_max = left_max * right_max; |
| 3075 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | 3078 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3114 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | 3117 ASSERT(!min.IsUnknown() && !max.IsUnknown()); |
| 3115 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); | 3118 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); |
| 3116 | 3119 |
| 3117 if (min.IsConstant()) min.Clamp(); | 3120 if (min.IsConstant()) min.Clamp(); |
| 3118 if (max.IsConstant()) max.Clamp(); | 3121 if (max.IsConstant()) max.Clamp(); |
| 3119 | 3122 |
| 3120 range_ = new Range(min, max); | 3123 range_ = new Range(min, max); |
| 3121 } | 3124 } |
| 3122 | 3125 |
| 3123 | 3126 |
| 3127 bool Range::IsPositive() const { |
| 3128 if (min().IsNegativeInfinity()) { |
| 3129 return false; |
| 3130 } |
| 3131 if (min().LowerBound().value() < 0) { |
| 3132 return false; |
| 3133 } |
| 3134 if (max().IsPositiveInfinity()) { |
| 3135 return true; |
| 3136 } |
| 3137 return max().UpperBound().value() >= 0; |
| 3138 } |
| 3139 |
| 3140 |
| 3141 bool Range::IsNegative() const { |
| 3142 if (max().IsPositiveInfinity()) { |
| 3143 return false; |
| 3144 } |
| 3145 if (max().UpperBound().value() >= 0) { |
| 3146 return false; |
| 3147 } |
| 3148 if (min().IsNegativeInfinity()) { |
| 3149 return true; |
| 3150 } |
| 3151 return min().LowerBound().value() < 0; |
| 3152 } |
| 3153 |
| 3154 |
| 3155 bool Range::OnlyLessThanOrEqualTo(intptr_t val) const { |
| 3156 if (max().IsPositiveInfinity()) { |
| 3157 // Cannot be true. |
| 3158 return false; |
| 3159 } |
| 3160 if (max().UpperBound().value() > val) { |
| 3161 // Not true. |
| 3162 return false; |
| 3163 } |
| 3164 if (!min().IsNegativeInfinity()) { |
| 3165 if (min().LowerBound().value() > val) { |
| 3166 // Lower bound is > value. |
| 3167 return false; |
| 3168 } |
| 3169 } |
| 3170 return true; |
| 3171 } |
| 3172 |
| 3173 |
| 3124 // Inclusive. | 3174 // Inclusive. |
| 3125 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { | 3175 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { |
| 3126 if (min().LowerBound().value() < min_int) return false; | 3176 if (min().IsNegativeInfinity() || (min().LowerBound().value() < min_int)) { |
| 3127 if (max().UpperBound().value() > max_int) return false; | 3177 return false; |
| 3178 } |
| 3179 if (max().IsPositiveInfinity() || (max().UpperBound().value() > max_int)) { |
| 3180 return false; |
| 3181 } |
| 3128 return true; | 3182 return true; |
| 3129 } | 3183 } |
| 3130 | 3184 |
| 3131 | 3185 |
| 3132 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { | 3186 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { |
| 3133 const intptr_t this_min = min().LowerBound().value(); | 3187 const intptr_t this_min = min().IsNegativeInfinity() ? |
| 3134 const intptr_t this_max = max().UpperBound().value(); | 3188 kIntptrMin : min().LowerBound().value(); |
| 3189 const intptr_t this_max = max().IsPositiveInfinity() ? |
| 3190 kIntptrMax : max().UpperBound().value(); |
| 3135 if ((this_min <= min_int) && (min_int <= this_max)) return true; | 3191 if ((this_min <= min_int) && (min_int <= this_max)) return true; |
| 3136 if ((this_min <= max_int) && (max_int <= this_max)) return true; | 3192 if ((this_min <= max_int) && (max_int <= this_max)) return true; |
| 3137 if ((min_int < this_min) && (max_int > this_max)) return true; | 3193 if ((min_int < this_min) && (max_int > this_max)) return true; |
| 3138 return false; | 3194 return false; |
| 3139 } | 3195 } |
| 3140 | 3196 |
| 3141 | 3197 |
| 3142 bool Range::IsUnsatisfiable() const { | 3198 bool Range::IsUnsatisfiable() const { |
| 3199 // Infinity case: [+inf, ...] || [..., -inf] |
| 3200 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { |
| 3201 return true; |
| 3202 } |
| 3143 // Constant case: For example [0, -1]. | 3203 // Constant case: For example [0, -1]. |
| 3144 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { | 3204 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { |
| 3145 return true; | 3205 return true; |
| 3146 } | 3206 } |
| 3147 // Symbol case: For example [v+1, v]. | 3207 // Symbol case: For example [v+1, v]. |
| 3148 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { | 3208 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { |
| 3149 return true; | 3209 return true; |
| 3150 } | 3210 } |
| 3151 return false; | 3211 return false; |
| 3152 } | 3212 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3164 if (index_range == NULL) { | 3224 if (index_range == NULL) { |
| 3165 return false; | 3225 return false; |
| 3166 } | 3226 } |
| 3167 | 3227 |
| 3168 // Range of the index is not positive. Check can't be redundant. | 3228 // Range of the index is not positive. Check can't be redundant. |
| 3169 if (Range::ConstantMin(index_range).value() < 0) { | 3229 if (Range::ConstantMin(index_range).value() < 0) { |
| 3170 return false; | 3230 return false; |
| 3171 } | 3231 } |
| 3172 | 3232 |
| 3173 RangeBoundary max = CanonicalizeBoundary(index_range->max(), | 3233 RangeBoundary max = CanonicalizeBoundary(index_range->max(), |
| 3174 RangeBoundary::OverflowedMaxSmi()); | 3234 RangeBoundary::PositiveInfinity()); |
| 3175 | 3235 |
| 3176 if (max.Overflowed()) { | 3236 if (max.Overflowed()) { |
| 3177 return false; | 3237 return false; |
| 3178 } | 3238 } |
| 3179 | 3239 |
| 3240 |
| 3241 RangeBoundary max_upper = max.UpperBound(); |
| 3242 RangeBoundary length_lower = length.LowerBound(); |
| 3243 |
| 3244 if (max_upper.Overflowed() || length_lower.Overflowed()) { |
| 3245 return false; |
| 3246 } |
| 3247 |
| 3180 // Try to compare constant boundaries. | 3248 // Try to compare constant boundaries. |
| 3181 if (max.UpperBound().value() < length.LowerBound().value()) { | 3249 if (max_upper.value() < length_lower.value()) { |
| 3182 return true; | 3250 return true; |
| 3183 } | 3251 } |
| 3184 | 3252 |
| 3185 length = CanonicalizeBoundary(length, RangeBoundary::OverflowedMaxSmi()); | 3253 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); |
| 3186 if (length.Overflowed()) { | 3254 if (length.Overflowed()) { |
| 3187 return false; | 3255 return false; |
| 3188 } | 3256 } |
| 3189 | 3257 |
| 3190 // Try symbolic comparison. | 3258 // Try symbolic comparison. |
| 3191 do { | 3259 do { |
| 3192 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); | 3260 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); |
| 3193 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); | 3261 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); |
| 3194 | 3262 |
| 3195 // Failed to prove that maximum is bounded with array length. | 3263 // Failed to prove that maximum is bounded with array length. |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3469 case Token::kTRUNCDIV: return 0; | 3537 case Token::kTRUNCDIV: return 0; |
| 3470 case Token::kMOD: return 1; | 3538 case Token::kMOD: return 1; |
| 3471 default: UNIMPLEMENTED(); return -1; | 3539 default: UNIMPLEMENTED(); return -1; |
| 3472 } | 3540 } |
| 3473 } | 3541 } |
| 3474 | 3542 |
| 3475 | 3543 |
| 3476 #undef __ | 3544 #undef __ |
| 3477 | 3545 |
| 3478 } // namespace dart | 3546 } // namespace dart |
| OLD | NEW |