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 2431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2442 intptr_t use_index = instr->env()->Length(); // Start index after inner. | 2442 intptr_t use_index = instr->env()->Length(); // Start index after inner. |
| 2443 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { | 2443 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { |
| 2444 Value* value = it.CurrentValue(); | 2444 Value* value = it.CurrentValue(); |
| 2445 value->set_instruction(instr); | 2445 value->set_instruction(instr); |
| 2446 value->set_use_index(use_index++); | 2446 value->set_use_index(use_index++); |
| 2447 value->definition()->AddEnvUse(value); | 2447 value->definition()->AddEnvUse(value); |
| 2448 } | 2448 } |
| 2449 } | 2449 } |
| 2450 | 2450 |
| 2451 | 2451 |
| 2452 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { | 2452 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) { |
| 2453 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { | 2453 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { |
| 2454 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); | 2454 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); |
| 2455 } | 2455 } |
| 2456 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); | 2456 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); |
| 2457 } | 2457 } |
| 2458 | 2458 |
| 2459 | 2459 |
| 2460 RangeBoundary RangeBoundary::LowerBound() const { | 2460 RangeBoundary RangeBoundary::LowerBound() const { |
| 2461 if (IsNegativeInfinity()) return *this; | 2461 if (IsInfinity()) { |
| 2462 return NegativeInfinity(); | |
| 2463 } | |
| 2462 if (IsConstant()) return *this; | 2464 if (IsConstant()) return *this; |
| 2463 return Add(Range::ConstantMin(symbol()->range()), | 2465 return Add(Range::ConstantMin(symbol()->range()), |
| 2464 RangeBoundary::FromConstant(offset_), | 2466 RangeBoundary::FromConstant(offset_), |
| 2465 NegativeInfinity()); | 2467 NegativeInfinity()); |
| 2466 } | 2468 } |
| 2467 | 2469 |
| 2468 | 2470 |
| 2469 RangeBoundary RangeBoundary::UpperBound() const { | 2471 RangeBoundary RangeBoundary::UpperBound() const { |
| 2470 if (IsPositiveInfinity()) return *this; | 2472 if (IsInfinity()) { |
| 2473 return PositiveInfinity(); | |
| 2474 } | |
| 2471 if (IsConstant()) return *this; | 2475 if (IsConstant()) return *this; |
| 2472 return Add(Range::ConstantMax(symbol()->range()), | 2476 return Add(Range::ConstantMax(symbol()->range()), |
| 2473 RangeBoundary::FromConstant(offset_), | 2477 RangeBoundary::FromConstant(offset_), |
| 2474 PositiveInfinity()); | 2478 PositiveInfinity()); |
| 2475 } | 2479 } |
| 2476 | 2480 |
| 2477 | 2481 |
| 2482 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, | |
| 2483 const RangeBoundary& b, | |
| 2484 const RangeBoundary& overflow) { | |
| 2485 if (a.IsInfinity() || b.IsInfinity()) { | |
| 2486 // In that case that a or b is +/- inf, return the overflow boundary. | |
| 2487 return overflow; | |
|
Florian Schneider
2014/06/18 10:14:10
Can this case ever occur?
Cutch
2014/06/18 22:16:52
Not now that I clamp.
| |
| 2488 } | |
| 2489 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 2490 | |
| 2491 int64_t result = a.ConstantValue() + b.ConstantValue(); | |
| 2492 | |
| 2493 if (Utils::DidAddOverflow(a.ConstantValue(), b.ConstantValue(), result)) { | |
| 2494 return overflow; | |
| 2495 } | |
| 2496 | |
| 2497 return RangeBoundary::FromConstant(result); | |
| 2498 } | |
| 2499 | |
| 2500 | |
| 2501 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, | |
| 2502 const RangeBoundary& b, | |
| 2503 const RangeBoundary& overflow) { | |
| 2504 if (a.IsInfinity() || b.IsInfinity()) { | |
| 2505 // In that case that a or b is +/- inf, return the overflow boundary. | |
| 2506 return overflow; | |
|
Florian Schneider
2014/06/18 10:14:10
Is this case ever hit?
Cutch
2014/06/18 22:16:52
Not now that I clamp.
| |
| 2507 } | |
| 2508 ASSERT(a.IsConstant() && b.IsConstant()); | |
| 2509 | |
| 2510 int64_t result = a.ConstantValue() - b.ConstantValue(); | |
| 2511 | |
| 2512 if (Utils::DidSubOverflow(a.ConstantValue(), b.ConstantValue(), result)) { | |
| 2513 return overflow; | |
| 2514 } | |
| 2515 return RangeBoundary::FromConstant(result); | |
| 2516 } | |
| 2517 | |
| 2518 | |
| 2519 bool RangeBoundary::SymbolicAdd(const RangeBoundary& a, | |
| 2520 const RangeBoundary& b, | |
| 2521 RangeBoundary* result) { | |
| 2522 if (a.IsSymbol() && b.IsConstant()) { | |
| 2523 const int64_t offset = a.offset() + b.ConstantValue(); | |
| 2524 if (Utils::DidAddOverflow(a.offset(), b.ConstantValue(), offset)) { | |
| 2525 return false; | |
| 2526 } | |
| 2527 | |
| 2528 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2529 return true; | |
| 2530 } else if (b.IsSymbol() && a.IsConstant()) { | |
| 2531 return SymbolicAdd(b, a, result); | |
| 2532 } | |
| 2533 return false; | |
| 2534 } | |
| 2535 | |
| 2536 | |
| 2537 bool RangeBoundary::SymbolicSub(const RangeBoundary& a, | |
| 2538 const RangeBoundary& b, | |
| 2539 RangeBoundary* result) { | |
| 2540 if (a.IsSymbol() && b.IsConstant()) { | |
| 2541 const int64_t offset = a.offset() - b.ConstantValue(); | |
| 2542 if (Utils::DidSubOverflow(a.offset(), b.ConstantValue(), offset)) { | |
| 2543 return false; | |
| 2544 } | |
| 2545 | |
| 2546 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2547 return true; | |
| 2548 } | |
| 2549 return false; | |
| 2550 } | |
| 2551 | |
| 2552 | |
| 2478 static Definition* UnwrapConstraint(Definition* defn) { | 2553 static Definition* UnwrapConstraint(Definition* defn) { |
| 2479 while (defn->IsConstraint()) { | 2554 while (defn->IsConstraint()) { |
| 2480 defn = defn->AsConstraint()->value()->definition(); | 2555 defn = defn->AsConstraint()->value()->definition(); |
| 2481 } | 2556 } |
| 2482 return defn; | 2557 return defn; |
| 2483 } | 2558 } |
| 2484 | 2559 |
| 2485 | 2560 |
| 2486 static bool AreEqualDefinitions(Definition* a, Definition* b) { | 2561 static bool AreEqualDefinitions(Definition* a, Definition* b) { |
| 2487 a = UnwrapConstraint(a); | 2562 a = UnwrapConstraint(a); |
| 2488 b = UnwrapConstraint(b); | 2563 b = UnwrapConstraint(b); |
| 2489 return (a == b) || | 2564 return (a == b) || |
| 2490 (a->AllowsCSE() && | 2565 (a->AllowsCSE() && |
| 2491 a->Dependencies().IsNone() && | 2566 a->Dependencies().IsNone() && |
| 2492 b->AllowsCSE() && | 2567 b->AllowsCSE() && |
| 2493 b->Dependencies().IsNone() && | 2568 b->Dependencies().IsNone() && |
| 2494 a->Equals(b)); | 2569 a->Equals(b)); |
| 2495 } | 2570 } |
| 2496 | 2571 |
| 2497 | 2572 |
| 2498 // Returns true if two range boundaries refer to the same symbol. | 2573 // Returns true if two range boundaries refer to the same symbol. |
| 2499 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { | 2574 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { |
| 2500 return a.IsSymbol() && b.IsSymbol() && | 2575 return a.IsSymbol() && b.IsSymbol() && |
| 2501 AreEqualDefinitions(a.symbol(), b.symbol()); | 2576 AreEqualDefinitions(a.symbol(), b.symbol()); |
| 2502 } | 2577 } |
| 2503 | 2578 |
| 2504 | 2579 |
| 2505 // Returns true if range has a least specific minimum value. | 2580 bool RangeBoundary::Equals(const RangeBoundary& other) const { |
| 2506 static bool IsMinSmi(Range* range) { | 2581 if (IsConstant() && other.IsConstant()) { |
| 2507 return (range == NULL) || | 2582 return ConstantValue() == other.ConstantValue(); |
| 2508 (range->min().IsConstant() && | 2583 } else if (IsInfinity() && other.IsInfinity()) { |
| 2509 (range->min().value() <= Smi::kMinValue)); | 2584 return kind() == other.kind(); |
| 2585 } else if (IsSymbol() && other.IsSymbol()) { | |
| 2586 return (offset() == other.offset()) && DependOnSameSymbol(*this, other); | |
| 2587 } else if (IsUnknown() && other.IsUnknown()) { | |
| 2588 return true; | |
| 2589 } | |
| 2590 return false; | |
| 2510 } | 2591 } |
| 2511 | 2592 |
| 2512 | 2593 |
| 2513 // Returns true if range has a least specific maximium value. | 2594 RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary, |
| 2514 static bool IsMaxSmi(Range* range) { | 2595 int64_t shift_count, |
| 2515 return (range == NULL) || | 2596 const RangeBoundary& overflow) { |
| 2516 (range->max().IsConstant() && | 2597 ASSERT(value_boundary.IsConstant()); |
| 2517 (range->max().value() >= Smi::kMaxValue)); | 2598 ASSERT(shift_count >= 0); |
| 2518 } | 2599 int64_t limit = 64 - shift_count; |
| 2600 int64_t value = static_cast<int64_t>(value_boundary.ConstantValue()); | |
| 2519 | 2601 |
| 2602 if ((value == 0) || | |
| 2603 (shift_count == 0) || | |
| 2604 ((limit > 0) && (Utils::IsInt(limit, value)))) { | |
| 2605 // Result stays in 64 bit range. | |
| 2606 int64_t result = value << shift_count; | |
| 2607 return Smi::IsValid64(result) ? RangeBoundary(result) : overflow; | |
| 2608 } | |
| 2520 | 2609 |
| 2521 // Returns true if two range boundaries can be proven to be equal. | 2610 return overflow; |
| 2522 static bool IsEqual(const RangeBoundary& a, const RangeBoundary& b) { | |
| 2523 if (a.IsConstant() && b.IsConstant()) { | |
| 2524 return a.value() == b.value(); | |
| 2525 } else if (a.IsSymbol() && b.IsSymbol()) { | |
| 2526 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b); | |
| 2527 } else { | |
| 2528 return false; | |
| 2529 } | |
| 2530 } | 2611 } |
| 2531 | 2612 |
| 2532 | 2613 |
| 2533 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, | 2614 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, |
| 2534 const RangeBoundary& overflow) { | 2615 const RangeBoundary& overflow) { |
| 2535 if (a.IsConstant() || a.IsNegativeInfinity() || a.IsPositiveInfinity()) { | 2616 if (a.IsConstant() || a.IsInfinity()) { |
| 2536 return a; | 2617 return a; |
| 2537 } | 2618 } |
| 2538 | 2619 |
| 2539 intptr_t offset = a.offset(); | 2620 int64_t offset = a.offset(); |
| 2540 Definition* symbol = a.symbol(); | 2621 Definition* symbol = a.symbol(); |
| 2541 | 2622 |
| 2542 bool changed; | 2623 bool changed; |
| 2543 do { | 2624 do { |
| 2544 changed = false; | 2625 changed = false; |
| 2545 if (symbol->IsConstraint()) { | 2626 if (symbol->IsConstraint()) { |
| 2546 symbol = symbol->AsConstraint()->value()->definition(); | 2627 symbol = symbol->AsConstraint()->value()->definition(); |
| 2547 changed = true; | 2628 changed = true; |
| 2548 } else if (symbol->IsBinarySmiOp()) { | 2629 } else if (symbol->IsBinarySmiOp()) { |
| 2549 BinarySmiOpInstr* op = symbol->AsBinarySmiOp(); | 2630 BinarySmiOpInstr* op = symbol->AsBinarySmiOp(); |
| 2550 Definition* left = op->left()->definition(); | 2631 Definition* left = op->left()->definition(); |
| 2551 Definition* right = op->right()->definition(); | 2632 Definition* right = op->right()->definition(); |
| 2552 switch (op->op_kind()) { | 2633 switch (op->op_kind()) { |
| 2553 case Token::kADD: | 2634 case Token::kADD: |
| 2554 if (right->IsConstant()) { | 2635 if (right->IsConstant()) { |
| 2555 offset += Smi::Cast(right->AsConstant()->value()).Value(); | 2636 int64_t rhs = Smi::Cast(right->AsConstant()->value()).Value(); |
| 2637 int64_t old_offset = offset; | |
| 2638 offset += rhs; | |
| 2639 if (Utils::DidAddOverflow(old_offset, rhs, offset)) { | |
| 2640 return overflow; | |
| 2641 } | |
| 2556 symbol = left; | 2642 symbol = left; |
| 2557 changed = true; | 2643 changed = true; |
| 2558 } else if (left->IsConstant()) { | 2644 } else if (left->IsConstant()) { |
| 2559 offset += Smi::Cast(left->AsConstant()->value()).Value(); | 2645 int64_t rhs = Smi::Cast(left->AsConstant()->value()).Value(); |
| 2646 int64_t old_offset = offset; | |
| 2647 offset += rhs; | |
| 2648 if (Utils::DidAddOverflow(old_offset, rhs, offset)) { | |
| 2649 return overflow; | |
| 2650 } | |
| 2560 symbol = right; | 2651 symbol = right; |
| 2561 changed = true; | 2652 changed = true; |
| 2562 } | 2653 } |
| 2563 break; | 2654 break; |
| 2564 | 2655 |
| 2565 case Token::kSUB: | 2656 case Token::kSUB: |
| 2566 if (right->IsConstant()) { | 2657 if (right->IsConstant()) { |
| 2567 offset -= Smi::Cast(right->AsConstant()->value()).Value(); | 2658 int64_t rhs = Smi::Cast(right->AsConstant()->value()).Value(); |
| 2659 int64_t old_offset = offset; | |
| 2660 offset -= rhs; | |
| 2661 if (Utils::DidSubOverflow(old_offset, rhs, offset)) { | |
| 2662 return overflow; | |
| 2663 } | |
| 2568 symbol = left; | 2664 symbol = left; |
| 2569 changed = true; | 2665 changed = true; |
| 2570 } | 2666 } |
| 2571 break; | 2667 break; |
| 2572 | 2668 |
| 2573 default: | 2669 default: |
| 2574 break; | 2670 break; |
| 2575 } | 2671 } |
| 2576 } | 2672 } |
| 2577 | |
| 2578 if (!Smi::IsValid(offset)) return overflow; | |
| 2579 } while (changed); | 2673 } while (changed); |
| 2580 | 2674 |
| 2581 return RangeBoundary::FromDefinition(symbol, offset); | 2675 return RangeBoundary::FromDefinition(symbol, offset); |
| 2582 } | 2676 } |
| 2583 | 2677 |
| 2584 | 2678 |
| 2585 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { | 2679 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { |
| 2586 if (!a->IsSymbol()) return false; | 2680 if (!a->IsSymbol()) return false; |
| 2587 | 2681 |
| 2588 Range* range = a->symbol()->range(); | 2682 Range* range = a->symbol()->range(); |
| 2589 if ((range == NULL) || !range->max().IsSymbol()) return false; | 2683 if ((range == NULL) || !range->max().IsSymbol()) return false; |
| 2590 | 2684 |
| 2591 const intptr_t offset = range->max().offset() + a->offset(); | 2685 const int64_t offset = range->max().offset() + a->offset(); |
| 2592 | 2686 |
| 2593 if (!Smi::IsValid(offset)) { | 2687 if (Utils::DidAddOverflow(range->max().offset(), a->offset(), offset)) { |
| 2594 *a = RangeBoundary::PositiveInfinity(); | 2688 *a = RangeBoundary::PositiveInfinity(); |
| 2595 return true; | 2689 return true; |
| 2596 } | 2690 } |
| 2597 | 2691 |
| 2598 *a = CanonicalizeBoundary( | 2692 *a = CanonicalizeBoundary( |
| 2599 RangeBoundary::FromDefinition(range->max().symbol(), offset), | 2693 RangeBoundary::FromDefinition(range->max().symbol(), offset), |
| 2600 RangeBoundary::PositiveInfinity()); | 2694 RangeBoundary::PositiveInfinity()); |
| 2601 | 2695 |
| 2602 return true; | 2696 return true; |
| 2603 } | 2697 } |
| 2604 | 2698 |
| 2605 | 2699 |
| 2606 static bool CanonicalizeMinBoundary(RangeBoundary* a) { | 2700 static bool CanonicalizeMinBoundary(RangeBoundary* a) { |
| 2607 if (!a->IsSymbol()) return false; | 2701 if (!a->IsSymbol()) return false; |
| 2608 | 2702 |
| 2609 Range* range = a->symbol()->range(); | 2703 Range* range = a->symbol()->range(); |
| 2610 if ((range == NULL) || !range->min().IsSymbol()) return false; | 2704 if ((range == NULL) || !range->min().IsSymbol()) return false; |
| 2611 | 2705 |
| 2612 const intptr_t offset = range->min().offset() + a->offset(); | 2706 const int64_t offset = range->min().offset() + a->offset(); |
| 2613 if (!Smi::IsValid(offset)) { | 2707 |
| 2708 if (Utils::DidAddOverflow(range->min().offset(), a->offset(), offset)) { | |
| 2614 *a = RangeBoundary::NegativeInfinity(); | 2709 *a = RangeBoundary::NegativeInfinity(); |
| 2615 return true; | 2710 return true; |
| 2616 } | 2711 } |
| 2617 | 2712 |
| 2618 *a = CanonicalizeBoundary( | 2713 *a = CanonicalizeBoundary( |
| 2619 RangeBoundary::FromDefinition(range->min().symbol(), offset), | 2714 RangeBoundary::FromDefinition(range->min().symbol(), offset), |
| 2620 RangeBoundary::NegativeInfinity()); | 2715 RangeBoundary::NegativeInfinity()); |
| 2621 | 2716 |
| 2622 return true; | 2717 return true; |
| 2623 } | 2718 } |
| 2624 | 2719 |
| 2625 | 2720 |
| 2626 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { | 2721 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b, |
| 2722 RangeSize size) { | |
| 2723 ASSERT(!(a.IsNegativeInfinity() || b.IsNegativeInfinity())); | |
| 2724 ASSERT(!a.IsUnknown() || !b.IsUnknown()); | |
| 2725 if (a.IsUnknown() && !b.IsUnknown()) { | |
| 2726 return b; | |
| 2727 } | |
| 2728 if (!a.IsUnknown() && b.IsUnknown()) { | |
| 2729 return a; | |
| 2730 } | |
| 2731 if (size == kRangeBoundarySmi) { | |
| 2732 if (a.IsSmiMaximumOrAbove() && !b.IsSmiMaximumOrAbove()) { | |
| 2733 return b; | |
| 2734 } | |
| 2735 if (!a.IsSmiMaximumOrAbove() && b.IsSmiMaximumOrAbove()) { | |
| 2736 return a; | |
| 2737 } | |
| 2738 } else { | |
| 2739 ASSERT(size == kRangeBoundaryInt64); | |
| 2740 if (a.IsMaximumOrAbove() && !b.IsMaximumOrAbove()) { | |
| 2741 return b; | |
| 2742 } | |
| 2743 if (!a.IsMaximumOrAbove() && b.IsMaximumOrAbove()) { | |
| 2744 return a; | |
| 2745 } | |
| 2746 } | |
| 2747 | |
| 2748 if (a.Equals(b)) { | |
| 2749 return b; | |
| 2750 } | |
| 2751 | |
| 2752 { | |
| 2753 RangeBoundary canonical_a = | |
| 2754 CanonicalizeBoundary(a, RangeBoundary::PositiveInfinity()); | |
| 2755 RangeBoundary canonical_b = | |
| 2756 CanonicalizeBoundary(b, RangeBoundary::PositiveInfinity()); | |
| 2757 do { | |
| 2758 if (DependOnSameSymbol(canonical_a, canonical_b)) { | |
| 2759 a = canonical_a; | |
| 2760 b = canonical_b; | |
| 2761 break; | |
| 2762 } | |
| 2763 } while (CanonicalizeMaxBoundary(&canonical_a) || | |
| 2764 CanonicalizeMaxBoundary(&canonical_b)); | |
| 2765 } | |
| 2766 | |
| 2627 if (DependOnSameSymbol(a, b)) { | 2767 if (DependOnSameSymbol(a, b)) { |
| 2628 return (a.offset() <= b.offset()) ? a : b; | 2768 return (a.offset() <= b.offset()) ? a : b; |
| 2629 } | 2769 } |
| 2630 | 2770 |
| 2631 const intptr_t min_a = a.LowerBound().Clamp().value(); | 2771 const int64_t min_a = a.UpperBound().Clamp(size).ConstantValue(); |
| 2632 const intptr_t min_b = b.LowerBound().Clamp().value(); | 2772 const int64_t min_b = b.UpperBound().Clamp(size).ConstantValue(); |
| 2633 | 2773 |
| 2634 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); | 2774 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); |
| 2635 } | 2775 } |
| 2636 | 2776 |
| 2637 | 2777 |
| 2638 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b) { | 2778 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b, |
| 2639 if (DependOnSameSymbol(a, b)) { | 2779 RangeSize size) { |
| 2640 return (a.offset() >= b.offset()) ? a : b; | 2780 ASSERT(!(a.IsPositiveInfinity() || b.IsPositiveInfinity())); |
| 2781 ASSERT(!a.IsUnknown() || !b.IsUnknown()); | |
| 2782 if (a.IsUnknown() && !b.IsUnknown()) { | |
| 2783 return b; | |
| 2784 } | |
| 2785 if (!a.IsUnknown() && b.IsUnknown()) { | |
| 2786 return a; | |
| 2787 } | |
| 2788 if (size == kRangeBoundarySmi) { | |
| 2789 if (a.IsSmiMinimumOrBelow() && !b.IsSmiMinimumOrBelow()) { | |
| 2790 return b; | |
| 2791 } | |
| 2792 if (!a.IsSmiMinimumOrBelow() && b.IsSmiMinimumOrBelow()) { | |
| 2793 return a; | |
| 2794 } | |
| 2795 } else { | |
| 2796 ASSERT(size == kRangeBoundaryInt64); | |
| 2797 if (a.IsMinimumOrBelow() && !b.IsMinimumOrBelow()) { | |
| 2798 return b; | |
| 2799 } | |
| 2800 if (!a.IsMinimumOrBelow() && b.IsMinimumOrBelow()) { | |
| 2801 return a; | |
| 2802 } | |
| 2803 } | |
| 2804 if (a.Equals(b)) { | |
| 2805 return b; | |
| 2641 } | 2806 } |
| 2642 | 2807 |
| 2643 const intptr_t max_a = a.UpperBound().Clamp().value(); | 2808 { |
| 2644 const intptr_t max_b = b.UpperBound().Clamp().value(); | 2809 RangeBoundary canonical_a = |
| 2810 CanonicalizeBoundary(a, RangeBoundary::NegativeInfinity()); | |
| 2811 RangeBoundary canonical_b = | |
| 2812 CanonicalizeBoundary(b, RangeBoundary::NegativeInfinity()); | |
| 2813 | |
| 2814 do { | |
| 2815 if (DependOnSameSymbol(canonical_a, canonical_b)) { | |
| 2816 a = canonical_a; | |
| 2817 b = canonical_b; | |
| 2818 break; | |
| 2819 } | |
| 2820 } while (CanonicalizeMinBoundary(&canonical_a) || | |
| 2821 CanonicalizeMinBoundary(&canonical_b)); | |
| 2822 } | |
| 2823 | |
| 2824 if (DependOnSameSymbol(a, b)) { | |
| 2825 return (a.offset() <= b.offset()) ? b : a; | |
| 2826 } | |
| 2827 | |
| 2828 const int64_t max_a = a.LowerBound().Clamp(size).ConstantValue(); | |
| 2829 const int64_t max_b = b.LowerBound().Clamp(size).ConstantValue(); | |
| 2645 | 2830 |
| 2646 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); | 2831 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); |
| 2647 } | 2832 } |
| 2648 | 2833 |
| 2649 | 2834 |
| 2835 int64_t RangeBoundary::ConstantValue() const { | |
| 2836 ASSERT(IsConstant()); | |
| 2837 return value_; | |
| 2838 } | |
| 2839 | |
| 2840 | |
| 2650 void Definition::InferRange() { | 2841 void Definition::InferRange() { |
| 2651 ASSERT(Type()->ToCid() == kSmiCid); // Has meaning only for smis. | 2842 if (Type()->ToCid() == kSmiCid) { |
| 2652 if (range_ == NULL) { | 2843 if (range_ == NULL) { |
| 2653 range_ = Range::Unknown(); | 2844 range_ = Range::UnknownSmi(); |
| 2845 } | |
| 2846 } else if (IsMintDefinition()) { | |
| 2847 if (range_ == NULL) { | |
| 2848 range_ = Range::Unknown(); | |
| 2849 } | |
| 2850 } else { | |
| 2851 // Only Smi and Mint supported. | |
| 2852 UNREACHABLE(); | |
| 2654 } | 2853 } |
| 2655 } | 2854 } |
| 2656 | 2855 |
| 2657 | 2856 |
| 2658 void ConstantInstr::InferRange() { | 2857 void ConstantInstr::InferRange() { |
| 2659 ASSERT(value_.IsSmi()); | 2858 if (value_.IsSmi()) { |
| 2660 if (range_ == NULL) { | 2859 if (range_ == NULL) { |
| 2661 intptr_t value = Smi::Cast(value_).Value(); | 2860 int64_t value = Smi::Cast(value_).Value(); |
| 2662 range_ = new Range(RangeBoundary::FromConstant(value), | 2861 range_ = new Range(RangeBoundary::FromConstant(value), |
| 2663 RangeBoundary::FromConstant(value)); | 2862 RangeBoundary::FromConstant(value)); |
| 2863 } | |
| 2864 } else if (value_.IsMint()) { | |
| 2865 if (range_ == NULL) { | |
| 2866 int64_t value = Mint::Cast(value_).value(); | |
| 2867 range_ = new Range(RangeBoundary::FromConstant(value), | |
| 2868 RangeBoundary::FromConstant(value)); | |
| 2869 } | |
| 2870 } else { | |
| 2871 // Only Smi and Mint supported. | |
| 2872 UNREACHABLE(); | |
| 2664 } | 2873 } |
| 2665 } | 2874 } |
| 2666 | 2875 |
| 2876 | |
| 2877 void UnboxIntegerInstr::InferRange() { | |
| 2878 if (range_ == NULL) { | |
| 2879 Definition* unboxed = value()->definition(); | |
| 2880 if (unboxed == NULL) { | |
| 2881 range_ = Range::Unknown(); | |
| 2882 return; | |
| 2883 } | |
| 2884 Range* range = unboxed->range(); | |
| 2885 if (range == NULL) { | |
| 2886 range_ = Range::Unknown(); | |
| 2887 return; | |
| 2888 } | |
| 2889 range_ = new Range(range->min(), range->max()); | |
| 2890 } | |
| 2891 } | |
| 2892 | |
| 2667 | 2893 |
| 2668 void ConstraintInstr::InferRange() { | 2894 void ConstraintInstr::InferRange() { |
| 2669 Range* value_range = value()->definition()->range(); | 2895 Range* value_range = value()->definition()->range(); |
| 2670 | 2896 |
| 2671 RangeBoundary min; | 2897 RangeBoundary min; |
| 2672 RangeBoundary max; | 2898 RangeBoundary max; |
| 2673 | 2899 |
| 2674 if (IsMinSmi(value_range) && !IsMinSmi(constraint())) { | 2900 { |
| 2675 min = constraint()->min(); | 2901 RangeBoundary value_min = (value_range == NULL) ? |
| 2676 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { | 2902 RangeBoundary() : value_range->min(); |
| 2677 min = value_range->min(); | 2903 RangeBoundary constraint_min = constraint()->min(); |
| 2678 } else if ((value_range != NULL) && | 2904 min = RangeBoundary::Max(value_min, constraint_min, |
| 2679 IsEqual(constraint()->min(), value_range->min())) { | 2905 RangeBoundary::kRangeBoundarySmi); |
| 2680 min = constraint()->min(); | |
| 2681 } else { | |
| 2682 if (value_range != NULL) { | |
| 2683 RangeBoundary canonical_a = | |
| 2684 CanonicalizeBoundary(constraint()->min(), | |
| 2685 RangeBoundary::NegativeInfinity()); | |
| 2686 RangeBoundary canonical_b = | |
| 2687 CanonicalizeBoundary(value_range->min(), | |
| 2688 RangeBoundary::NegativeInfinity()); | |
| 2689 | |
| 2690 do { | |
| 2691 if (DependOnSameSymbol(canonical_a, canonical_b)) { | |
| 2692 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b | |
| 2693 : canonical_a; | |
| 2694 } | |
| 2695 } while (CanonicalizeMinBoundary(&canonical_a) || | |
| 2696 CanonicalizeMinBoundary(&canonical_b)); | |
| 2697 } | |
| 2698 | |
| 2699 if (min.IsUnknown()) { | |
| 2700 min = RangeBoundary::Max(Range::ConstantMin(value_range), | |
| 2701 Range::ConstantMin(constraint())); | |
| 2702 } | |
| 2703 } | 2906 } |
| 2704 | 2907 |
| 2705 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { | 2908 ASSERT(!min.IsUnknown()); |
| 2706 max = constraint()->max(); | |
| 2707 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) { | |
| 2708 max = value_range->max(); | |
| 2709 } else if ((value_range != NULL) && | |
| 2710 IsEqual(constraint()->max(), value_range->max())) { | |
| 2711 max = constraint()->max(); | |
| 2712 } else { | |
| 2713 if (value_range != NULL) { | |
| 2714 RangeBoundary canonical_b = | |
| 2715 CanonicalizeBoundary(value_range->max(), | |
| 2716 RangeBoundary::PositiveInfinity()); | |
| 2717 RangeBoundary canonical_a = | |
| 2718 CanonicalizeBoundary(constraint()->max(), | |
| 2719 RangeBoundary::PositiveInfinity()); | |
| 2720 | 2909 |
| 2721 do { | 2910 { |
| 2722 if (DependOnSameSymbol(canonical_a, canonical_b)) { | 2911 RangeBoundary value_max = (value_range == NULL) ? |
| 2723 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a | 2912 RangeBoundary() : value_range->max(); |
| 2724 : canonical_b; | 2913 RangeBoundary constraint_max = constraint()->max(); |
| 2725 break; | 2914 max = RangeBoundary::Min(value_max, constraint_max, |
| 2726 } | 2915 RangeBoundary::kRangeBoundarySmi); |
| 2727 } while (CanonicalizeMaxBoundary(&canonical_a) || | 2916 } |
| 2728 CanonicalizeMaxBoundary(&canonical_b)); | |
| 2729 } | |
| 2730 | 2917 |
| 2731 if (max.IsUnknown()) { | 2918 ASSERT(!max.IsUnknown()); |
| 2732 max = RangeBoundary::Min(Range::ConstantMax(value_range), | |
| 2733 Range::ConstantMax(constraint())); | |
| 2734 } | |
| 2735 } | |
| 2736 | 2919 |
| 2737 range_ = new Range(min, max); | 2920 range_ = new Range(min, max); |
| 2738 | 2921 |
| 2739 // Mark branches that generate unsatisfiable constraints as constant. | 2922 // Mark branches that generate unsatisfiable constraints as constant. |
| 2740 if (target() != NULL && range_->IsUnsatisfiable()) { | 2923 if (target() != NULL && range_->IsUnsatisfiable()) { |
| 2741 BranchInstr* branch = | 2924 BranchInstr* branch = |
| 2742 target()->PredecessorAt(0)->last_instruction()->AsBranch(); | 2925 target()->PredecessorAt(0)->last_instruction()->AsBranch(); |
| 2743 if (target() == branch->true_successor()) { | 2926 if (target() == branch->true_successor()) { |
| 2744 // True unreachable. | 2927 // True unreachable. |
| 2745 if (FLAG_trace_constant_propagation) { | 2928 if (FLAG_trace_constant_propagation) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2798 RangeBoundary::FromConstant(255)); | 2981 RangeBoundary::FromConstant(255)); |
| 2799 break; | 2982 break; |
| 2800 case kTypedDataInt16ArrayCid: | 2983 case kTypedDataInt16ArrayCid: |
| 2801 range_ = new Range(RangeBoundary::FromConstant(-32768), | 2984 range_ = new Range(RangeBoundary::FromConstant(-32768), |
| 2802 RangeBoundary::FromConstant(32767)); | 2985 RangeBoundary::FromConstant(32767)); |
| 2803 break; | 2986 break; |
| 2804 case kTypedDataUint16ArrayCid: | 2987 case kTypedDataUint16ArrayCid: |
| 2805 range_ = new Range(RangeBoundary::FromConstant(0), | 2988 range_ = new Range(RangeBoundary::FromConstant(0), |
| 2806 RangeBoundary::FromConstant(65535)); | 2989 RangeBoundary::FromConstant(65535)); |
| 2807 break; | 2990 break; |
| 2991 case kTypedDataInt32ArrayCid: | |
| 2992 range_ = new Range(RangeBoundary::FromConstant(kMinInt32), | |
| 2993 RangeBoundary::FromConstant(kMaxInt32)); | |
| 2994 break; | |
| 2995 case kTypedDataUint32ArrayCid: | |
| 2996 range_ = new Range(RangeBoundary::FromConstant(0), | |
| 2997 RangeBoundary::FromConstant(kMaxUint32)); | |
| 2998 break; | |
| 2808 case kOneByteStringCid: | 2999 case kOneByteStringCid: |
| 2809 range_ = new Range(RangeBoundary::FromConstant(0), | 3000 range_ = new Range(RangeBoundary::FromConstant(0), |
| 2810 RangeBoundary::FromConstant(0xFF)); | 3001 RangeBoundary::FromConstant(0xFF)); |
| 2811 break; | 3002 break; |
| 2812 case kTwoByteStringCid: | 3003 case kTwoByteStringCid: |
| 2813 range_ = new Range(RangeBoundary::FromConstant(0), | 3004 range_ = new Range(RangeBoundary::FromConstant(0), |
| 2814 RangeBoundary::FromConstant(0xFFFF)); | 3005 RangeBoundary::FromConstant(0xFFFF)); |
| 2815 break; | 3006 break; |
| 2816 default: | 3007 default: |
| 2817 Definition::InferRange(); | 3008 Definition::InferRange(); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2919 } | 3110 } |
| 2920 | 3111 |
| 2921 | 3112 |
| 2922 void PhiInstr::InferRange() { | 3113 void PhiInstr::InferRange() { |
| 2923 RangeBoundary new_min; | 3114 RangeBoundary new_min; |
| 2924 RangeBoundary new_max; | 3115 RangeBoundary new_max; |
| 2925 | 3116 |
| 2926 for (intptr_t i = 0; i < InputCount(); i++) { | 3117 for (intptr_t i = 0; i < InputCount(); i++) { |
| 2927 Range* input_range = InputAt(i)->definition()->range(); | 3118 Range* input_range = InputAt(i)->definition()->range(); |
| 2928 if (input_range == NULL) { | 3119 if (input_range == NULL) { |
| 2929 range_ = Range::Unknown(); | 3120 range_ = Range::UnknownSmi(); |
| 2930 return; | 3121 return; |
| 2931 } | 3122 } |
| 2932 | 3123 |
| 2933 if (new_min.IsUnknown()) { | 3124 if (new_min.IsUnknown()) { |
| 2934 new_min = Range::ConstantMin(input_range); | 3125 new_min = Range::ConstantMin(input_range); |
| 2935 } else { | 3126 } else { |
| 2936 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range)); | 3127 new_min = RangeBoundary::Min(new_min, |
| 3128 Range::ConstantMinSmi(input_range), | |
| 3129 RangeBoundary::kRangeBoundarySmi); | |
| 2937 } | 3130 } |
| 2938 | 3131 |
| 2939 if (new_max.IsUnknown()) { | 3132 if (new_max.IsUnknown()) { |
| 2940 new_max = Range::ConstantMax(input_range); | 3133 new_max = Range::ConstantMax(input_range); |
| 2941 } else { | 3134 } else { |
| 2942 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range)); | 3135 new_max = RangeBoundary::Max(new_max, |
| 3136 Range::ConstantMaxSmi(input_range), | |
| 3137 RangeBoundary::kRangeBoundarySmi); | |
| 2943 } | 3138 } |
| 2944 } | 3139 } |
| 2945 | 3140 |
| 2946 ASSERT(new_min.IsUnknown() == new_max.IsUnknown()); | 3141 ASSERT(new_min.IsUnknown() == new_max.IsUnknown()); |
| 2947 if (new_min.IsUnknown()) { | 3142 if (new_min.IsUnknown()) { |
| 2948 range_ = Range::Unknown(); | 3143 range_ = Range::UnknownSmi(); |
| 2949 return; | 3144 return; |
| 2950 } | 3145 } |
| 2951 | 3146 |
| 2952 range_ = new Range(new_min, new_max); | 3147 range_ = new Range(new_min, new_max); |
| 2953 } | 3148 } |
| 2954 | 3149 |
| 2955 | 3150 |
| 2956 bool PhiInstr::IsRedundant() const { | 3151 bool PhiInstr::IsRedundant() const { |
| 2957 ASSERT(InputCount() > 1); | 3152 ASSERT(InputCount() > 1); |
| 2958 Definition* first = InputAt(0)->definition(); | 3153 Definition* first = InputAt(0)->definition(); |
| 2959 for (intptr_t i = 1; i < InputCount(); ++i) { | 3154 for (intptr_t i = 1; i < InputCount(); ++i) { |
| 2960 Definition* def = InputAt(i)->definition(); | 3155 Definition* def = InputAt(i)->definition(); |
| 2961 if (def != first) return false; | 3156 if (def != first) return false; |
| 2962 } | 3157 } |
| 2963 return true; | 3158 return true; |
| 2964 } | 3159 } |
| 2965 | 3160 |
| 2966 | 3161 |
| 2967 static bool SymbolicSub(const RangeBoundary& a, | |
| 2968 const RangeBoundary& b, | |
| 2969 RangeBoundary* result) { | |
| 2970 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2971 const intptr_t offset = a.offset() - b.value(); | |
| 2972 if (!Smi::IsValid(offset)) return false; | |
| 2973 | |
| 2974 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2975 return true; | |
| 2976 } | |
| 2977 return false; | |
| 2978 } | |
| 2979 | |
| 2980 | |
| 2981 static bool SymbolicAdd(const RangeBoundary& a, | |
| 2982 const RangeBoundary& b, | |
| 2983 RangeBoundary* result) { | |
| 2984 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) { | |
| 2985 const intptr_t offset = a.offset() + b.value(); | |
| 2986 if (!Smi::IsValid(offset)) return false; | |
| 2987 | |
| 2988 *result = RangeBoundary::FromDefinition(a.symbol(), offset); | |
| 2989 return true; | |
| 2990 } else if (b.IsSymbol() && a.IsConstant() && !a.Overflowed()) { | |
| 2991 const intptr_t offset = b.offset() + a.value(); | |
| 2992 if (!Smi::IsValid(offset)) return false; | |
| 2993 | |
| 2994 *result = RangeBoundary::FromDefinition(b.symbol(), offset); | |
| 2995 return true; | |
| 2996 } | |
| 2997 return false; | |
| 2998 } | |
| 2999 | |
| 3000 | |
| 3001 static bool IsArrayLength(Definition* defn) { | 3162 static bool IsArrayLength(Definition* defn) { |
| 3163 if (defn == NULL) { | |
| 3164 return false; | |
| 3165 } | |
| 3002 LoadFieldInstr* load = defn->AsLoadField(); | 3166 LoadFieldInstr* load = defn->AsLoadField(); |
| 3003 return (load != NULL) && load->IsImmutableLengthLoad(); | 3167 return (load != NULL) && load->IsImmutableLengthLoad(); |
| 3004 } | 3168 } |
| 3005 | 3169 |
| 3006 | 3170 |
| 3007 static int64_t ConstantAbsMax(const Range* range) { | |
| 3008 if (range == NULL) return Smi::kMaxValue; | |
| 3009 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).value()); | |
| 3010 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).value()); | |
| 3011 return abs_min > abs_max ? abs_min : abs_max; | |
| 3012 } | |
| 3013 | |
| 3014 | |
| 3015 static bool OnlyPositiveOrZero(const Range* a, const Range* b) { | |
| 3016 if ((a == NULL) || (b == NULL)) return false; | |
| 3017 if (Range::ConstantMin(a).value() < 0) return false; | |
| 3018 if (Range::ConstantMin(b).value() < 0) return false; | |
| 3019 return true; | |
| 3020 } | |
| 3021 | |
| 3022 | |
| 3023 static bool OnlyNegativeOrZero(const Range* a, const Range* b) { | |
| 3024 if ((a == NULL) || (b == NULL)) return false; | |
| 3025 if (Range::ConstantMax(a).value() > 0) return false; | |
| 3026 if (Range::ConstantMax(b).value() > 0) return false; | |
| 3027 return true; | |
| 3028 } | |
| 3029 | |
| 3030 | |
| 3031 void BinarySmiOpInstr::InferRange() { | 3171 void BinarySmiOpInstr::InferRange() { |
| 3032 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the | 3172 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the |
| 3033 // right and a non-constant on the left. | 3173 // right and a non-constant on the left. |
| 3034 Definition* left_defn = left()->definition(); | 3174 Definition* left_defn = left()->definition(); |
| 3035 | 3175 |
| 3036 Range* left_range = left_defn->range(); | 3176 Range* left_range = left_defn->range(); |
| 3037 Range* right_range = right()->definition()->range(); | 3177 Range* right_range = right()->definition()->range(); |
| 3038 | 3178 |
| 3039 if ((left_range == NULL) || (right_range == NULL)) { | 3179 if ((left_range == NULL) || (right_range == NULL)) { |
| 3040 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | 3180 range_ = Range::UnknownSmi(); |
| 3041 return; | 3181 return; |
| 3042 } | 3182 } |
| 3043 | 3183 |
| 3044 RangeBoundary left_min = | 3184 Range* possible_range = Range::BinaryOp(op_kind(), |
| 3045 IsArrayLength(left_defn) ? | 3185 left_range, |
| 3046 RangeBoundary::FromDefinition(left_defn) : left_range->min(); | 3186 right_range, |
| 3187 left_defn); | |
| 3047 | 3188 |
| 3048 RangeBoundary left_max = | 3189 if ((range_ == NULL) && (possible_range == NULL)) { |
| 3049 IsArrayLength(left_defn) ? | 3190 // Initialize. |
| 3050 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | 3191 range_ = Range::UnknownSmi(); |
| 3051 | 3192 return; |
| 3052 RangeBoundary min; | |
| 3053 RangeBoundary max; | |
| 3054 switch (op_kind()) { | |
| 3055 case Token::kADD: | |
| 3056 if (!SymbolicAdd(left_min, right_range->min(), &min)) { | |
| 3057 min = | |
| 3058 RangeBoundary::Add(Range::ConstantMin(left_range), | |
| 3059 Range::ConstantMin(right_range), | |
| 3060 RangeBoundary::NegativeInfinity()); | |
| 3061 } | |
| 3062 | |
| 3063 if (!SymbolicAdd(left_max, right_range->max(), &max)) { | |
| 3064 max = | |
| 3065 RangeBoundary::Add(Range::ConstantMax(right_range), | |
| 3066 Range::ConstantMax(left_range), | |
| 3067 RangeBoundary::PositiveInfinity()); | |
| 3068 } | |
| 3069 break; | |
| 3070 | |
| 3071 case Token::kSUB: | |
| 3072 if (!SymbolicSub(left_min, right_range->max(), &min)) { | |
| 3073 min = | |
| 3074 RangeBoundary::Sub(Range::ConstantMin(left_range), | |
| 3075 Range::ConstantMax(right_range), | |
| 3076 RangeBoundary::NegativeInfinity()); | |
| 3077 } | |
| 3078 | |
| 3079 if (!SymbolicSub(left_max, right_range->min(), &max)) { | |
| 3080 max = | |
| 3081 RangeBoundary::Sub(Range::ConstantMax(left_range), | |
| 3082 Range::ConstantMin(right_range), | |
| 3083 RangeBoundary::PositiveInfinity()); | |
| 3084 } | |
| 3085 break; | |
| 3086 | |
| 3087 case Token::kMUL: { | |
| 3088 const int64_t left_max = ConstantAbsMax(left_range); | |
| 3089 const int64_t right_max = ConstantAbsMax(right_range); | |
| 3090 ASSERT(left_max <= -kSmiMin); | |
| 3091 ASSERT(right_max <= -kSmiMin); | |
| 3092 if ((left_max == 0) || (right_max <= kMaxInt64 / left_max)) { | |
| 3093 // Product of left and right max values stays in 64 bit range. | |
| 3094 const int64_t result_max = left_max * right_max; | |
| 3095 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | |
| 3096 const intptr_t r_min = | |
| 3097 OnlyPositiveOrZero(left_range, right_range) ? 0 : -result_max; | |
| 3098 min = RangeBoundary::FromConstant(r_min); | |
| 3099 const intptr_t r_max = | |
| 3100 OnlyNegativeOrZero(left_range, right_range) ? 0 : result_max; | |
| 3101 max = RangeBoundary::FromConstant(r_max); | |
| 3102 break; | |
| 3103 } | |
| 3104 } | |
| 3105 if (range_ == NULL) { | |
| 3106 range_ = Range::Unknown(); | |
| 3107 } | |
| 3108 return; | |
| 3109 } | |
| 3110 case Token::kSHL: { | |
| 3111 Range::Shl(left_range, right_range, &min, &max); | |
| 3112 break; | |
| 3113 } | |
| 3114 case Token::kBIT_AND: | |
| 3115 if (Range::ConstantMin(right_range).value() >= 0) { | |
| 3116 min = RangeBoundary::FromConstant(0); | |
| 3117 max = Range::ConstantMax(right_range); | |
| 3118 break; | |
| 3119 } | |
| 3120 if (Range::ConstantMin(left_range).value() >= 0) { | |
| 3121 min = RangeBoundary::FromConstant(0); | |
| 3122 max = Range::ConstantMax(left_range); | |
| 3123 break; | |
| 3124 } | |
| 3125 | |
| 3126 if (range_ == NULL) { | |
| 3127 range_ = Range::Unknown(); | |
| 3128 } | |
| 3129 return; | |
| 3130 | |
| 3131 default: | |
| 3132 if (range_ == NULL) { | |
| 3133 range_ = Range::Unknown(); | |
| 3134 } | |
| 3135 return; | |
| 3136 } | 3193 } |
| 3137 | 3194 |
| 3138 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | 3195 if (possible_range == NULL) { |
| 3139 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); | 3196 // Nothing new. |
| 3197 return; | |
| 3198 } | |
| 3140 | 3199 |
| 3141 if (min.IsConstant()) min.Clamp(); | 3200 range_ = possible_range; |
| 3142 if (max.IsConstant()) max.Clamp(); | |
| 3143 | 3201 |
| 3144 range_ = new Range(min, max); | 3202 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown()); |
| 3203 // Calculate overflowed status before clamping. | |
| 3204 const bool overflowed = range_->min().LowerBound().OverflowedSmi() || | |
| 3205 range_->max().UpperBound().OverflowedSmi(); | |
| 3206 | |
| 3207 // Clamp value to be within smi range. | |
| 3208 range_->Clamp(RangeBoundary::kRangeBoundarySmi); | |
| 3209 | |
| 3210 set_overflow(overflowed); | |
| 3145 } | 3211 } |
| 3146 | 3212 |
| 3147 | 3213 |
| 3214 void BinaryMintOpInstr::InferRange() { | |
| 3215 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on | |
| 3216 // the right and a non-constant on the left. | |
| 3217 Definition* left_defn = left()->definition(); | |
| 3218 | |
| 3219 Range* left_range = left_defn->range(); | |
| 3220 Range* right_range = right()->definition()->range(); | |
| 3221 | |
| 3222 if ((left_range == NULL) || (right_range == NULL)) { | |
| 3223 range_ = Range::Unknown(); | |
| 3224 return; | |
| 3225 } | |
| 3226 | |
| 3227 Range* possible_range = Range::BinaryOp(op_kind(), | |
| 3228 left_range, | |
| 3229 right_range, | |
| 3230 left_defn); | |
| 3231 | |
| 3232 if ((range_ == NULL) && (possible_range == NULL)) { | |
| 3233 // Initialize. | |
| 3234 range_ = Range::Unknown(); | |
| 3235 return; | |
| 3236 } | |
| 3237 | |
| 3238 if (possible_range == NULL) { | |
| 3239 // Nothing new. | |
| 3240 return; | |
| 3241 } | |
| 3242 | |
| 3243 range_ = possible_range; | |
| 3244 | |
| 3245 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown()); | |
| 3246 | |
| 3247 // Clamp value to be within mint range. | |
| 3248 range_->Clamp(RangeBoundary::kRangeBoundaryInt64); | |
| 3249 } | |
| 3250 | |
| 3251 | |
| 3148 bool Range::IsPositive() const { | 3252 bool Range::IsPositive() const { |
| 3149 if (min().IsNegativeInfinity()) { | 3253 if (min().IsNegativeInfinity()) { |
| 3150 return false; | 3254 return false; |
| 3151 } | 3255 } |
| 3152 if (min().LowerBound().value() < 0) { | 3256 if (min().LowerBound().ConstantValue() < 0) { |
| 3153 return false; | 3257 return false; |
| 3154 } | 3258 } |
| 3155 if (max().IsPositiveInfinity()) { | 3259 if (max().IsPositiveInfinity()) { |
| 3156 return true; | 3260 return true; |
| 3157 } | 3261 } |
| 3158 return max().UpperBound().value() >= 0; | 3262 return max().UpperBound().ConstantValue() >= 0; |
| 3159 } | 3263 } |
| 3160 | 3264 |
| 3161 | 3265 |
| 3162 bool Range::IsNegative() const { | 3266 bool Range::OnlyLessThanOrEqualTo(int64_t val) 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()) { | 3267 if (max().IsPositiveInfinity()) { |
| 3178 // Cannot be true. | 3268 // Cannot be true. |
| 3179 return false; | 3269 return false; |
| 3180 } | 3270 } |
| 3181 if (max().UpperBound().value() > val) { | 3271 if (max().UpperBound().ConstantValue() > val) { |
| 3182 // Not true. | 3272 // Not true. |
| 3183 return false; | 3273 return false; |
| 3184 } | 3274 } |
| 3185 if (!min().IsNegativeInfinity()) { | 3275 return true; |
| 3186 if (min().LowerBound().value() > val) { | 3276 } |
| 3187 // Lower bound is > value. | 3277 |
| 3188 return false; | 3278 |
| 3189 } | 3279 bool Range::OnlyGreaterThanOrEqualTo(int64_t val) const { |
| 3280 if (min().IsNegativeInfinity()) { | |
| 3281 return false; | |
| 3282 } | |
| 3283 if (min().LowerBound().ConstantValue() < val) { | |
| 3284 return false; | |
| 3190 } | 3285 } |
| 3191 return true; | 3286 return true; |
| 3192 } | 3287 } |
| 3193 | 3288 |
| 3194 | 3289 |
| 3195 // Inclusive. | 3290 // Inclusive. |
| 3196 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { | 3291 bool Range::IsWithin(int64_t min_int, int64_t max_int) const { |
| 3197 RangeBoundary lower_min = min().LowerBound(); | 3292 RangeBoundary lower_min = min().LowerBound(); |
| 3198 if (lower_min.IsNegativeInfinity() || (lower_min.value() < min_int)) { | 3293 if (lower_min.IsNegativeInfinity() || (lower_min.ConstantValue() < min_int)) { |
| 3199 return false; | 3294 return false; |
| 3200 } | 3295 } |
| 3201 RangeBoundary upper_max = max().UpperBound(); | 3296 RangeBoundary upper_max = max().UpperBound(); |
| 3202 if (upper_max.IsPositiveInfinity() || (upper_max.value() > max_int)) { | 3297 if (upper_max.IsPositiveInfinity() || (upper_max.ConstantValue() > max_int)) { |
| 3203 return false; | 3298 return false; |
| 3204 } | 3299 } |
| 3205 return true; | 3300 return true; |
| 3206 } | 3301 } |
| 3207 | 3302 |
| 3208 | 3303 |
| 3209 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { | 3304 bool Range::Overlaps(int64_t min_int, int64_t max_int) const { |
| 3210 const intptr_t this_min = min().IsNegativeInfinity() ? | 3305 RangeBoundary lower = min().LowerBound(); |
| 3211 kIntptrMin : min().LowerBound().value(); | 3306 RangeBoundary upper = max().UpperBound(); |
| 3212 const intptr_t this_max = max().IsPositiveInfinity() ? | 3307 const int64_t this_min = lower.IsNegativeInfinity() ? |
| 3213 kIntptrMax : max().UpperBound().value(); | 3308 RangeBoundary::kMin : lower.ConstantValue(); |
| 3309 const int64_t this_max = upper.IsPositiveInfinity() ? | |
| 3310 RangeBoundary::kMax : upper.ConstantValue(); | |
| 3214 if ((this_min <= min_int) && (min_int <= this_max)) return true; | 3311 if ((this_min <= min_int) && (min_int <= this_max)) return true; |
| 3215 if ((this_min <= max_int) && (max_int <= this_max)) return true; | 3312 if ((this_min <= max_int) && (max_int <= this_max)) return true; |
| 3216 if ((min_int < this_min) && (max_int > this_max)) return true; | 3313 if ((min_int < this_min) && (max_int > this_max)) return true; |
| 3217 return false; | 3314 return false; |
| 3218 } | 3315 } |
| 3219 | 3316 |
| 3220 | 3317 |
| 3221 bool Range::IsUnsatisfiable() const { | 3318 bool Range::IsUnsatisfiable() const { |
| 3222 // Infinity case: [+inf, ...] || [..., -inf] | 3319 // Infinity case: [+inf, ...] || [..., -inf] |
| 3223 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { | 3320 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { |
| 3224 return true; | 3321 return true; |
| 3225 } | 3322 } |
| 3226 // Constant case: For example [0, -1]. | 3323 // Constant case: For example [0, -1]. |
| 3227 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { | 3324 if (Range::ConstantMin(this).ConstantValue() > |
| 3325 Range::ConstantMax(this).ConstantValue()) { | |
| 3228 return true; | 3326 return true; |
| 3229 } | 3327 } |
| 3230 // Symbol case: For example [v+1, v]. | 3328 // Symbol case: For example [v+1, v]. |
| 3231 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { | 3329 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { |
| 3232 return true; | 3330 return true; |
| 3233 } | 3331 } |
| 3234 return false; | 3332 return false; |
| 3235 } | 3333 } |
| 3236 | 3334 |
| 3237 | 3335 |
| 3238 void Range::Shl(Range* left, | 3336 void Range::Clamp(RangeBoundary::RangeSize size) { |
| 3239 Range* right, | 3337 min_ = min_.Clamp(size); |
| 3338 max_ = max_.Clamp(size); | |
| 3339 } | |
| 3340 | |
| 3341 | |
| 3342 void Range::Shl(const Range* left, | |
| 3343 const Range* right, | |
| 3240 RangeBoundary* result_min, | 3344 RangeBoundary* result_min, |
| 3241 RangeBoundary* result_max) { | 3345 RangeBoundary* result_max) { |
| 3346 ASSERT(left != NULL); | |
| 3347 ASSERT(right != NULL); | |
| 3348 ASSERT(result_min != NULL); | |
| 3349 ASSERT(result_max != NULL); | |
| 3242 RangeBoundary left_max = Range::ConstantMax(left); | 3350 RangeBoundary left_max = Range::ConstantMax(left); |
| 3243 RangeBoundary left_min = Range::ConstantMin(left); | 3351 RangeBoundary left_min = Range::ConstantMin(left); |
| 3244 // A negative shift count always deoptimizes (and throws), so the minimum | 3352 // A negative shift count always deoptimizes (and throws), so the minimum |
| 3245 // shift count is zero. | 3353 // shift count is zero. |
| 3246 intptr_t right_max = Utils::Maximum(Range::ConstantMax(right).value(), | 3354 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(), |
| 3247 static_cast<intptr_t>(0)); | 3355 static_cast<int64_t>(0)); |
| 3248 intptr_t right_min = Utils::Maximum(Range::ConstantMin(right).value(), | 3356 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(), |
| 3249 static_cast<intptr_t>(0)); | 3357 static_cast<int64_t>(0)); |
| 3250 | 3358 |
| 3251 *result_min = RangeBoundary::Shl( | 3359 *result_min = RangeBoundary::Shl( |
| 3252 left_min, | 3360 left_min, |
| 3253 left_min.value() > 0 ? right_min : right_max, | 3361 left_min.ConstantValue() > 0 ? right_min : right_max, |
| 3254 left_min.value() > 0 | 3362 left_min.ConstantValue() > 0 |
| 3255 ? RangeBoundary::PositiveInfinity() | 3363 ? RangeBoundary::PositiveInfinity() |
| 3256 : RangeBoundary::NegativeInfinity()); | 3364 : RangeBoundary::NegativeInfinity()); |
| 3257 | 3365 |
| 3258 *result_max = RangeBoundary::Shl( | 3366 *result_max = RangeBoundary::Shl( |
| 3259 left_max, | 3367 left_max, |
| 3260 left_max.value() > 0 ? right_max : right_min, | 3368 left_max.ConstantValue() > 0 ? right_max : right_min, |
| 3261 left_max.value() > 0 | 3369 left_max.ConstantValue() > 0 |
| 3262 ? RangeBoundary::PositiveInfinity() | 3370 ? RangeBoundary::PositiveInfinity() |
| 3263 : RangeBoundary::NegativeInfinity()); | 3371 : RangeBoundary::NegativeInfinity()); |
| 3264 } | 3372 } |
| 3265 | 3373 |
| 3266 | 3374 |
| 3375 bool Range::And(const Range* left_range, | |
| 3376 const Range* right_range, | |
| 3377 RangeBoundary* min, | |
| 3378 RangeBoundary* max) { | |
| 3379 ASSERT(left_range != NULL); | |
| 3380 ASSERT(right_range != NULL); | |
| 3381 ASSERT(min != NULL); | |
| 3382 ASSERT(max != NULL); | |
| 3383 | |
| 3384 if (Range::ConstantMin(right_range).ConstantValue() >= 0) { | |
| 3385 *min = RangeBoundary::FromConstant(0); | |
| 3386 *max = Range::ConstantMax(right_range); | |
| 3387 return true; | |
| 3388 } | |
| 3389 | |
| 3390 if (Range::ConstantMin(left_range).ConstantValue() >= 0) { | |
| 3391 *min = RangeBoundary::FromConstant(0); | |
| 3392 *max = Range::ConstantMax(left_range); | |
| 3393 return true; | |
| 3394 } | |
| 3395 | |
| 3396 return false; | |
| 3397 } | |
| 3398 | |
| 3399 | |
| 3400 void Range::Add(const Range* left_range, | |
| 3401 const Range* right_range, | |
| 3402 RangeBoundary* min, | |
| 3403 RangeBoundary* max, | |
| 3404 Definition* left_defn) { | |
| 3405 ASSERT(left_range != NULL); | |
| 3406 ASSERT(right_range != NULL); | |
| 3407 ASSERT(min != NULL); | |
| 3408 ASSERT(max != NULL); | |
| 3409 | |
| 3410 RangeBoundary left_min = | |
| 3411 IsArrayLength(left_defn) ? | |
| 3412 RangeBoundary::FromDefinition(left_defn) : left_range->min(); | |
| 3413 | |
| 3414 RangeBoundary left_max = | |
| 3415 IsArrayLength(left_defn) ? | |
| 3416 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | |
| 3417 | |
| 3418 if (!RangeBoundary::SymbolicAdd(left_min, right_range->min(), min)) { | |
| 3419 *min = RangeBoundary::Add(left_range->min().LowerBound(), | |
| 3420 right_range->min().LowerBound(), | |
| 3421 RangeBoundary::NegativeInfinity()); | |
| 3422 } | |
| 3423 if (!RangeBoundary::SymbolicAdd(left_max, right_range->max(), max)) { | |
| 3424 *max = RangeBoundary::Add(right_range->max().UpperBound(), | |
| 3425 left_range->max().UpperBound(), | |
| 3426 RangeBoundary::PositiveInfinity()); | |
| 3427 } | |
| 3428 } | |
| 3429 | |
| 3430 | |
| 3431 void Range::Sub(const Range* left_range, | |
| 3432 const Range* right_range, | |
| 3433 RangeBoundary* min, | |
| 3434 RangeBoundary* max, | |
| 3435 Definition* left_defn) { | |
| 3436 ASSERT(left_range != NULL); | |
| 3437 ASSERT(right_range != NULL); | |
| 3438 ASSERT(min != NULL); | |
| 3439 ASSERT(max != NULL); | |
| 3440 | |
| 3441 RangeBoundary left_min = | |
| 3442 IsArrayLength(left_defn) ? | |
| 3443 RangeBoundary::FromDefinition(left_defn) : left_range->min(); | |
| 3444 | |
| 3445 RangeBoundary left_max = | |
| 3446 IsArrayLength(left_defn) ? | |
| 3447 RangeBoundary::FromDefinition(left_defn) : left_range->max(); | |
| 3448 | |
| 3449 if (!RangeBoundary::SymbolicSub(left_min, right_range->max(), min)) { | |
| 3450 *min = RangeBoundary::Sub(left_range->min().LowerBound(), | |
| 3451 right_range->max().UpperBound(), | |
| 3452 RangeBoundary::NegativeInfinity()); | |
| 3453 } | |
| 3454 if (!RangeBoundary::SymbolicSub(left_max, right_range->min(), max)) { | |
| 3455 *max = RangeBoundary::Sub(left_range->max().UpperBound(), | |
| 3456 right_range->min().LowerBound(), | |
| 3457 RangeBoundary::PositiveInfinity()); | |
| 3458 } | |
| 3459 } | |
| 3460 | |
| 3461 | |
| 3462 bool Range::Mul(const Range* left_range, | |
| 3463 const Range* right_range, | |
| 3464 RangeBoundary* min, | |
| 3465 RangeBoundary* max) { | |
| 3466 ASSERT(left_range != NULL); | |
| 3467 ASSERT(right_range != NULL); | |
| 3468 ASSERT(min != NULL); | |
| 3469 ASSERT(max != NULL); | |
| 3470 | |
| 3471 const int64_t left_max = ConstantAbsMax(left_range); | |
| 3472 const int64_t right_max = ConstantAbsMax(right_range); | |
| 3473 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) && | |
| 3474 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) { | |
| 3475 // Product of left and right max values stays in 64 bit range. | |
| 3476 const int64_t result_max = left_max * right_max; | |
| 3477 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) { | |
| 3478 const intptr_t r_min = | |
| 3479 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -result_max; | |
| 3480 *min = RangeBoundary::FromConstant(r_min); | |
| 3481 const intptr_t r_max = | |
| 3482 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : result_max; | |
| 3483 *max = RangeBoundary::FromConstant(r_max); | |
| 3484 return true; | |
| 3485 } | |
| 3486 } | |
| 3487 return false; | |
| 3488 } | |
| 3489 | |
| 3490 | |
| 3491 // Both the a and b ranges are >= 0. | |
| 3492 bool Range::OnlyPositiveOrZero(const Range& a, const Range& b) { | |
| 3493 return a.OnlyGreaterThanOrEqualTo(0) && b.OnlyGreaterThanOrEqualTo(0); | |
| 3494 } | |
| 3495 | |
| 3496 | |
| 3497 // Both the a and b ranges are <= 0. | |
| 3498 bool Range::OnlyNegativeOrZero(const Range& a, const Range& b) { | |
| 3499 return a.OnlyLessThanOrEqualTo(0) && b.OnlyLessThanOrEqualTo(0); | |
| 3500 } | |
| 3501 | |
| 3502 | |
| 3503 // Return the maximum absolute value included in range. | |
| 3504 int64_t Range::ConstantAbsMax(const Range* range) { | |
| 3505 if (range == NULL) { | |
| 3506 return RangeBoundary::kMax; | |
| 3507 } | |
| 3508 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); | |
| 3509 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); | |
| 3510 return Utils::Maximum(abs_min, abs_max); | |
| 3511 } | |
| 3512 | |
| 3513 | |
| 3514 Range* Range::BinaryOp(const Token::Kind op, | |
| 3515 const Range* left_range, | |
| 3516 const Range* right_range, | |
| 3517 Definition* left_defn) { | |
| 3518 ASSERT(left_range != NULL); | |
| 3519 ASSERT(right_range != NULL); | |
| 3520 | |
| 3521 // Both left and right ranges are finite. | |
| 3522 ASSERT(left_range->IsFinite()); | |
| 3523 ASSERT(right_range->IsFinite()); | |
| 3524 | |
| 3525 RangeBoundary min; | |
| 3526 RangeBoundary max; | |
| 3527 ASSERT(min.IsUnknown() && max.IsUnknown()); | |
| 3528 | |
| 3529 switch (op) { | |
| 3530 case Token::kADD: | |
| 3531 Range::Add(left_range, right_range, &min, &max, left_defn); | |
| 3532 break; | |
| 3533 case Token::kSUB: | |
| 3534 Range::Sub(left_range, right_range, &min, &max, left_defn); | |
| 3535 break; | |
| 3536 case Token::kMUL: { | |
| 3537 if (!Range::Mul(left_range, right_range, &min, &max)) { | |
| 3538 return NULL; | |
| 3539 } | |
| 3540 break; | |
| 3541 } | |
| 3542 case Token::kSHL: { | |
| 3543 Range::Shl(left_range, right_range, &min, &max); | |
| 3544 break; | |
| 3545 } | |
| 3546 case Token::kBIT_AND: | |
| 3547 if (!Range::And(left_range, right_range, &min, &max)) { | |
| 3548 return NULL; | |
| 3549 } | |
| 3550 break; | |
| 3551 default: | |
| 3552 return NULL; | |
| 3553 break; | |
| 3554 } | |
| 3555 | |
| 3556 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | |
| 3557 | |
| 3558 return new Range(min, max); | |
| 3559 } | |
| 3560 | |
| 3561 | |
| 3267 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { | 3562 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { |
| 3268 return LoadFieldInstr::IsFixedLengthArrayCid(cid); | 3563 return LoadFieldInstr::IsFixedLengthArrayCid(cid); |
| 3269 } | 3564 } |
| 3270 | 3565 |
| 3271 | 3566 |
| 3272 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { | 3567 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { |
| 3273 Range* index_range = index()->definition()->range(); | 3568 Range* index_range = index()->definition()->range(); |
| 3274 | 3569 |
| 3275 // Range of the index is unknown can't decide if the check is redundant. | 3570 // Range of the index is unknown can't decide if the check is redundant. |
| 3276 if (index_range == NULL) { | 3571 if (index_range == NULL) { |
| 3277 return false; | 3572 return false; |
| 3278 } | 3573 } |
| 3279 | 3574 |
| 3280 // Range of the index is not positive. Check can't be redundant. | 3575 // Range of the index is not positive. Check can't be redundant. |
| 3281 if (Range::ConstantMin(index_range).value() < 0) { | 3576 if (Range::ConstantMinSmi(index_range).ConstantValue() < 0) { |
| 3282 return false; | 3577 return false; |
| 3283 } | 3578 } |
| 3284 | 3579 |
| 3285 RangeBoundary max = CanonicalizeBoundary(index_range->max(), | 3580 RangeBoundary max = CanonicalizeBoundary(index_range->max(), |
| 3286 RangeBoundary::PositiveInfinity()); | 3581 RangeBoundary::PositiveInfinity()); |
| 3287 | 3582 |
| 3288 if (max.Overflowed()) { | 3583 if (max.OverflowedSmi()) { |
| 3289 return false; | 3584 return false; |
| 3290 } | 3585 } |
| 3291 | 3586 |
| 3292 | 3587 |
| 3293 RangeBoundary max_upper = max.UpperBound(); | 3588 RangeBoundary max_upper = max.UpperBound(); |
| 3294 RangeBoundary length_lower = length.LowerBound(); | 3589 RangeBoundary length_lower = length.LowerBound(); |
| 3295 | 3590 |
| 3296 if (max_upper.Overflowed() || length_lower.Overflowed()) { | 3591 if (max_upper.OverflowedSmi() || length_lower.OverflowedSmi()) { |
| 3297 return false; | 3592 return false; |
| 3298 } | 3593 } |
| 3299 | 3594 |
| 3300 // Try to compare constant boundaries. | 3595 // Try to compare constant boundaries. |
| 3301 if (max_upper.value() < length_lower.value()) { | 3596 if (max_upper.ConstantValue() < length_lower.ConstantValue()) { |
| 3302 return true; | 3597 return true; |
| 3303 } | 3598 } |
| 3304 | 3599 |
| 3305 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); | 3600 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); |
| 3306 if (length.Overflowed()) { | 3601 if (length.OverflowedSmi()) { |
| 3307 return false; | 3602 return false; |
| 3308 } | 3603 } |
| 3309 | 3604 |
| 3310 // Try symbolic comparison. | 3605 // Try symbolic comparison. |
| 3311 do { | 3606 do { |
| 3312 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); | 3607 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); |
| 3313 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); | 3608 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); |
| 3314 | 3609 |
| 3315 // Failed to prove that maximum is bounded with array length. | 3610 // Failed to prove that maximum is bounded with array length. |
| 3316 return false; | 3611 return false; |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3589 case Token::kTRUNCDIV: return 0; | 3884 case Token::kTRUNCDIV: return 0; |
| 3590 case Token::kMOD: return 1; | 3885 case Token::kMOD: return 1; |
| 3591 default: UNIMPLEMENTED(); return -1; | 3886 default: UNIMPLEMENTED(); return -1; |
| 3592 } | 3887 } |
| 3593 } | 3888 } |
| 3594 | 3889 |
| 3595 | 3890 |
| 3596 #undef __ | 3891 #undef __ |
| 3597 | 3892 |
| 3598 } // namespace dart | 3893 } // namespace dart |
| OLD | NEW |