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 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
(...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 if (type_ == NULL) { | 1797 if (type_ == NULL) { |
1798 type_ = ComputeInitialType(); | 1798 type_ = ComputeInitialType(); |
1799 } | 1799 } |
1800 return type_; | 1800 return type_; |
1801 } | 1801 } |
1802 | 1802 |
1803 virtual CompileType* ComputeInitialType() const { | 1803 virtual CompileType* ComputeInitialType() const { |
1804 return ZoneCompileType::Wrap(ComputeType()); | 1804 return ZoneCompileType::Wrap(ComputeType()); |
1805 } | 1805 } |
1806 | 1806 |
| 1807 // Does this define a mint? |
| 1808 bool IsMintDefinition() { |
| 1809 return (Type()->ToCid() == kMintCid) || |
| 1810 IsBinaryMintOp() || |
| 1811 IsUnaryMintOp() || |
| 1812 IsShiftMintOp() || |
| 1813 IsUnboxInteger(); |
| 1814 } |
| 1815 |
1807 // Compute compile type for this definition. It is safe to use this | 1816 // Compute compile type for this definition. It is safe to use this |
1808 // approximation even before type propagator was run (e.g. during graph | 1817 // approximation even before type propagator was run (e.g. during graph |
1809 // building). | 1818 // building). |
1810 virtual CompileType ComputeType() const { | 1819 virtual CompileType ComputeType() const { |
1811 return CompileType::Dynamic(); | 1820 return CompileType::Dynamic(); |
1812 } | 1821 } |
1813 | 1822 |
1814 // Update CompileType of the definition. Returns true if the type has changed. | 1823 // Update CompileType of the definition. Returns true if the type has changed. |
1815 virtual bool RecomputeType() { | 1824 virtual bool RecomputeType() { |
1816 return false; | 1825 return false; |
(...skipping 13 matching lines...) Expand all Loading... |
1830 return false; | 1839 return false; |
1831 } | 1840 } |
1832 | 1841 |
1833 bool HasUses() const { | 1842 bool HasUses() const { |
1834 return (input_use_list_ != NULL) || (env_use_list_ != NULL); | 1843 return (input_use_list_ != NULL) || (env_use_list_ != NULL); |
1835 } | 1844 } |
1836 bool HasOnlyUse(Value* use) const; | 1845 bool HasOnlyUse(Value* use) const; |
1837 | 1846 |
1838 Value* input_use_list() const { return input_use_list_; } | 1847 Value* input_use_list() const { return input_use_list_; } |
1839 void set_input_use_list(Value* head) { input_use_list_ = head; } | 1848 void set_input_use_list(Value* head) { input_use_list_ = head; } |
| 1849 intptr_t InputUseListLength() const { |
| 1850 intptr_t length = 0; |
| 1851 Value* use = input_use_list_; |
| 1852 while (use != NULL) { |
| 1853 length++; |
| 1854 use = use->next_use(); |
| 1855 } |
| 1856 return length; |
| 1857 } |
1840 | 1858 |
1841 Value* env_use_list() const { return env_use_list_; } | 1859 Value* env_use_list() const { return env_use_list_; } |
1842 void set_env_use_list(Value* head) { env_use_list_ = head; } | 1860 void set_env_use_list(Value* head) { env_use_list_ = head; } |
1843 | 1861 |
1844 void AddInputUse(Value* value) { Value::AddToList(value, &input_use_list_); } | 1862 void AddInputUse(Value* value) { Value::AddToList(value, &input_use_list_); } |
1845 void AddEnvUse(Value* value) { Value::AddToList(value, &env_use_list_); } | 1863 void AddEnvUse(Value* value) { Value::AddToList(value, &env_use_list_); } |
1846 | 1864 |
1847 // Replace uses of this definition with uses of other definition or value. | 1865 // Replace uses of this definition with uses of other definition or value. |
1848 // Precondition: use lists must be properly calculated. | 1866 // Precondition: use lists must be properly calculated. |
1849 // Postcondition: use lists and use values are still valid. | 1867 // Postcondition: use lists and use values are still valid. |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2489 class RangeBoundary : public ValueObject { | 2507 class RangeBoundary : public ValueObject { |
2490 public: | 2508 public: |
2491 enum Kind { | 2509 enum Kind { |
2492 kUnknown, | 2510 kUnknown, |
2493 kNegativeInfinity, | 2511 kNegativeInfinity, |
2494 kPositiveInfinity, | 2512 kPositiveInfinity, |
2495 kSymbol, | 2513 kSymbol, |
2496 kConstant, | 2514 kConstant, |
2497 }; | 2515 }; |
2498 | 2516 |
| 2517 enum RangeSize { |
| 2518 kRangeBoundarySmi, |
| 2519 kRangeBoundaryInt64, |
| 2520 }; |
| 2521 |
2499 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } | 2522 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } |
2500 | 2523 |
2501 RangeBoundary(const RangeBoundary& other) | 2524 RangeBoundary(const RangeBoundary& other) |
2502 : ValueObject(), | 2525 : ValueObject(), |
2503 kind_(other.kind_), | 2526 kind_(other.kind_), |
2504 value_(other.value_), | 2527 value_(other.value_), |
2505 offset_(other.offset_) { } | 2528 offset_(other.offset_) { } |
2506 | 2529 |
2507 explicit RangeBoundary(intptr_t val) | 2530 explicit RangeBoundary(int64_t val) |
2508 : kind_(kConstant), value_(val), offset_(0) { } | 2531 : kind_(kConstant), value_(val), offset_(0) { } |
2509 | 2532 |
2510 RangeBoundary& operator=(const RangeBoundary& other) { | 2533 RangeBoundary& operator=(const RangeBoundary& other) { |
2511 kind_ = other.kind_; | 2534 kind_ = other.kind_; |
2512 value_ = other.value_; | 2535 value_ = other.value_; |
2513 offset_ = other.offset_; | 2536 offset_ = other.offset_; |
2514 return *this; | 2537 return *this; |
2515 } | 2538 } |
2516 | 2539 |
2517 static RangeBoundary FromConstant(intptr_t val) { | 2540 static const int64_t kMin = kMinInt64; |
| 2541 static const int64_t kMax = kMaxInt64; |
| 2542 |
| 2543 // Construct a RangeBoundary for a constant value. |
| 2544 static RangeBoundary FromConstant(int64_t val) { |
2518 return RangeBoundary(val); | 2545 return RangeBoundary(val); |
2519 } | 2546 } |
2520 | 2547 |
| 2548 // Construct a RangeBoundary for -inf. |
2521 static RangeBoundary NegativeInfinity() { | 2549 static RangeBoundary NegativeInfinity() { |
2522 return RangeBoundary(kNegativeInfinity, 0, 0); | 2550 return RangeBoundary(kNegativeInfinity, 0, 0); |
2523 } | 2551 } |
2524 | 2552 |
| 2553 // Construct a RangeBoundary for +inf. |
2525 static RangeBoundary PositiveInfinity() { | 2554 static RangeBoundary PositiveInfinity() { |
2526 return RangeBoundary(kPositiveInfinity, 0, 0); | 2555 return RangeBoundary(kPositiveInfinity, 0, 0); |
2527 } | 2556 } |
2528 | 2557 |
2529 static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0); | 2558 // Construct a RangeBoundary from a definition and offset. |
| 2559 static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0); |
2530 | 2560 |
| 2561 // Construct a RangeBoundary for the constant MinSmi value. |
2531 static RangeBoundary MinSmi() { | 2562 static RangeBoundary MinSmi() { |
2532 return FromConstant(Smi::kMinValue); | 2563 return FromConstant(Smi::kMinValue); |
2533 } | 2564 } |
2534 | 2565 |
| 2566 // Construct a RangeBoundary for the constant MaxSmi value. |
2535 static RangeBoundary MaxSmi() { | 2567 static RangeBoundary MaxSmi() { |
2536 return FromConstant(Smi::kMaxValue); | 2568 return FromConstant(Smi::kMaxValue); |
2537 } | 2569 } |
2538 | 2570 |
2539 static RangeBoundary Min(RangeBoundary a, RangeBoundary b); | 2571 // Construct a RangeBoundary for the constant kMin value. |
2540 | 2572 static RangeBoundary MinConstant() { |
2541 static RangeBoundary Max(RangeBoundary a, RangeBoundary b); | 2573 return FromConstant(kMin); |
2542 | |
2543 bool Overflowed() const { | |
2544 // If the value is a constant outside of Smi range or infinity. | |
2545 return (IsConstant() && !Smi::IsValid(value())) || IsInfinity(); | |
2546 } | 2574 } |
2547 | 2575 |
2548 RangeBoundary Clamp() const { | 2576 // Construct a RangeBoundary for the constant kMax value. |
| 2577 static RangeBoundary MaxConstant() { |
| 2578 return FromConstant(kMax); |
| 2579 } |
| 2580 |
| 2581 // Calculate the minimum of a and b within smi range. |
| 2582 static RangeBoundary Min(RangeBoundary a, RangeBoundary b, RangeSize size); |
| 2583 static RangeBoundary Max(RangeBoundary a, RangeBoundary b, RangeSize size); |
| 2584 |
| 2585 // Returns true when this is a constant that is outside of Smi range. |
| 2586 bool OverflowedSmi() const { |
| 2587 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); |
| 2588 } |
| 2589 |
| 2590 // Returns true if this outside mint range. |
| 2591 bool OverflowedMint() const { |
| 2592 return IsInfinity(); |
| 2593 } |
| 2594 |
| 2595 // -/+ infinity are clamped to MinConstant/MaxConstant. |
| 2596 RangeBoundary Clamp(RangeSize size) const { |
2549 if (IsNegativeInfinity()) { | 2597 if (IsNegativeInfinity()) { |
2550 return MinSmi(); | 2598 return (size == kRangeBoundaryInt64) ? MinConstant() : MinSmi(); |
2551 } else if (IsPositiveInfinity()) { | 2599 } |
2552 return MaxSmi(); | 2600 if (IsPositiveInfinity()) { |
2553 } else if (IsConstant()) { | 2601 return (size == kRangeBoundaryInt64) ? MaxConstant() : MaxSmi(); |
2554 if (value() < Smi::kMinValue) return MinSmi(); | 2602 } |
2555 if (value() > Smi::kMaxValue) return MaxSmi(); | 2603 if ((size == kRangeBoundarySmi) && IsConstant()) { |
| 2604 if (ConstantValue() <= Smi::kMinValue) { |
| 2605 return MinSmi(); |
| 2606 } |
| 2607 if (ConstantValue() >= Smi::kMaxValue) { |
| 2608 return MaxSmi(); |
| 2609 } |
2556 } | 2610 } |
2557 return *this; | 2611 return *this; |
2558 } | 2612 } |
2559 | 2613 |
2560 bool Equals(const RangeBoundary& other) { | 2614 |
2561 return kind_ == other.kind_ | 2615 bool IsSmiMinimumOrBelow() const { |
2562 && value_ == other.value_ | 2616 return IsNegativeInfinity() || |
2563 && offset_ == other.offset_; | 2617 (IsConstant() && (ConstantValue() <= Smi::kMinValue)); |
2564 } | 2618 } |
2565 | 2619 |
| 2620 bool IsSmiMaximumOrAbove() const { |
| 2621 return IsPositiveInfinity() || |
| 2622 (IsConstant() && (ConstantValue() >= Smi::kMaxValue)); |
| 2623 } |
| 2624 |
| 2625 bool IsMinimumOrBelow() const { |
| 2626 return IsNegativeInfinity() || (IsConstant() && (ConstantValue() == kMin)); |
| 2627 } |
| 2628 |
| 2629 bool IsMaximumOrAbove() const { |
| 2630 return IsPositiveInfinity() || (IsConstant() && (ConstantValue() == kMax)); |
| 2631 } |
| 2632 |
| 2633 intptr_t kind() const { |
| 2634 return kind_; |
| 2635 } |
| 2636 |
| 2637 // Kind tests. |
2566 bool IsUnknown() const { return kind_ == kUnknown; } | 2638 bool IsUnknown() const { return kind_ == kUnknown; } |
2567 bool IsConstant() const { return kind_ == kConstant; } | 2639 bool IsConstant() const { return kind_ == kConstant; } |
2568 bool IsSymbol() const { return kind_ == kSymbol; } | 2640 bool IsSymbol() const { return kind_ == kSymbol; } |
2569 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } | 2641 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } |
2570 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } | 2642 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } |
2571 bool IsInfinity() const { | 2643 bool IsInfinity() const { |
2572 return IsNegativeInfinity() || IsPositiveInfinity(); | 2644 return IsNegativeInfinity() || IsPositiveInfinity(); |
2573 } | 2645 } |
2574 | 2646 bool IsConstantOrInfinity() const { |
2575 intptr_t value() const { | 2647 return IsConstant() || IsInfinity(); |
2576 ASSERT(IsConstant()); | |
2577 return value_; | |
2578 } | 2648 } |
2579 | 2649 |
| 2650 // Returns the value of a kConstant RangeBoundary. |
| 2651 int64_t ConstantValue() const; |
| 2652 |
| 2653 // Returns the Definition associated with a kSymbol RangeBoundary. |
2580 Definition* symbol() const { | 2654 Definition* symbol() const { |
2581 ASSERT(IsSymbol()); | 2655 ASSERT(IsSymbol()); |
2582 return reinterpret_cast<Definition*>(value_); | 2656 return reinterpret_cast<Definition*>(value_); |
2583 } | 2657 } |
2584 | 2658 |
2585 intptr_t offset() const { | 2659 // Offset from symbol. |
| 2660 int64_t offset() const { |
2586 return offset_; | 2661 return offset_; |
2587 } | 2662 } |
2588 | 2663 |
| 2664 // Computes the LowerBound of this. Three cases: |
| 2665 // IsInfinity() -> NegativeInfinity(). |
| 2666 // IsConstant() -> value(). |
| 2667 // IsSymbol() -> lower bound computed from definition + offset. |
2589 RangeBoundary LowerBound() const; | 2668 RangeBoundary LowerBound() const; |
| 2669 |
| 2670 // Computes the UpperBound of this. Three cases: |
| 2671 // IsInfinity() -> PositiveInfinity(). |
| 2672 // IsConstant() -> value(). |
| 2673 // IsSymbol() -> upper bound computed from definition + offset. |
2590 RangeBoundary UpperBound() const; | 2674 RangeBoundary UpperBound() const; |
2591 | 2675 |
2592 void PrintTo(BufferFormatter* f) const; | 2676 void PrintTo(BufferFormatter* f) const; |
2593 const char* ToCString() const; | 2677 const char* ToCString() const; |
2594 | 2678 |
2595 static RangeBoundary Add(const RangeBoundary& a, | 2679 static RangeBoundary Add(const RangeBoundary& a, |
2596 const RangeBoundary& b, | 2680 const RangeBoundary& b, |
2597 const RangeBoundary& overflow) { | 2681 const RangeBoundary& overflow); |
2598 ASSERT(a.IsConstant() && b.IsConstant()); | |
2599 | |
2600 intptr_t result = a.value() + b.value(); | |
2601 if (!Smi::IsValid(result)) { | |
2602 return overflow; | |
2603 } | |
2604 return RangeBoundary::FromConstant(result); | |
2605 } | |
2606 | 2682 |
2607 static RangeBoundary Sub(const RangeBoundary& a, | 2683 static RangeBoundary Sub(const RangeBoundary& a, |
2608 const RangeBoundary& b, | 2684 const RangeBoundary& b, |
2609 const RangeBoundary& overflow) { | 2685 const RangeBoundary& overflow); |
2610 ASSERT(a.IsConstant() && b.IsConstant()); | |
2611 | |
2612 intptr_t result = a.value() - b.value(); | |
2613 if (!Smi::IsValid(result)) { | |
2614 return overflow; | |
2615 } | |
2616 return RangeBoundary::FromConstant(result); | |
2617 } | |
2618 | 2686 |
2619 static RangeBoundary Shl(const RangeBoundary& value_boundary, | 2687 static RangeBoundary Shl(const RangeBoundary& value_boundary, |
2620 intptr_t shift_count, | 2688 int64_t shift_count, |
2621 const RangeBoundary& overflow) { | 2689 const RangeBoundary& overflow); |
2622 ASSERT(value_boundary.IsConstant()); | 2690 |
2623 ASSERT(shift_count >= 0); | 2691 // Attempts to calculate a + b when: |
2624 intptr_t limit = 64 - shift_count; | 2692 // a is a symbol and b is a constant OR |
2625 int64_t value = static_cast<int64_t>(value_boundary.value()); | 2693 // a is a constant and b is a symbol |
2626 if ((value == 0) || | 2694 // returns true if it succeeds, output is in result. |
2627 (shift_count == 0) || | 2695 static bool SymbolicAdd(const RangeBoundary& a, |
2628 ((limit > 0) && (Utils::IsInt(limit, value)))) { | 2696 const RangeBoundary& b, |
2629 // Result stays in 64 bit range. | 2697 RangeBoundary* result); |
2630 int64_t result = value << shift_count; | 2698 |
2631 return Smi::IsValid64(result) ? RangeBoundary(result) : overflow; | 2699 // Attempts to calculate a - b when: |
2632 } | 2700 // a is a symbol and b is a constant |
2633 return overflow; | 2701 // returns true if it succeeds, output is in result. |
2634 } | 2702 static bool SymbolicSub(const RangeBoundary& a, |
| 2703 const RangeBoundary& b, |
| 2704 RangeBoundary* result); |
| 2705 |
| 2706 bool Equals(const RangeBoundary& other) const; |
2635 | 2707 |
2636 private: | 2708 private: |
2637 RangeBoundary(Kind kind, intptr_t value, intptr_t offset) | 2709 RangeBoundary(Kind kind, int64_t value, int64_t offset) |
2638 : kind_(kind), value_(value), offset_(offset) { } | 2710 : kind_(kind), value_(value), offset_(offset) { } |
2639 | 2711 |
2640 Kind kind_; | 2712 Kind kind_; |
2641 intptr_t value_; | 2713 int64_t value_; |
2642 intptr_t offset_; | 2714 int64_t offset_; |
2643 }; | 2715 }; |
2644 | 2716 |
2645 | 2717 |
2646 class Range : public ZoneAllocated { | 2718 class Range : public ZoneAllocated { |
2647 public: | 2719 public: |
2648 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { } | 2720 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { } |
2649 | 2721 |
2650 static Range* Unknown() { | 2722 static Range* Unknown() { |
2651 return new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | 2723 return new Range(RangeBoundary::MinConstant(), |
| 2724 RangeBoundary::MaxConstant()); |
| 2725 } |
| 2726 |
| 2727 static Range* UnknownSmi() { |
| 2728 return new Range(RangeBoundary::MinSmi(), |
| 2729 RangeBoundary::MaxSmi()); |
2652 } | 2730 } |
2653 | 2731 |
2654 void PrintTo(BufferFormatter* f) const; | 2732 void PrintTo(BufferFormatter* f) const; |
2655 static const char* ToCString(Range* range); | 2733 static const char* ToCString(const Range* range); |
2656 | 2734 |
2657 const RangeBoundary& min() const { return min_; } | 2735 const RangeBoundary& min() const { return min_; } |
2658 const RangeBoundary& max() const { return max_; } | 2736 const RangeBoundary& max() const { return max_; } |
2659 | 2737 |
2660 static RangeBoundary ConstantMin(const Range* range) { | 2738 static RangeBoundary ConstantMinSmi(const Range* range) { |
2661 if (range == NULL) { | 2739 if (range == NULL) { |
2662 return RangeBoundary::MinSmi(); | 2740 return RangeBoundary::MinSmi(); |
2663 } | 2741 } |
2664 return range->min().LowerBound().Clamp(); | 2742 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundarySmi); |
| 2743 } |
| 2744 |
| 2745 static RangeBoundary ConstantMaxSmi(const Range* range) { |
| 2746 if (range == NULL) { |
| 2747 return RangeBoundary::MaxSmi(); |
| 2748 } |
| 2749 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundarySmi); |
| 2750 } |
| 2751 |
| 2752 static RangeBoundary ConstantMin(const Range* range) { |
| 2753 if (range == NULL) { |
| 2754 return RangeBoundary::MinConstant(); |
| 2755 } |
| 2756 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundaryInt64); |
2665 } | 2757 } |
2666 | 2758 |
2667 static RangeBoundary ConstantMax(const Range* range) { | 2759 static RangeBoundary ConstantMax(const Range* range) { |
2668 if (range == NULL) { | 2760 if (range == NULL) { |
2669 return RangeBoundary::MaxSmi(); | 2761 return RangeBoundary::MaxConstant(); |
2670 } | 2762 } |
2671 return range->max().UpperBound().Clamp(); | 2763 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundaryInt64); |
2672 } | 2764 } |
2673 | 2765 |
2674 // [0, +inf] | 2766 // [0, +inf] |
2675 bool IsPositive() const; | 2767 bool IsPositive() const; |
2676 | 2768 |
2677 // [-inf, 0) | 2769 // [-inf, val]. |
2678 bool IsNegative() const; | 2770 bool OnlyLessThanOrEqualTo(int64_t val) const; |
2679 | 2771 |
2680 // [-inf, val]. | 2772 // [val, +inf]. |
2681 bool OnlyLessThanOrEqualTo(intptr_t val) const; | 2773 bool OnlyGreaterThanOrEqualTo(int64_t val) const; |
2682 | 2774 |
2683 // Inclusive. | 2775 // Inclusive. |
2684 bool IsWithin(intptr_t min_int, intptr_t max_int) const; | 2776 bool IsWithin(int64_t min_int, int64_t max_int) const; |
2685 | 2777 |
2686 // Inclusive. | 2778 // Inclusive. |
2687 bool Overlaps(intptr_t min_int, intptr_t max_int) const; | 2779 bool Overlaps(int64_t min_int, int64_t max_int) const; |
2688 | 2780 |
2689 bool IsUnsatisfiable() const; | 2781 bool IsUnsatisfiable() const; |
2690 | 2782 |
2691 static void Shl(Range* left_range, | 2783 static void Add(const Range* left_range, |
2692 Range* right_range, | 2784 const Range* right_range, |
| 2785 RangeBoundary* min, |
| 2786 RangeBoundary* max, |
| 2787 Definition* left_defn); |
| 2788 |
| 2789 static void Sub(const Range* left_range, |
| 2790 const Range* right_range, |
| 2791 RangeBoundary* min, |
| 2792 RangeBoundary* max, |
| 2793 Definition* left_defn); |
| 2794 |
| 2795 static bool Mul(const Range* left_range, |
| 2796 const Range* right_range, |
2693 RangeBoundary* min, | 2797 RangeBoundary* min, |
2694 RangeBoundary* max); | 2798 RangeBoundary* max); |
2695 | 2799 |
| 2800 static void Shl(const Range* left_range, |
| 2801 const Range* right_range, |
| 2802 RangeBoundary* min, |
| 2803 RangeBoundary* max); |
| 2804 |
| 2805 static bool And(const Range* left_range, |
| 2806 const Range* right_range, |
| 2807 RangeBoundary* min, |
| 2808 RangeBoundary* max); |
| 2809 |
| 2810 |
| 2811 // Both the a and b ranges are >= 0. |
| 2812 static bool OnlyPositiveOrZero(const Range& a, const Range& b); |
| 2813 |
| 2814 // Both the a and b ranges are <= 0. |
| 2815 static bool OnlyNegativeOrZero(const Range& a, const Range& b); |
| 2816 |
| 2817 // Return the maximum absolute value included in range. |
| 2818 static int64_t ConstantAbsMax(const Range* range); |
| 2819 |
| 2820 static Range* BinaryOp(const Token::Kind op, |
| 2821 const Range* left_range, |
| 2822 const Range* right_range, |
| 2823 Definition* left_defn); |
| 2824 |
2696 private: | 2825 private: |
2697 RangeBoundary min_; | 2826 RangeBoundary min_; |
2698 RangeBoundary max_; | 2827 RangeBoundary max_; |
2699 }; | 2828 }; |
2700 | 2829 |
2701 | 2830 |
2702 class ConstraintInstr : public TemplateDefinition<2> { | 2831 class ConstraintInstr : public TemplateDefinition<2> { |
2703 public: | 2832 public: |
2704 ConstraintInstr(Value* value, Range* constraint) | 2833 ConstraintInstr(Value* value, Range* constraint) |
2705 : constraint_(constraint), | 2834 : constraint_(constraint), |
(...skipping 2419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5125 virtual bool CanDeoptimize() const { | 5254 virtual bool CanDeoptimize() const { |
5126 return (value()->Type()->ToCid() != kSmiCid) | 5255 return (value()->Type()->ToCid() != kSmiCid) |
5127 && (value()->Type()->ToCid() != kMintCid); | 5256 && (value()->Type()->ToCid() != kMintCid); |
5128 } | 5257 } |
5129 | 5258 |
5130 virtual Representation representation() const { | 5259 virtual Representation representation() const { |
5131 return kUnboxedMint; | 5260 return kUnboxedMint; |
5132 } | 5261 } |
5133 | 5262 |
5134 | 5263 |
| 5264 virtual void InferRange(); |
| 5265 |
5135 DECLARE_INSTRUCTION(UnboxInteger) | 5266 DECLARE_INSTRUCTION(UnboxInteger) |
5136 virtual CompileType ComputeType() const; | 5267 virtual CompileType ComputeType() const; |
5137 | 5268 |
5138 virtual bool AllowsCSE() const { return true; } | 5269 virtual bool AllowsCSE() const { return true; } |
5139 virtual EffectSet Effects() const { return EffectSet::None(); } | 5270 virtual EffectSet Effects() const { return EffectSet::None(); } |
5140 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 5271 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
5141 virtual bool AttributesEqual(Instruction* other) const { return true; } | 5272 virtual bool AttributesEqual(Instruction* other) const { return true; } |
5142 | 5273 |
5143 virtual bool MayThrow() const { return false; } | 5274 virtual bool MayThrow() const { return false; } |
5144 | 5275 |
(...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6914 ASSERT((idx == 0) || (idx == 1)); | 7045 ASSERT((idx == 0) || (idx == 1)); |
6915 return kUnboxedMint; | 7046 return kUnboxedMint; |
6916 } | 7047 } |
6917 | 7048 |
6918 virtual intptr_t DeoptimizationTarget() const { | 7049 virtual intptr_t DeoptimizationTarget() const { |
6919 // Direct access since this instruction cannot deoptimize, and the deopt-id | 7050 // Direct access since this instruction cannot deoptimize, and the deopt-id |
6920 // was inherited from another instruction that could deoptimize. | 7051 // was inherited from another instruction that could deoptimize. |
6921 return deopt_id_; | 7052 return deopt_id_; |
6922 } | 7053 } |
6923 | 7054 |
| 7055 virtual void InferRange(); |
| 7056 |
6924 virtual Definition* Canonicalize(FlowGraph* flow_graph); | 7057 virtual Definition* Canonicalize(FlowGraph* flow_graph); |
6925 | 7058 |
6926 DECLARE_INSTRUCTION(BinaryMintOp) | 7059 DECLARE_INSTRUCTION(BinaryMintOp) |
6927 virtual CompileType ComputeType() const; | 7060 virtual CompileType ComputeType() const; |
6928 | 7061 |
6929 virtual bool AllowsCSE() const { return true; } | 7062 virtual bool AllowsCSE() const { return true; } |
6930 virtual EffectSet Effects() const { return EffectSet::None(); } | 7063 virtual EffectSet Effects() const { return EffectSet::None(); } |
6931 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 7064 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
6932 virtual bool AttributesEqual(Instruction* other) const { | 7065 virtual bool AttributesEqual(Instruction* other) const { |
6933 ASSERT(other->IsBinaryMintOp()); | 7066 ASSERT(other->IsBinaryMintOp()); |
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8037 ForwardInstructionIterator* current_iterator_; | 8170 ForwardInstructionIterator* current_iterator_; |
8038 | 8171 |
8039 private: | 8172 private: |
8040 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 8173 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
8041 }; | 8174 }; |
8042 | 8175 |
8043 | 8176 |
8044 } // namespace dart | 8177 } // namespace dart |
8045 | 8178 |
8046 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8179 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |