| 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 14 matching lines...) Expand all Loading... |
| 25 class Definition; | 25 class Definition; |
| 26 class Environment; | 26 class Environment; |
| 27 class FlowGraph; | 27 class FlowGraph; |
| 28 class FlowGraphBuilder; | 28 class FlowGraphBuilder; |
| 29 class FlowGraphCompiler; | 29 class FlowGraphCompiler; |
| 30 class FlowGraphVisitor; | 30 class FlowGraphVisitor; |
| 31 class Instruction; | 31 class Instruction; |
| 32 class LocalVariable; | 32 class LocalVariable; |
| 33 class ParsedFunction; | 33 class ParsedFunction; |
| 34 class Range; | 34 class Range; |
| 35 class RangeBoundary; |
| 35 | 36 |
| 36 | 37 |
| 37 // TODO(srdjan): Unify with INTRINSIC_LIST. | 38 // TODO(srdjan): Unify with INTRINSIC_LIST. |
| 38 // (class-name, function-name, recognized enum, fingerprint). | 39 // (class-name, function-name, recognized enum, fingerprint). |
| 39 // See intrinsifier for fingerprint computation. | 40 // See intrinsifier for fingerprint computation. |
| 40 #define RECOGNIZED_LIST(V) \ | 41 #define RECOGNIZED_LIST(V) \ |
| 41 V(::, identical, ObjectIdentical, 496869842) \ | 42 V(::, identical, ObjectIdentical, 496869842) \ |
| 42 V(ClassID, getID, ClassIDgetID, 1322490980) \ | 43 V(ClassID, getID, ClassIDgetID, 1322490980) \ |
| 43 V(Object, ==, ObjectEquals, 1068471689) \ | 44 V(Object, ==, ObjectEquals, 1068471689) \ |
| 44 V(Object, Object., ObjectConstructor, 1066669787) \ | 45 V(Object, Object., ObjectConstructor, 1066669787) \ |
| (...skipping 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2556 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 2557 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| 2557 virtual EffectSet Effects() const { return EffectSet::None(); } | 2558 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 2558 | 2559 |
| 2559 virtual bool MayThrow() const { return false; } | 2560 virtual bool MayThrow() const { return false; } |
| 2560 | 2561 |
| 2561 private: | 2562 private: |
| 2562 DISALLOW_COPY_AND_ASSIGN(RedefinitionInstr); | 2563 DISALLOW_COPY_AND_ASSIGN(RedefinitionInstr); |
| 2563 }; | 2564 }; |
| 2564 | 2565 |
| 2565 | 2566 |
| 2566 class RangeBoundary : public ValueObject { | |
| 2567 public: | |
| 2568 enum Kind { | |
| 2569 kUnknown, | |
| 2570 kNegativeInfinity, | |
| 2571 kPositiveInfinity, | |
| 2572 kSymbol, | |
| 2573 kConstant, | |
| 2574 }; | |
| 2575 | |
| 2576 enum RangeSize { | |
| 2577 kRangeBoundarySmi, | |
| 2578 kRangeBoundaryInt64, | |
| 2579 }; | |
| 2580 | |
| 2581 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } | |
| 2582 | |
| 2583 RangeBoundary(const RangeBoundary& other) | |
| 2584 : ValueObject(), | |
| 2585 kind_(other.kind_), | |
| 2586 value_(other.value_), | |
| 2587 offset_(other.offset_) { } | |
| 2588 | |
| 2589 explicit RangeBoundary(int64_t val) | |
| 2590 : kind_(kConstant), value_(val), offset_(0) { } | |
| 2591 | |
| 2592 RangeBoundary& operator=(const RangeBoundary& other) { | |
| 2593 kind_ = other.kind_; | |
| 2594 value_ = other.value_; | |
| 2595 offset_ = other.offset_; | |
| 2596 return *this; | |
| 2597 } | |
| 2598 | |
| 2599 static const int64_t kMin = kMinInt64; | |
| 2600 static const int64_t kMax = kMaxInt64; | |
| 2601 | |
| 2602 // Construct a RangeBoundary for a constant value. | |
| 2603 static RangeBoundary FromConstant(int64_t val) { | |
| 2604 return RangeBoundary(val); | |
| 2605 } | |
| 2606 | |
| 2607 // Construct a RangeBoundary for -inf. | |
| 2608 static RangeBoundary NegativeInfinity() { | |
| 2609 return RangeBoundary(kNegativeInfinity, 0, 0); | |
| 2610 } | |
| 2611 | |
| 2612 // Construct a RangeBoundary for +inf. | |
| 2613 static RangeBoundary PositiveInfinity() { | |
| 2614 return RangeBoundary(kPositiveInfinity, 0, 0); | |
| 2615 } | |
| 2616 | |
| 2617 // Construct a RangeBoundary from a definition and offset. | |
| 2618 static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0); | |
| 2619 | |
| 2620 // Construct a RangeBoundary for the constant MinSmi value. | |
| 2621 static RangeBoundary MinSmi() { | |
| 2622 return FromConstant(Smi::kMinValue); | |
| 2623 } | |
| 2624 | |
| 2625 // Construct a RangeBoundary for the constant MaxSmi value. | |
| 2626 static RangeBoundary MaxSmi() { | |
| 2627 return FromConstant(Smi::kMaxValue); | |
| 2628 } | |
| 2629 | |
| 2630 // Construct a RangeBoundary for the constant kMin value. | |
| 2631 static RangeBoundary MinConstant() { | |
| 2632 return FromConstant(kMin); | |
| 2633 } | |
| 2634 | |
| 2635 // Construct a RangeBoundary for the constant kMax value. | |
| 2636 static RangeBoundary MaxConstant() { | |
| 2637 return FromConstant(kMax); | |
| 2638 } | |
| 2639 | |
| 2640 // Calculate the minimum of a and b within the given range. | |
| 2641 static RangeBoundary Min(RangeBoundary a, RangeBoundary b, RangeSize size); | |
| 2642 static RangeBoundary Max(RangeBoundary a, RangeBoundary b, RangeSize size); | |
| 2643 | |
| 2644 // Returns true when this is a constant that is outside of Smi range. | |
| 2645 bool OverflowedSmi() const { | |
| 2646 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); | |
| 2647 } | |
| 2648 | |
| 2649 // Returns true if this outside mint range. | |
| 2650 bool OverflowedMint() const { | |
| 2651 return IsInfinity(); | |
| 2652 } | |
| 2653 | |
| 2654 // -/+ infinity are clamped to MinConstant/MaxConstant of the given type. | |
| 2655 RangeBoundary Clamp(RangeSize size) const { | |
| 2656 if (IsNegativeInfinity()) { | |
| 2657 return (size == kRangeBoundaryInt64) ? MinConstant() : MinSmi(); | |
| 2658 } | |
| 2659 if (IsPositiveInfinity()) { | |
| 2660 return (size == kRangeBoundaryInt64) ? MaxConstant() : MaxSmi(); | |
| 2661 } | |
| 2662 if ((size == kRangeBoundarySmi) && IsConstant()) { | |
| 2663 if (ConstantValue() <= Smi::kMinValue) { | |
| 2664 return MinSmi(); | |
| 2665 } | |
| 2666 if (ConstantValue() >= Smi::kMaxValue) { | |
| 2667 return MaxSmi(); | |
| 2668 } | |
| 2669 } | |
| 2670 // If this range is a symbolic range, we do not clamp it. | |
| 2671 // This could lead to some imprecision later on. | |
| 2672 return *this; | |
| 2673 } | |
| 2674 | |
| 2675 | |
| 2676 bool IsSmiMinimumOrBelow() const { | |
| 2677 return IsNegativeInfinity() || | |
| 2678 (IsConstant() && (ConstantValue() <= Smi::kMinValue)); | |
| 2679 } | |
| 2680 | |
| 2681 bool IsSmiMaximumOrAbove() const { | |
| 2682 return IsPositiveInfinity() || | |
| 2683 (IsConstant() && (ConstantValue() >= Smi::kMaxValue)); | |
| 2684 } | |
| 2685 | |
| 2686 bool IsMinimumOrBelow() const { | |
| 2687 return IsNegativeInfinity() || (IsConstant() && (ConstantValue() == kMin)); | |
| 2688 } | |
| 2689 | |
| 2690 bool IsMaximumOrAbove() const { | |
| 2691 return IsPositiveInfinity() || (IsConstant() && (ConstantValue() == kMax)); | |
| 2692 } | |
| 2693 | |
| 2694 intptr_t kind() const { | |
| 2695 return kind_; | |
| 2696 } | |
| 2697 | |
| 2698 // Kind tests. | |
| 2699 bool IsUnknown() const { return kind_ == kUnknown; } | |
| 2700 bool IsConstant() const { return kind_ == kConstant; } | |
| 2701 bool IsSymbol() const { return kind_ == kSymbol; } | |
| 2702 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } | |
| 2703 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } | |
| 2704 bool IsInfinity() const { | |
| 2705 return IsNegativeInfinity() || IsPositiveInfinity(); | |
| 2706 } | |
| 2707 bool IsConstantOrInfinity() const { | |
| 2708 return IsConstant() || IsInfinity(); | |
| 2709 } | |
| 2710 | |
| 2711 // Returns the value of a kConstant RangeBoundary. | |
| 2712 int64_t ConstantValue() const; | |
| 2713 | |
| 2714 // Returns the Definition associated with a kSymbol RangeBoundary. | |
| 2715 Definition* symbol() const { | |
| 2716 ASSERT(IsSymbol()); | |
| 2717 return reinterpret_cast<Definition*>(value_); | |
| 2718 } | |
| 2719 | |
| 2720 // Offset from symbol. | |
| 2721 int64_t offset() const { | |
| 2722 return offset_; | |
| 2723 } | |
| 2724 | |
| 2725 // Computes the LowerBound of this. Three cases: | |
| 2726 // IsInfinity() -> NegativeInfinity(). | |
| 2727 // IsConstant() -> value(). | |
| 2728 // IsSymbol() -> lower bound computed from definition + offset. | |
| 2729 RangeBoundary LowerBound() const; | |
| 2730 | |
| 2731 // Computes the UpperBound of this. Three cases: | |
| 2732 // IsInfinity() -> PositiveInfinity(). | |
| 2733 // IsConstant() -> value(). | |
| 2734 // IsSymbol() -> upper bound computed from definition + offset. | |
| 2735 RangeBoundary UpperBound() const; | |
| 2736 | |
| 2737 void PrintTo(BufferFormatter* f) const; | |
| 2738 const char* ToCString() const; | |
| 2739 | |
| 2740 static RangeBoundary Add(const RangeBoundary& a, | |
| 2741 const RangeBoundary& b, | |
| 2742 const RangeBoundary& overflow); | |
| 2743 | |
| 2744 static RangeBoundary Sub(const RangeBoundary& a, | |
| 2745 const RangeBoundary& b, | |
| 2746 const RangeBoundary& overflow); | |
| 2747 | |
| 2748 static RangeBoundary Shl(const RangeBoundary& value_boundary, | |
| 2749 int64_t shift_count, | |
| 2750 const RangeBoundary& overflow); | |
| 2751 | |
| 2752 static RangeBoundary Shr(const RangeBoundary& value_boundary, | |
| 2753 int64_t shift_count) { | |
| 2754 ASSERT(value_boundary.IsConstant()); | |
| 2755 ASSERT(shift_count >= 0); | |
| 2756 int64_t value = static_cast<int64_t>(value_boundary.ConstantValue()); | |
| 2757 int64_t result = value >> shift_count; | |
| 2758 return RangeBoundary(result); | |
| 2759 } | |
| 2760 | |
| 2761 // Attempts to calculate a + b when: | |
| 2762 // a is a symbol and b is a constant OR | |
| 2763 // a is a constant and b is a symbol | |
| 2764 // returns true if it succeeds, output is in result. | |
| 2765 static bool SymbolicAdd(const RangeBoundary& a, | |
| 2766 const RangeBoundary& b, | |
| 2767 RangeBoundary* result); | |
| 2768 | |
| 2769 // Attempts to calculate a - b when: | |
| 2770 // a is a symbol and b is a constant | |
| 2771 // returns true if it succeeds, output is in result. | |
| 2772 static bool SymbolicSub(const RangeBoundary& a, | |
| 2773 const RangeBoundary& b, | |
| 2774 RangeBoundary* result); | |
| 2775 | |
| 2776 bool Equals(const RangeBoundary& other) const; | |
| 2777 | |
| 2778 private: | |
| 2779 RangeBoundary(Kind kind, int64_t value, int64_t offset) | |
| 2780 : kind_(kind), value_(value), offset_(offset) { } | |
| 2781 | |
| 2782 Kind kind_; | |
| 2783 int64_t value_; | |
| 2784 int64_t offset_; | |
| 2785 }; | |
| 2786 | |
| 2787 | |
| 2788 class Range : public ZoneAllocated { | |
| 2789 public: | |
| 2790 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { } | |
| 2791 | |
| 2792 static Range* Unknown() { | |
| 2793 return new Range(RangeBoundary::MinConstant(), | |
| 2794 RangeBoundary::MaxConstant()); | |
| 2795 } | |
| 2796 | |
| 2797 static Range* UnknownSmi() { | |
| 2798 return new Range(RangeBoundary::MinSmi(), | |
| 2799 RangeBoundary::MaxSmi()); | |
| 2800 } | |
| 2801 | |
| 2802 void PrintTo(BufferFormatter* f) const; | |
| 2803 static const char* ToCString(const Range* range); | |
| 2804 | |
| 2805 const RangeBoundary& min() const { return min_; } | |
| 2806 const RangeBoundary& max() const { return max_; } | |
| 2807 | |
| 2808 static RangeBoundary ConstantMinSmi(const Range* range) { | |
| 2809 if (range == NULL) { | |
| 2810 return RangeBoundary::MinSmi(); | |
| 2811 } | |
| 2812 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundarySmi); | |
| 2813 } | |
| 2814 | |
| 2815 static RangeBoundary ConstantMaxSmi(const Range* range) { | |
| 2816 if (range == NULL) { | |
| 2817 return RangeBoundary::MaxSmi(); | |
| 2818 } | |
| 2819 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundarySmi); | |
| 2820 } | |
| 2821 | |
| 2822 static RangeBoundary ConstantMin(const Range* range) { | |
| 2823 if (range == NULL) { | |
| 2824 return RangeBoundary::MinConstant(); | |
| 2825 } | |
| 2826 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundaryInt64); | |
| 2827 } | |
| 2828 | |
| 2829 static RangeBoundary ConstantMax(const Range* range) { | |
| 2830 if (range == NULL) { | |
| 2831 return RangeBoundary::MaxConstant(); | |
| 2832 } | |
| 2833 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundaryInt64); | |
| 2834 } | |
| 2835 | |
| 2836 // [0, +inf] | |
| 2837 bool IsPositive() const; | |
| 2838 | |
| 2839 // [-inf, val]. | |
| 2840 bool OnlyLessThanOrEqualTo(int64_t val) const; | |
| 2841 | |
| 2842 // [val, +inf]. | |
| 2843 bool OnlyGreaterThanOrEqualTo(int64_t val) const; | |
| 2844 | |
| 2845 // Inclusive. | |
| 2846 bool IsWithin(int64_t min_int, int64_t max_int) const; | |
| 2847 | |
| 2848 // Inclusive. | |
| 2849 bool Overlaps(int64_t min_int, int64_t max_int) const; | |
| 2850 | |
| 2851 bool IsUnsatisfiable() const; | |
| 2852 | |
| 2853 bool IsFinite() const { | |
| 2854 return !min_.IsInfinity() && !max_.IsInfinity(); | |
| 2855 } | |
| 2856 | |
| 2857 // Clamp this to be within size. | |
| 2858 void Clamp(RangeBoundary::RangeSize size); | |
| 2859 | |
| 2860 static void Add(const Range* left_range, | |
| 2861 const Range* right_range, | |
| 2862 RangeBoundary* min, | |
| 2863 RangeBoundary* max, | |
| 2864 Definition* left_defn); | |
| 2865 | |
| 2866 static void Sub(const Range* left_range, | |
| 2867 const Range* right_range, | |
| 2868 RangeBoundary* min, | |
| 2869 RangeBoundary* max, | |
| 2870 Definition* left_defn); | |
| 2871 | |
| 2872 static bool Mul(const Range* left_range, | |
| 2873 const Range* right_range, | |
| 2874 RangeBoundary* min, | |
| 2875 RangeBoundary* max); | |
| 2876 static void Shr(const Range* left_range, | |
| 2877 const Range* right_range, | |
| 2878 RangeBoundary* min, | |
| 2879 RangeBoundary* max); | |
| 2880 | |
| 2881 static void Shl(const Range* left_range, | |
| 2882 const Range* right_range, | |
| 2883 RangeBoundary* min, | |
| 2884 RangeBoundary* max); | |
| 2885 | |
| 2886 static bool And(const Range* left_range, | |
| 2887 const Range* right_range, | |
| 2888 RangeBoundary* min, | |
| 2889 RangeBoundary* max); | |
| 2890 | |
| 2891 | |
| 2892 // Both the a and b ranges are >= 0. | |
| 2893 static bool OnlyPositiveOrZero(const Range& a, const Range& b); | |
| 2894 | |
| 2895 // Both the a and b ranges are <= 0. | |
| 2896 static bool OnlyNegativeOrZero(const Range& a, const Range& b); | |
| 2897 | |
| 2898 // Return the maximum absolute value included in range. | |
| 2899 static int64_t ConstantAbsMax(const Range* range); | |
| 2900 | |
| 2901 static Range* BinaryOp(const Token::Kind op, | |
| 2902 const Range* left_range, | |
| 2903 const Range* right_range, | |
| 2904 Definition* left_defn); | |
| 2905 | |
| 2906 private: | |
| 2907 RangeBoundary min_; | |
| 2908 RangeBoundary max_; | |
| 2909 }; | |
| 2910 | |
| 2911 | |
| 2912 class ConstraintInstr : public TemplateDefinition<2> { | 2567 class ConstraintInstr : public TemplateDefinition<2> { |
| 2913 public: | 2568 public: |
| 2914 ConstraintInstr(Value* value, Range* constraint) | 2569 ConstraintInstr(Value* value, Range* constraint) |
| 2915 : constraint_(constraint), | 2570 : constraint_(constraint), |
| 2916 target_(NULL) { | 2571 target_(NULL) { |
| 2917 SetInputAt(0, value); | 2572 SetInputAt(0, value); |
| 2918 } | 2573 } |
| 2919 | 2574 |
| 2920 DECLARE_INSTRUCTION(Constraint) | 2575 DECLARE_INSTRUCTION(Constraint) |
| 2921 | 2576 |
| (...skipping 5157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8079 | 7734 |
| 8080 Value* length() const { return inputs_[kLengthPos]; } | 7735 Value* length() const { return inputs_[kLengthPos]; } |
| 8081 Value* index() const { return inputs_[kIndexPos]; } | 7736 Value* index() const { return inputs_[kIndexPos]; } |
| 8082 | 7737 |
| 8083 DECLARE_INSTRUCTION(CheckArrayBound) | 7738 DECLARE_INSTRUCTION(CheckArrayBound) |
| 8084 | 7739 |
| 8085 virtual intptr_t ArgumentCount() const { return 0; } | 7740 virtual intptr_t ArgumentCount() const { return 0; } |
| 8086 | 7741 |
| 8087 virtual bool CanDeoptimize() const { return true; } | 7742 virtual bool CanDeoptimize() const { return true; } |
| 8088 | 7743 |
| 8089 bool IsRedundant(RangeBoundary length); | 7744 bool IsRedundant(const RangeBoundary& length); |
| 8090 | 7745 |
| 8091 virtual Instruction* Canonicalize(FlowGraph* flow_graph); | 7746 virtual Instruction* Canonicalize(FlowGraph* flow_graph); |
| 8092 | 7747 |
| 8093 // Returns the length offset for array and string types. | 7748 // Returns the length offset for array and string types. |
| 8094 static intptr_t LengthOffsetFor(intptr_t class_id); | 7749 static intptr_t LengthOffsetFor(intptr_t class_id); |
| 8095 | 7750 |
| 8096 static bool IsFixedLengthArrayType(intptr_t class_id); | 7751 static bool IsFixedLengthArrayType(intptr_t class_id); |
| 8097 | 7752 |
| 8098 virtual bool AllowsCSE() const { return true; } | 7753 virtual bool AllowsCSE() const { return true; } |
| 8099 virtual EffectSet Effects() const { return EffectSet::None(); } | 7754 virtual EffectSet Effects() const { return EffectSet::None(); } |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8629 ForwardInstructionIterator* current_iterator_; | 8284 ForwardInstructionIterator* current_iterator_; |
| 8630 | 8285 |
| 8631 private: | 8286 private: |
| 8632 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 8287 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 8633 }; | 8288 }; |
| 8634 | 8289 |
| 8635 | 8290 |
| 8636 } // namespace dart | 8291 } // namespace dart |
| 8637 | 8292 |
| 8638 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8293 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |