Chromium Code Reviews| 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 2447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2458 | 2458 |
| 2459 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { | 2459 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { |
| 2460 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { | 2460 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { |
| 2461 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); | 2461 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); |
| 2462 } | 2462 } |
| 2463 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); | 2463 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); |
| 2464 } | 2464 } |
| 2465 | 2465 |
| 2466 | 2466 |
| 2467 RangeBoundary RangeBoundary::LowerBound() const { | 2467 RangeBoundary RangeBoundary::LowerBound() const { |
| 2468 if (IsNegativeInfinity()) return *this; | 2468 if (IsInfinity()) { |
| 2469 return NegativeInfinity(); | |
| 2470 } | |
| 2469 if (IsConstant()) return *this; | 2471 if (IsConstant()) return *this; |
| 2470 return Add(Range::ConstantMin(symbol()->range()), | 2472 return Add(Range::ConstantMin(symbol()->range()), |
| 2471 RangeBoundary::FromConstant(offset_), | 2473 RangeBoundary::FromConstant(offset_), |
| 2472 NegativeInfinity()); | 2474 NegativeInfinity()); |
| 2473 } | 2475 } |
| 2474 | 2476 |
| 2475 | 2477 |
| 2476 RangeBoundary RangeBoundary::UpperBound() const { | 2478 RangeBoundary RangeBoundary::UpperBound() const { |
| 2477 if (IsPositiveInfinity()) return *this; | 2479 if (IsInfinity()) { |
| 2480 return PositiveInfinity(); | |
| 2481 } | |
| 2478 if (IsConstant()) return *this; | 2482 if (IsConstant()) return *this; |
| 2479 return Add(Range::ConstantMax(symbol()->range()), | 2483 return Add(Range::ConstantMax(symbol()->range()), |
| 2480 RangeBoundary::FromConstant(offset_), | 2484 RangeBoundary::FromConstant(offset_), |
| 2481 PositiveInfinity()); | 2485 PositiveInfinity()); |
| 2482 } | 2486 } |
| 2483 | 2487 |
| 2484 | 2488 |
| 2489 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, | |
| 2490 const RangeBoundary& b, | |
| 2491 const RangeBoundary& overflow) { | |
| 2492 if (a.IsInfinity() || b.IsInfinity()) { | |
| 2493 // In that case that a or b is +/- inf, return the overflow boundary. | |
| 2494 return overflow; | |
| 2495 } | |
| 2496 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 2497 | |
| 2498 intptr_t result = a.ConstantValue() + b.ConstantValue(); | |
| 2499 if (!Smi::IsValid(result)) { | |
| 2500 return overflow; | |
| 2501 } | |
| 2502 return RangeBoundary::FromConstant(result); | |
| 2503 } | |
| 2504 | |
| 2505 | |
| 2506 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, | |
| 2507 const RangeBoundary& b, | |
| 2508 const RangeBoundary& overflow) { | |
| 2509 if (a.IsInfinity() || b.IsInfinity()) { | |
| 2510 // In that case that a or b is +/- inf, return the overflow boundary. | |
| 2511 return overflow; | |
| 2512 } | |
| 2513 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 2514 | |
| 2515 intptr_t result = a.ConstantValue() - b.ConstantValue(); | |
| 2516 if (!Smi::IsValid(result)) { | |
| 2517 return overflow; | |
| 2518 } | |
| 2519 return RangeBoundary::FromConstant(result); | |
| 2520 } | |
| 2521 | |
| 2522 | |
| 2523 bool RangeBoundary::SymbolicAdd(const RangeBoundary& a, | |
| 2524 const RangeBoundary& b, | |
| 2525 RangeBoundary* result) { | |
| 2526 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2527 const intptr_t offset = a.offset() + b.ConstantValue(); | |
| 2528 if (!Smi::IsValid(offset)) return false; | |
| 2529 | |
| 2530 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2531 return true; | |
| 2532 } else if (b.IsSymbol() && a.IsConstant() && !a.Overflowed()) { | |
| 2533 const intptr_t offset = b.offset() + a.ConstantValue(); | |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
return SymbolicAdd(b, a, result); to avoid duplica
Cutch
2014/06/13 22:45:22
Done.
| |
| 2534 if (!Smi::IsValid(offset)) return false; | |
| 2535 | |
| 2536 *result = RangeBoundary::FromDefinition(b.symbol(), offset); | |
| 2537 return true; | |
| 2538 } | |
| 2539 return false; | |
| 2540 } | |
| 2541 | |
| 2542 | |
| 2543 bool RangeBoundary::SymbolicSub(const RangeBoundary& a, | |
| 2544 const RangeBoundary& b, | |
| 2545 RangeBoundary* result) { | |
| 2546 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2547 const intptr_t offset = a.offset() - b.ConstantValue(); | |
| 2548 if (!Smi::IsValid(offset)) return false; | |
| 2549 | |
| 2550 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2551 return true; | |
| 2552 } | |
| 2553 return false; | |
| 2554 } | |
| 2555 | |
| 2556 | |
| 2485 static Definition* UnwrapConstraint(Definition* defn) { | 2557 static Definition* UnwrapConstraint(Definition* defn) { |
| 2486 while (defn->IsConstraint()) { | 2558 while (defn->IsConstraint()) { |
| 2487 defn = defn->AsConstraint()->value()->definition(); | 2559 defn = defn->AsConstraint()->value()->definition(); |
| 2488 } | 2560 } |
| 2489 return defn; | 2561 return defn; |
| 2490 } | 2562 } |
| 2491 | 2563 |
| 2492 | 2564 |
| 2493 static bool AreEqualDefinitions(Definition* a, Definition* b) { | 2565 static bool AreEqualDefinitions(Definition* a, Definition* b) { |
| 2494 a = UnwrapConstraint(a); | 2566 a = UnwrapConstraint(a); |
| 2495 b = UnwrapConstraint(b); | 2567 b = UnwrapConstraint(b); |
| 2496 return (a == b) || | 2568 return (a == b) || |
| 2497 (a->AllowsCSE() && | 2569 (a->AllowsCSE() && |
| 2498 a->Dependencies().IsNone() && | 2570 a->Dependencies().IsNone() && |
| 2499 b->AllowsCSE() && | 2571 b->AllowsCSE() && |
| 2500 b->Dependencies().IsNone() && | 2572 b->Dependencies().IsNone() && |
| 2501 a->Equals(b)); | 2573 a->Equals(b)); |
| 2502 } | 2574 } |
| 2503 | 2575 |
| 2504 | 2576 |
| 2505 // Returns true if two range boundaries refer to the same symbol. | 2577 // Returns true if two range boundaries refer to the same symbol. |
| 2506 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { | 2578 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { |
| 2507 return a.IsSymbol() && b.IsSymbol() && | 2579 return a.IsSymbol() && b.IsSymbol() && |
| 2508 AreEqualDefinitions(a.symbol(), b.symbol()); | 2580 AreEqualDefinitions(a.symbol(), b.symbol()); |
| 2509 } | 2581 } |
| 2510 | 2582 |
| 2511 | 2583 |
| 2512 // Returns true if range has a least specific minimum value. | 2584 bool RangeBoundary::Equals(const RangeBoundary& other) const { |
| 2513 static bool IsMinSmi(Range* range) { | 2585 if (IsConstant() && other.IsConstant()) { |
| 2514 return (range == NULL) || | 2586 return ConstantValue() == other.ConstantValue(); |
| 2515 (range->min().IsConstant() && | 2587 } else if (IsInfinity() && other.IsInfinity()) { |
| 2516 (range->min().value() <= Smi::kMinValue)); | 2588 return kind() == other.kind(); |
| 2517 } | 2589 } else if (IsSymbol() && other.IsSymbol()) { |
| 2518 | 2590 return (offset() == other.offset()) && DependOnSameSymbol(*this, other); |
| 2519 | |
| 2520 // Returns true if range has a least specific maximium value. | |
| 2521 static bool IsMaxSmi(Range* range) { | |
| 2522 return (range == NULL) || | |
| 2523 (range->max().IsConstant() && | |
| 2524 (range->max().value() >= Smi::kMaxValue)); | |
| 2525 } | |
| 2526 | |
| 2527 | |
| 2528 // Returns true if two range boundaries can be proven to be equal. | |
| 2529 static bool IsEqual(const RangeBoundary& a, const RangeBoundary& b) { | |
| 2530 if (a.IsConstant() && b.IsConstant()) { | |
| 2531 return a.value() == b.value(); | |
| 2532 } else if (a.IsSymbol() && b.IsSymbol()) { | |
| 2533 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); | |
| 2534 } else { | |
| 2535 return false; | |
| 2536 } | 2591 } |
| 2592 return false; | |
| 2537 } | 2593 } |
| 2538 | 2594 |
| 2539 | 2595 |
| 2540 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, | 2596 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, |
| 2541 const RangeBoundary& overflow) { | 2597 const RangeBoundary& overflow) { |
| 2542 if (a.IsConstant() || a.IsNegativeInfinity() || a.IsPositiveInfinity()) { | 2598 if (a.IsConstant() || a.IsInfinity()) { |
| 2543 return a; | 2599 return a; |
| 2544 } | 2600 } |
| 2545 | 2601 |
| 2546 intptr_t offset = a.offset(); | 2602 intptr_t offset = a.offset(); |
| 2547 Definition* symbol = a.symbol(); | 2603 Definition* symbol = a.symbol(); |
| 2548 | 2604 |
| 2549 bool changed; | 2605 bool changed; |
| 2550 do { | 2606 do { |
| 2551 changed = false; | 2607 changed = false; |
| 2552 if (symbol->IsConstraint()) { | 2608 if (symbol->IsConstraint()) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2624 | 2680 |
| 2625 *a = CanonicalizeBoundary( | 2681 *a = CanonicalizeBoundary( |
| 2626 RangeBoundary::FromDefinition(range->min().symbol(), offset), | 2682 RangeBoundary::FromDefinition(range->min().symbol(), offset), |
| 2627 RangeBoundary::NegativeInfinity()); | 2683 RangeBoundary::NegativeInfinity()); |
| 2628 | 2684 |
| 2629 return true; | 2685 return true; |
| 2630 } | 2686 } |
| 2631 | 2687 |
| 2632 | 2688 |
| 2633 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { | 2689 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { |
| 2690 // Infinity cases. | |
| 2691 if (a.IsNegativeInfinity() || b.IsNegativeInfinity()) { | |
| 2692 return NegativeInfinity(); | |
| 2693 } | |
| 2694 if (a.IsPositiveInfinity()) { | |
| 2695 return b; | |
| 2696 } | |
| 2697 if (b.IsPositiveInfinity()) { | |
| 2698 return a; | |
| 2699 } | |
| 2700 | |
| 2701 // Equality case. | |
| 2702 if (a.Equals(b)) { | |
| 2703 return a; | |
| 2704 } | |
| 2705 | |
| 2634 if (DependOnSameSymbol(a, b)) { | 2706 if (DependOnSameSymbol(a, b)) { |
| 2635 return (a.offset() <= b.offset()) ? a : b; | 2707 return (a.offset() <= b.offset()) ? a : b; |
| 2636 } | 2708 } |
| 2637 | 2709 |
| 2638 const intptr_t min_a = a.LowerBound().Clamp().value(); | 2710 const intptr_t min_a = a.LowerBound().Clamp().ConstantValue(); |
| 2639 const intptr_t min_b = b.LowerBound().Clamp().value(); | 2711 const intptr_t min_b = b.LowerBound().Clamp().ConstantValue(); |
| 2640 | 2712 |
| 2641 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); | 2713 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); |
| 2642 } | 2714 } |
| 2643 | 2715 |
| 2644 | 2716 |
| 2645 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b) { | 2717 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b) { |
| 2646 if (DependOnSameSymbol(a, b)) { | 2718 // Infinity cases. |
| 2647 return (a.offset() >= b.offset()) ? a : b; | 2719 if (a.IsPositiveInfinity() || b.IsPositiveInfinity()) { |
| 2720 return RangeBoundary::PositiveInfinity(); | |
| 2721 } | |
| 2722 if (a.IsNegativeInfinity()) { | |
| 2723 return b; | |
| 2724 } | |
| 2725 if (b.IsNegativeInfinity()) { | |
| 2726 return a; | |
| 2727 } | |
| 2728 // Equality case. | |
| 2729 if (a.Equals(b)) { | |
| 2730 return a; | |
| 2648 } | 2731 } |
| 2649 | 2732 |
| 2650 const intptr_t max_a = a.UpperBound().Clamp().value(); | 2733 if (DependOnSameSymbol(a, b)) { |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
I would move loop that tries to Canonicalize bound
| |
| 2651 const intptr_t max_b = b.UpperBound().Clamp().value(); | 2734 return (a.offset() <= b.offset()) ? b : a; |
| 2735 } | |
| 2736 | |
| 2737 const intptr_t max_a = a.UpperBound().Clamp().ConstantValue(); | |
| 2738 const intptr_t max_b = b.UpperBound().Clamp().ConstantValue(); | |
| 2652 | 2739 |
| 2653 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); | 2740 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); |
| 2654 } | 2741 } |
| 2655 | 2742 |
| 2656 | 2743 |
| 2744 intptr_t RangeBoundary::ConstantValue() const { | |
| 2745 ASSERT(IsConstant()); | |
| 2746 return value_; | |
| 2747 } | |
| 2748 | |
| 2749 | |
| 2657 void Definition::InferRange() { | 2750 void Definition::InferRange() { |
| 2658 ASSERT(Type()->ToCid() == kSmiCid); // Has meaning only for smis. | 2751 ASSERT(Type()->ToCid() == kSmiCid); // Has meaning only for smis. |
| 2659 if (range_ == NULL) { | 2752 if (range_ == NULL) { |
| 2660 range_ = Range::Unknown(); | 2753 range_ = Range::Unknown(); |
| 2661 } | 2754 } |
| 2662 } | 2755 } |
| 2663 | 2756 |
| 2664 | 2757 |
| 2665 void ConstantInstr::InferRange() { | 2758 void ConstantInstr::InferRange() { |
| 2666 ASSERT(value_.IsSmi()); | 2759 ASSERT(value_.IsSmi()); |
| 2667 if (range_ == NULL) { | 2760 if (range_ == NULL) { |
| 2668 intptr_t value = Smi::Cast(value_).Value(); | 2761 intptr_t value = Smi::Cast(value_).Value(); |
| 2669 range_ = new Range(RangeBoundary::FromConstant(value), | 2762 range_ = new Range(RangeBoundary::FromConstant(value), |
| 2670 RangeBoundary::FromConstant(value)); | 2763 RangeBoundary::FromConstant(value)); |
| 2671 } | 2764 } |
| 2672 } | 2765 } |
| 2673 | 2766 |
| 2674 | 2767 |
| 2675 void ConstraintInstr::InferRange() { | 2768 void ConstraintInstr::InferRange() { |
| 2676 Range* value_range = value()->definition()->range(); | 2769 Range* value_range = value()->definition()->range(); |
| 2677 | 2770 |
| 2678 RangeBoundary min; | 2771 RangeBoundary min; |
| 2679 RangeBoundary max; | 2772 RangeBoundary max; |
| 2680 | 2773 |
| 2681 if (IsMinSmi(value_range) && !IsMinSmi(constraint())) { | 2774 if (Range::IncludesNegativeInfinity(value_range) && |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
I would expect this code to actually use RangeBoun
| |
| 2775 !Range::IncludesNegativeInfinity(constraint())) { | |
| 2682 min = constraint()->min(); | 2776 min = constraint()->min(); |
| 2683 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { | 2777 } else if (Range::IncludesNegativeInfinity(constraint()) && |
| 2778 !Range::IncludesNegativeInfinity(value_range)) { | |
| 2684 min = value_range->min(); | 2779 min = value_range->min(); |
| 2685 } else if ((value_range != NULL) && | 2780 } else if ((value_range != NULL) && |
| 2686 IsEqual(constraint()->min(), value_range->min())) { | 2781 constraint()->min().Equals(value_range->min())) { |
| 2687 min = constraint()->min(); | 2782 min = constraint()->min(); |
| 2688 } else { | 2783 } else { |
| 2689 if (value_range != NULL) { | 2784 if (value_range != NULL) { |
| 2690 RangeBoundary canonical_a = | 2785 RangeBoundary canonical_a = |
| 2691 CanonicalizeBoundary(constraint()->min(), | 2786 CanonicalizeBoundary(constraint()->min(), |
| 2692 RangeBoundary::NegativeInfinity()); | 2787 RangeBoundary::NegativeInfinity()); |
| 2693 RangeBoundary canonical_b = | 2788 RangeBoundary canonical_b = |
| 2694 CanonicalizeBoundary(value_range->min(), | 2789 CanonicalizeBoundary(value_range->min(), |
| 2695 RangeBoundary::NegativeInfinity()); | 2790 RangeBoundary::NegativeInfinity()); |
| 2696 | 2791 |
| 2697 do { | 2792 do { |
| 2698 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2793 if (DependOnSameSymbol(canonical_a, canonical_b)) { |
| 2699 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b | 2794 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b |
| 2700 : canonical_a; | 2795 : canonical_a; |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
I agree this should have break.
| |
| 2701 } | 2796 } |
| 2702 } while (CanonicalizeMinBoundary(&canonical_a) || | 2797 } while (CanonicalizeMinBoundary(&canonical_a) || |
| 2703 CanonicalizeMinBoundary(&canonical_b)); | 2798 CanonicalizeMinBoundary(&canonical_b)); |
| 2704 } | 2799 } |
| 2705 | 2800 |
| 2706 if (min.IsUnknown()) { | 2801 if (min.IsUnknown()) { |
| 2707 min = RangeBoundary::Max(Range::ConstantMin(value_range), | 2802 min = RangeBoundary::Max(Range::ConstantMin(value_range), |
| 2708 Range::ConstantMin(constraint())); | 2803 Range::ConstantMin(constraint())); |
| 2709 } | 2804 } |
| 2710 } | 2805 } |
| 2711 | 2806 |
| 2712 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { | 2807 if (Range::IncludesPositiveInfinity(value_range) && |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
I would expect this to be replaced by RangeBoundar
Cutch
2014/06/13 22:45:22
Done.
| |
| 2808 !Range::IncludesPositiveInfinity(constraint())) { | |
| 2713 max = constraint()->max(); | 2809 max = constraint()->max(); |
| 2714 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { | 2810 } else if (Range::IncludesPositiveInfinity(constraint()) && |
| 2811 !Range::IncludesPositiveInfinity(value_range)) { | |
| 2715 max = value_range->max(); | 2812 max = value_range->max(); |
| 2716 } else if ((value_range != NULL) && | 2813 } else if ((value_range != NULL) && |
| 2717 IsEqual(constraint()->max(), value_range->max())) { | 2814 constraint()->max().Equals(value_range->max())) { |
| 2718 max = constraint()->max(); | 2815 max = constraint()->max(); |
| 2719 } else { | 2816 } else { |
| 2720 if (value_range != NULL) { | 2817 if (value_range != NULL) { |
| 2721 RangeBoundary canonical_b = | 2818 RangeBoundary canonical_b = |
| 2722 CanonicalizeBoundary(value_range->max(), | 2819 CanonicalizeBoundary(value_range->max(), |
| 2723 RangeBoundary::PositiveInfinity()); | 2820 RangeBoundary::PositiveInfinity()); |
| 2724 RangeBoundary canonical_a = | 2821 RangeBoundary canonical_a = |
| 2725 CanonicalizeBoundary(constraint()->max(), | 2822 CanonicalizeBoundary(constraint()->max(), |
| 2726 RangeBoundary::PositiveInfinity()); | 2823 RangeBoundary::PositiveInfinity()); |
| 2727 | 2824 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2964 ASSERT(InputCount() > 1); | 3061 ASSERT(InputCount() > 1); |
| 2965 Definition* first = InputAt(0)->definition(); | 3062 Definition* first = InputAt(0)->definition(); |
| 2966 for (intptr_t i = 1; i < InputCount(); ++i) { | 3063 for (intptr_t i = 1; i < InputCount(); ++i) { |
| 2967 Definition* def = InputAt(i)->definition(); | 3064 Definition* def = InputAt(i)->definition(); |
| 2968 if (def != first) return false; | 3065 if (def != first) return false; |
| 2969 } | 3066 } |
| 2970 return true; | 3067 return true; |
| 2971 } | 3068 } |
| 2972 | 3069 |
| 2973 | 3070 |
| 2974 static bool SymbolicSub(const RangeBoundary& a, | |
| 2975 const RangeBoundary& b, | |
| 2976 RangeBoundary* result) { | |
| 2977 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2978 const intptr_t offset = a.offset() - b.value(); | |
| 2979 if (!Smi::IsValid(offset)) return false; | |
| 2980 | |
| 2981 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2982 return true; | |
| 2983 } | |
| 2984 return false; | |
| 2985 } | |
| 2986 | |
| 2987 | |
| 2988 static bool SymbolicAdd(const RangeBoundary& a, | |
| 2989 const RangeBoundary& b, | |
| 2990 RangeBoundary* result) { | |
| 2991 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2992 const intptr_t offset = a.offset() + b.value(); | |
| 2993 if (!Smi::IsValid(offset)) return false; | |
| 2994 | |
| 2995 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2996 return true; | |
| 2997 } else if (b.IsSymbol() && a.IsConstant() && !a.Overflowed()) { | |
| 2998 const intptr_t offset = b.offset() + a.value(); | |
| 2999 if (!Smi::IsValid(offset)) return false; | |
| 3000 | |
| 3001 *result = RangeBoundary::FromDefinition(b.symbol(), offset); | |
| 3002 return true; | |
| 3003 } | |
| 3004 return false; | |
| 3005 } | |
| 3006 | |
| 3007 | |
| 3008 static bool IsArrayLength(Definition* defn) { | 3071 static bool IsArrayLength(Definition* defn) { |
| 3009 LoadFieldInstr* load = defn->AsLoadField(); | 3072 LoadFieldInstr* load = defn->AsLoadField(); |
| 3010 return (load != NULL) && load->IsImmutableLengthLoad(); | 3073 return (load != NULL) && load->IsImmutableLengthLoad(); |
| 3011 } | 3074 } |
| 3012 | 3075 |
| 3013 | 3076 |
| 3014 static int64_t ConstantAbsMax(const Range* range) { | |
| 3015 if (range == NULL) return Smi::kMaxValue; | |
| 3016 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).value()); | |
| 3017 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).value()); | |
| 3018 return abs_min > abs_max ? abs_min : abs_max; | |
| 3019 } | |
| 3020 | |
| 3021 | |
| 3022 static bool OnlyPositiveOrZero(const Range* a, const Range* b) { | |
| 3023 if ((a == NULL) || (b == NULL)) return false; | |
| 3024 if (Range::ConstantMin(a).value() < 0) return false; | |
| 3025 if (Range::ConstantMin(b).value() < 0) return false; | |
| 3026 return true; | |
| 3027 } | |
| 3028 | |
| 3029 | |
| 3030 static bool OnlyNegativeOrZero(const Range* a, const Range* b) { | |
| 3031 if ((a == NULL) || (b == NULL)) return false; | |
| 3032 if (Range::ConstantMax(a).value() > 0) return false; | |
| 3033 if (Range::ConstantMax(b).value() > 0) return false; | |
| 3034 return true; | |
| 3035 } | |
| 3036 | |
| 3037 | |
| 3038 void BinarySmiOpInstr::InferRange() { | 3077 void BinarySmiOpInstr::InferRange() { |
| 3039 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the | 3078 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the |
| 3040 // right and a non-constant on the left. | 3079 // right and a non-constant on the left. |
| 3041 Definition* left_defn = left()->definition(); | 3080 Definition* left_defn = left()->definition(); |
| 3042 | 3081 |
| 3043 Range* left_range = left_defn->range(); | 3082 Range* left_range = left_defn->range(); |
| 3044 Range* right_range = right()->definition()->range(); | 3083 Range* right_range = right()->definition()->range(); |
| 3045 | 3084 |
| 3046 if ((left_range == NULL) || (right_range == NULL)) { | 3085 if ((left_range == NULL) || (right_range == NULL)) { |
| 3047 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | 3086 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); |
| 3048 return; | 3087 return; |
| 3049 } | 3088 } |
| 3050 | 3089 |
| 3051 RangeBoundary left_min = | 3090 RangeBoundary left_min = |
| 3052 IsArrayLength(left_defn) ? | 3091 IsArrayLength(left_defn) ? |
| 3053 RangeBoundary::FromDefinition(left_defn) : left_range->min(); | 3092 RangeBoundary::FromDefinition(left_defn) : left_range->min(); |
| 3054 | 3093 |
| 3055 RangeBoundary left_max = | 3094 RangeBoundary left_max = |
| 3056 IsArrayLength(left_defn) ? | 3095 IsArrayLength(left_defn) ? |
| 3057 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | 3096 RangeBoundary::FromDefinition(left_defn) : left_range->max(); |
| 3058 | 3097 |
| 3059 RangeBoundary min; | 3098 // Only update overflow state for +, -, and cases where we already have a |
| 3060 RangeBoundary max; | 3099 // range. |
| 3061 switch (op_kind()) { | 3100 bool should_update_overflow = (op_kind() == Token::kADD) || |
| 3062 case Token::kADD: | 3101 (op_kind() == Token::kSUB) || |
| 3063 if (!SymbolicAdd(left_min, right_range->min(), &min)) { | 3102 (range_ != NULL); |
| 3064 min = | |
| 3065 RangeBoundary::Add(Range::ConstantMin(left_range), | |
| 3066 Range::ConstantMin(right_range), | |
| 3067 RangeBoundary::NegativeInfinity()); | |
| 3068 } | |
| 3069 | 3103 |
| 3070 if (!SymbolicAdd(left_max, right_range->max(), &max)) { | 3104 range_ = Range::BinaryOp(op_kind(), |
| 3071 max = | 3105 left_min, |
| 3072 RangeBoundary::Add(Range::ConstantMax(right_range), | 3106 left_max, |
| 3073 Range::ConstantMax(left_range), | 3107 left_range, |
| 3074 RangeBoundary::PositiveInfinity()); | 3108 right_range, |
| 3075 } | 3109 range_); |
| 3076 break; | 3110 if (range_ == NULL) { |
| 3077 | 3111 // No range information. |
| 3078 case Token::kSUB: | 3112 return; |
| 3079 if (!SymbolicSub(left_min, right_range->max(), &min)) { | |
| 3080 min = | |
| 3081 RangeBoundary::Sub(Range::ConstantMin(left_range), | |
| 3082 Range::ConstantMax(right_range), | |
| 3083 RangeBoundary::NegativeInfinity()); | |
| 3084 } | |
| 3085 | |
| 3086 if (!SymbolicSub(left_max, right_range->min(), &max)) { | |
| 3087 max = | |
| 3088 RangeBoundary::Sub(Range::ConstantMax(left_range), | |
| 3089 Range::ConstantMin(right_range), | |
| 3090 RangeBoundary::PositiveInfinity()); | |
| 3091 } | |
| 3092 break; | |
| 3093 | |
| 3094 case Token::kMUL: { | |
| 3095 const int64_t left_max = ConstantAbsMax(left_range); | |
| 3096 const int64_t right_max = ConstantAbsMax(right_range); | |
| 3097 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { | |
| 3098 // Product of left and right max values stays in 64 bit range. | |
| 3099 const int64_t result_max = left_max * right_max; | |
| 3100 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | |
| 3101 const intptr_t r_min = | |
| 3102 OnlyPositiveOrZero(left_range, right_range) ? 0 : -result_max; | |
| 3103 min = RangeBoundary::FromConstant(r_min); | |
| 3104 const intptr_t r_max = | |
| 3105 OnlyNegativeOrZero(left_range, right_range) ? 0 : result_max; | |
| 3106 max = RangeBoundary::FromConstant(r_max); | |
| 3107 break; | |
| 3108 } | |
| 3109 } | |
| 3110 if (range_ == NULL) { | |
| 3111 range_ = Range::Unknown(); | |
| 3112 } | |
| 3113 return; | |
| 3114 } | |
| 3115 case Token::kBIT_AND: | |
| 3116 if (Range::ConstantMin(right_range).value() >= 0) { | |
| 3117 min = RangeBoundary::FromConstant(0); | |
| 3118 max = Range::ConstantMax(right_range); | |
| 3119 break; | |
| 3120 } | |
| 3121 if (Range::ConstantMin(left_range).value() >= 0) { | |
| 3122 min = RangeBoundary::FromConstant(0); | |
| 3123 max = Range::ConstantMax(left_range); | |
| 3124 break; | |
| 3125 } | |
| 3126 | |
| 3127 if (range_ == NULL) { | |
| 3128 range_ = Range::Unknown(); | |
| 3129 } | |
| 3130 return; | |
| 3131 | |
| 3132 default: | |
| 3133 if (range_ == NULL) { | |
| 3134 range_ = Range::Unknown(); | |
| 3135 } | |
| 3136 return; | |
| 3137 } | 3113 } |
| 3138 | 3114 |
| 3139 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | 3115 if (!should_update_overflow) { |
| 3140 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); | 3116 return; |
| 3117 } | |
| 3141 | 3118 |
| 3142 if (min.IsConstant()) min.Clamp(); | 3119 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown()); |
| 3143 if (max.IsConstant()) max.Clamp(); | 3120 const bool overflowed = range_->min().LowerBound().Overflowed() || |
| 3144 | 3121 range_->max().UpperBound().Overflowed(); |
| 3145 range_ = new Range(min, max); | 3122 set_overflow(overflowed); |
| 3146 } | 3123 } |
| 3147 | 3124 |
| 3148 | 3125 |
| 3149 bool Range::IsPositive() const { | 3126 bool Range::IsPositive() const { |
| 3150 if (min().IsNegativeInfinity()) { | 3127 if (min().IsNegativeInfinity()) { |
| 3151 return false; | 3128 return false; |
| 3152 } | 3129 } |
| 3153 if (min().LowerBound().value() < 0) { | 3130 if (min().LowerBound().ConstantValue() < 0) { |
| 3154 return false; | 3131 return false; |
| 3155 } | 3132 } |
| 3156 if (max().IsPositiveInfinity()) { | 3133 if (max().IsPositiveInfinity()) { |
| 3157 return true; | 3134 return true; |
| 3158 } | 3135 } |
| 3159 return max().UpperBound().value() >= 0; | 3136 return max().UpperBound().ConstantValue() >= 0; |
| 3160 } | 3137 } |
| 3161 | 3138 |
| 3162 | 3139 |
| 3163 bool Range::IsNegative() const { | 3140 bool Range::IsNegative() const { |
| 3164 if (max().IsPositiveInfinity()) { | 3141 if (max().IsPositiveInfinity()) { |
| 3165 return false; | 3142 return false; |
| 3166 } | 3143 } |
| 3167 if (max().UpperBound().value() >= 0) { | 3144 if (max().UpperBound().ConstantValue() >= 0) { |
| 3168 return false; | 3145 return false; |
| 3169 } | 3146 } |
| 3170 if (min().IsNegativeInfinity()) { | 3147 if (min().IsNegativeInfinity()) { |
| 3171 return true; | 3148 return true; |
| 3172 } | 3149 } |
| 3173 return min().LowerBound().value() < 0; | 3150 return min().LowerBound().ConstantValue() < 0; |
| 3174 } | 3151 } |
| 3175 | 3152 |
| 3176 | 3153 |
| 3177 bool Range::OnlyLessThanOrEqualTo(intptr_t val) const { | 3154 bool Range::OnlyLessThanOrEqualTo(intptr_t val) const { |
| 3178 if (max().IsPositiveInfinity()) { | 3155 if (max().IsPositiveInfinity()) { |
| 3179 // Cannot be true. | 3156 // Cannot be true. |
| 3180 return false; | 3157 return false; |
| 3181 } | 3158 } |
| 3182 if (max().UpperBound().value() > val) { | 3159 if (max().UpperBound().ConstantValue() > val) { |
| 3183 // Not true. | 3160 // Not true. |
| 3184 return false; | 3161 return false; |
| 3185 } | 3162 } |
| 3186 if (!min().IsNegativeInfinity()) { | 3163 if (!min().IsNegativeInfinity()) { |
| 3187 if (min().LowerBound().value() > val) { | 3164 if (min().LowerBound().ConstantValue() > val) { |
| 3188 // Lower bound is > value. | 3165 // Lower bound is > value. |
| 3189 return false; | 3166 return false; |
| 3190 } | 3167 } |
| 3191 } | 3168 } |
| 3192 return true; | 3169 return true; |
| 3193 } | 3170 } |
| 3194 | 3171 |
| 3195 | 3172 |
| 3173 bool Range::OnlyGreaterThanOrEqualTo(intptr_t val) const { | |
| 3174 if (min().IsNegativeInfinity()) { | |
| 3175 return false; | |
| 3176 } | |
| 3177 if (min().LowerBound().ConstantValue() < val) { | |
| 3178 return false; | |
| 3179 } | |
| 3180 if (!max().IsPositiveInfinity()) { | |
| 3181 if (max().UpperBound().ConstantValue() < val) { | |
|
Vyacheslav Egorov (Google)
2014/06/13 11:50:21
min().LowerBound().ConstantValue() >= val && max()
| |
| 3182 return false; | |
| 3183 } | |
| 3184 } | |
| 3185 return true; | |
| 3186 } | |
| 3187 | |
| 3188 | |
| 3196 // Inclusive. | 3189 // Inclusive. |
| 3197 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { | 3190 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { |
| 3198 RangeBoundary lower_min = min().LowerBound(); | 3191 RangeBoundary lower_min = min().LowerBound(); |
| 3199 if (lower_min.IsNegativeInfinity() || (lower_min.value() < min_int)) { | 3192 if (lower_min.IsNegativeInfinity() || (lower_min.ConstantValue() < min_int)) { |
| 3200 return false; | 3193 return false; |
| 3201 } | 3194 } |
| 3202 RangeBoundary upper_max = max().UpperBound(); | 3195 RangeBoundary upper_max = max().UpperBound(); |
| 3203 if (upper_max.IsPositiveInfinity() || (upper_max.value() > max_int)) { | 3196 if (upper_max.IsPositiveInfinity() || (upper_max.ConstantValue() > max_int)) { |
| 3204 return false; | 3197 return false; |
| 3205 } | 3198 } |
| 3206 return true; | 3199 return true; |
| 3207 } | 3200 } |
| 3208 | 3201 |
| 3209 | 3202 |
| 3210 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { | 3203 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { |
| 3211 const intptr_t this_min = min().IsNegativeInfinity() ? | 3204 RangeBoundary lower = min().LowerBound(); |
| 3212 kIntptrMin : min().LowerBound().value(); | 3205 RangeBoundary upper = max().UpperBound(); |
| 3213 const intptr_t this_max = max().IsPositiveInfinity() ? | 3206 const intptr_t this_min = lower.IsNegativeInfinity() ? |
| 3214 kIntptrMax : max().UpperBound().value(); | 3207 RangeBoundary::kMin : lower.ConstantValue(); |
| 3208 const intptr_t this_max = upper.IsPositiveInfinity() ? | |
| 3209 RangeBoundary::kMax : upper.ConstantValue(); | |
| 3215 if ((this_min <= min_int) && (min_int <= this_max)) return true; | 3210 if ((this_min <= min_int) && (min_int <= this_max)) return true; |
| 3216 if ((this_min <= max_int) && (max_int <= this_max)) return true; | 3211 if ((this_min <= max_int) && (max_int <= this_max)) return true; |
| 3217 if ((min_int < this_min) && (max_int > this_max)) return true; | 3212 if ((min_int < this_min) && (max_int > this_max)) return true; |
| 3218 return false; | 3213 return false; |
| 3219 } | 3214 } |
| 3220 | 3215 |
| 3221 | 3216 |
| 3222 bool Range::IsUnsatisfiable() const { | 3217 bool Range::IsUnsatisfiable() const { |
| 3223 // Infinity case: [+inf, ...] || [..., -inf] | 3218 // Infinity case: [+inf, ...] || [..., -inf] |
| 3224 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { | 3219 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { |
| 3225 return true; | 3220 return true; |
| 3226 } | 3221 } |
| 3227 // Constant case: For example [0, -1]. | 3222 // Constant case: For example [0, -1]. |
| 3228 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { | 3223 if (Range::ConstantMin(this).ConstantValue() > |
| 3224 Range::ConstantMax(this).ConstantValue()) { | |
| 3229 return true; | 3225 return true; |
| 3230 } | 3226 } |
| 3231 // Symbol case: For example [v+1, v]. | 3227 // Symbol case: For example [v+1, v]. |
| 3232 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { | 3228 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { |
| 3233 return true; | 3229 return true; |
| 3234 } | 3230 } |
| 3235 return false; | 3231 return false; |
| 3236 } | 3232 } |
| 3237 | 3233 |
| 3238 | 3234 |
| 3235 // Returns true if range is at or below the minimum smi value. | |
| 3236 bool Range::IncludesNegativeInfinity(const Range* range) { | |
| 3237 return (range == NULL) || range->min().IsNegativeInfinity(); | |
| 3238 } | |
| 3239 | |
| 3240 | |
| 3241 // Returns true if range is at or above the maximum smi value. | |
| 3242 bool Range::IncludesPositiveInfinity(const Range* range) { | |
| 3243 return (range == NULL) || range->max().IsPositiveInfinity(); | |
| 3244 } | |
| 3245 | |
| 3246 | |
| 3247 // Both the a and b ranges are >= 0. | |
| 3248 bool Range::OnlyPositiveOrZero(const Range& a, const Range& b) { | |
| 3249 return a.OnlyGreaterThanOrEqualTo(0) && b.OnlyGreaterThanOrEqualTo(0); | |
| 3250 } | |
| 3251 | |
| 3252 | |
| 3253 // Both the a and b ranges are <= 0. | |
| 3254 bool Range::OnlyNegativeOrZero(const Range& a, const Range& b) { | |
| 3255 return a.OnlyLessThanOrEqualTo(0) && b.OnlyLessThanOrEqualTo(0); | |
| 3256 } | |
| 3257 | |
| 3258 | |
| 3259 // Return the maximum absolute value included in range. | |
| 3260 int64_t Range::ConstantAbsMax(const Range* range) { | |
| 3261 if (range == NULL) { | |
| 3262 return RangeBoundary::kMax; | |
| 3263 } | |
| 3264 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); | |
| 3265 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); | |
| 3266 return Utils::Maximum(abs_min, abs_max); | |
| 3267 } | |
| 3268 | |
| 3269 | |
| 3270 Range* Range::BinaryOp(const Token::Kind op, | |
| 3271 const RangeBoundary& left_min, | |
| 3272 const RangeBoundary& left_max, | |
| 3273 const Range* left_range, | |
| 3274 const Range* right_range, | |
| 3275 const Range* original_range) { | |
| 3276 ASSERT(left_range != NULL); | |
| 3277 ASSERT(right_range != NULL); | |
| 3278 RangeBoundary min; | |
| 3279 RangeBoundary max; | |
| 3280 switch (op) { | |
| 3281 case Token::kADD: | |
| 3282 if (!RangeBoundary::SymbolicAdd(left_min, right_range->min(), &min)) { | |
| 3283 min = RangeBoundary::Add(left_range->min().LowerBound(), | |
| 3284 right_range->min().LowerBound(), | |
| 3285 RangeBoundary::NegativeInfinity()); | |
| 3286 } | |
| 3287 if (!RangeBoundary::SymbolicAdd(left_max, right_range->max(), &max)) { | |
| 3288 max = RangeBoundary::Add(right_range->max().UpperBound(), | |
| 3289 left_range->max().UpperBound(), | |
| 3290 RangeBoundary::PositiveInfinity()); | |
| 3291 } | |
| 3292 break; | |
| 3293 case Token::kSUB: | |
| 3294 if (!RangeBoundary::SymbolicSub(left_min, right_range->max(), &min)) { | |
| 3295 min = RangeBoundary::Sub(left_range->min().LowerBound(), | |
| 3296 right_range->max().UpperBound(), | |
| 3297 RangeBoundary::NegativeInfinity()); | |
| 3298 } | |
| 3299 if (!RangeBoundary::SymbolicSub(left_max, right_range->min(), &max)) { | |
| 3300 max = RangeBoundary::Sub(left_range->max().UpperBound(), | |
| 3301 right_range->min().LowerBound(), | |
| 3302 RangeBoundary::PositiveInfinity()); | |
| 3303 } | |
| 3304 break; | |
| 3305 case Token::kMUL: { | |
| 3306 const int64_t left_max = ConstantAbsMax(left_range); | |
| 3307 const int64_t right_max = ConstantAbsMax(right_range); | |
| 3308 if ((left_max < 0x7FFFFFFF) && (right_max < 0x7FFFFFFF)) { | |
| 3309 // Product of left and right max values stays in 64 bit range. | |
| 3310 const int64_t result_max = left_max * right_max; | |
| 3311 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | |
| 3312 const intptr_t r_min = | |
| 3313 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -result_max; | |
| 3314 min = RangeBoundary::FromConstant(r_min); | |
| 3315 const intptr_t r_max = | |
| 3316 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : result_max; | |
| 3317 max = RangeBoundary::FromConstant(r_max); | |
| 3318 break; | |
| 3319 } | |
| 3320 } | |
| 3321 if (original_range == NULL) { | |
| 3322 return Range::Unknown(); | |
| 3323 } | |
| 3324 break; | |
| 3325 } | |
| 3326 case Token::kBIT_AND: | |
| 3327 if (Range::ConstantMin(right_range).ConstantValue() >= 0) { | |
| 3328 min = RangeBoundary::FromConstant(0); | |
| 3329 max = Range::ConstantMax(right_range); | |
| 3330 break; | |
| 3331 } | |
| 3332 if (Range::ConstantMin(left_range).ConstantValue() >= 0) { | |
| 3333 min = RangeBoundary::FromConstant(0); | |
| 3334 max = Range::ConstantMax(left_range); | |
| 3335 break; | |
| 3336 } | |
| 3337 if (original_range == NULL) { | |
| 3338 return Range::Unknown(); | |
| 3339 } | |
| 3340 break; | |
| 3341 default: | |
| 3342 if (original_range == NULL) { | |
| 3343 return Range::Unknown(); | |
| 3344 } | |
| 3345 return const_cast<Range*>(original_range); | |
| 3346 } | |
| 3347 | |
| 3348 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | |
| 3349 | |
| 3350 return new Range(min, max); | |
| 3351 } | |
| 3352 | |
| 3353 | |
| 3239 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { | 3354 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { |
| 3240 return LoadFieldInstr::IsFixedLengthArrayCid(cid); | 3355 return LoadFieldInstr::IsFixedLengthArrayCid(cid); |
| 3241 } | 3356 } |
| 3242 | 3357 |
| 3243 | 3358 |
| 3244 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { | 3359 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { |
| 3245 Range* index_range = index()->definition()->range(); | 3360 Range* index_range = index()->definition()->range(); |
| 3246 | 3361 |
| 3247 // Range of the index is unknown can't decide if the check is redundant. | 3362 // Range of the index is unknown can't decide if the check is redundant. |
| 3248 if (index_range == NULL) { | 3363 if (index_range == NULL) { |
| 3249 return false; | 3364 return false; |
| 3250 } | 3365 } |
| 3251 | 3366 |
| 3252 // Range of the index is not positive. Check can't be redundant. | 3367 // Range of the index is not positive. Check can't be redundant. |
| 3253 if (Range::ConstantMin(index_range).value() < 0) { | 3368 if (Range::ConstantMin(index_range).ConstantValue() < 0) { |
| 3254 return false; | 3369 return false; |
| 3255 } | 3370 } |
| 3256 | 3371 |
| 3257 RangeBoundary max = CanonicalizeBoundary(index_range->max(), | 3372 RangeBoundary max = CanonicalizeBoundary(index_range->max(), |
| 3258 RangeBoundary::PositiveInfinity()); | 3373 RangeBoundary::PositiveInfinity()); |
| 3259 | 3374 |
| 3260 if (max.Overflowed()) { | 3375 if (max.Overflowed()) { |
| 3261 return false; | 3376 return false; |
| 3262 } | 3377 } |
| 3263 | 3378 |
| 3264 | 3379 |
| 3265 RangeBoundary max_upper = max.UpperBound(); | 3380 RangeBoundary max_upper = max.UpperBound(); |
| 3266 RangeBoundary length_lower = length.LowerBound(); | 3381 RangeBoundary length_lower = length.LowerBound(); |
| 3267 | 3382 |
| 3268 if (max_upper.Overflowed() || length_lower.Overflowed()) { | 3383 if (max_upper.Overflowed() || length_lower.Overflowed()) { |
| 3269 return false; | 3384 return false; |
| 3270 } | 3385 } |
| 3271 | 3386 |
| 3272 // Try to compare constant boundaries. | 3387 // Try to compare constant boundaries. |
| 3273 if (max_upper.value() < length_lower.value()) { | 3388 if (max_upper.ConstantValue() < length_lower.ConstantValue()) { |
| 3274 return true; | 3389 return true; |
| 3275 } | 3390 } |
| 3276 | 3391 |
| 3277 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); | 3392 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); |
| 3278 if (length.Overflowed()) { | 3393 if (length.Overflowed()) { |
| 3279 return false; | 3394 return false; |
| 3280 } | 3395 } |
| 3281 | 3396 |
| 3282 // Try symbolic comparison. | 3397 // Try symbolic comparison. |
| 3283 do { | 3398 do { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3561 case Token::kTRUNCDIV: return 0; | 3676 case Token::kTRUNCDIV: return 0; |
| 3562 case Token::kMOD: return 1; | 3677 case Token::kMOD: return 1; |
| 3563 default: UNIMPLEMENTED(); return -1; | 3678 default: UNIMPLEMENTED(); return -1; |
| 3564 } | 3679 } |
| 3565 } | 3680 } |
| 3566 | 3681 |
| 3567 | 3682 |
| 3568 #undef __ | 3683 #undef __ |
| 3569 | 3684 |
| 3570 } // namespace dart | 3685 } // namespace dart |
| OLD | NEW |