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