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

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

Issue 321593004: Refactor RangeBoundary +/- infinity to be distinct RangeBoundary kinds. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months 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/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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698