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 2493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 value_(other.value_), | 2504 value_(other.value_), |
2505 offset_(other.offset_) { } | 2505 offset_(other.offset_) { } |
2506 | 2506 |
2507 RangeBoundary& operator=(const RangeBoundary& other) { | 2507 RangeBoundary& operator=(const RangeBoundary& other) { |
2508 kind_ = other.kind_; | 2508 kind_ = other.kind_; |
2509 value_ = other.value_; | 2509 value_ = other.value_; |
2510 offset_ = other.offset_; | 2510 offset_ = other.offset_; |
2511 return *this; | 2511 return *this; |
2512 } | 2512 } |
2513 | 2513 |
| 2514 static const intptr_t kMin = kIntptrMin; |
| 2515 static const intptr_t kMax = kIntptrMax; |
| 2516 |
| 2517 // Construct a RangeBoundary for a constant value. |
2514 static RangeBoundary FromConstant(intptr_t val) { | 2518 static RangeBoundary FromConstant(intptr_t val) { |
2515 return RangeBoundary(kConstant, val, 0); | 2519 return RangeBoundary(kConstant, val, 0); |
2516 } | 2520 } |
2517 | 2521 |
| 2522 // Construct a RangeBoundary for -inf. |
2518 static RangeBoundary NegativeInfinity() { | 2523 static RangeBoundary NegativeInfinity() { |
2519 return RangeBoundary(kNegativeInfinity, 0, 0); | 2524 return RangeBoundary(kNegativeInfinity, 0, 0); |
2520 } | 2525 } |
2521 | 2526 |
| 2527 // Construct a RangeBoundary for +inf. |
2522 static RangeBoundary PositiveInfinity() { | 2528 static RangeBoundary PositiveInfinity() { |
2523 return RangeBoundary(kPositiveInfinity, 0, 0); | 2529 return RangeBoundary(kPositiveInfinity, 0, 0); |
2524 } | 2530 } |
2525 | 2531 |
| 2532 // Construct a RangeBoundary from a definition and offset. |
2526 static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0); | 2533 static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0); |
2527 | 2534 |
| 2535 // Construct a RangeBoundary for the constant MinSmi value. |
2528 static RangeBoundary MinSmi() { | 2536 static RangeBoundary MinSmi() { |
2529 return FromConstant(Smi::kMinValue); | 2537 return FromConstant(Smi::kMinValue); |
2530 } | 2538 } |
2531 | 2539 |
| 2540 // Construct a RangeBoundary for the constant MaxSmi value. |
2532 static RangeBoundary MaxSmi() { | 2541 static RangeBoundary MaxSmi() { |
2533 return FromConstant(Smi::kMaxValue); | 2542 return FromConstant(Smi::kMaxValue); |
2534 } | 2543 } |
2535 | 2544 |
2536 static RangeBoundary Min(RangeBoundary a, RangeBoundary b); | 2545 static RangeBoundary Min(RangeBoundary a, RangeBoundary b); |
2537 | 2546 |
2538 static RangeBoundary Max(RangeBoundary a, RangeBoundary b); | 2547 static RangeBoundary Max(RangeBoundary a, RangeBoundary b); |
2539 | 2548 |
| 2549 // Returns true when this is a constant that is outside of range or is +/-inf. |
2540 bool Overflowed() const { | 2550 bool Overflowed() const { |
2541 // If the value is a constant outside of Smi range or infinity. | 2551 // TODO(johnmccutchan): Support overflow testing to non-smi ranges. |
2542 return (IsConstant() && !Smi::IsValid(value())) || IsInfinity(); | 2552 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); |
2543 } | 2553 } |
2544 | 2554 |
| 2555 // Clamps this into a representable constant or symbol RangeBoundary. |
| 2556 // +/- infinity are clamped to MinSmi/MaxSmi. |
2545 RangeBoundary Clamp() const { | 2557 RangeBoundary Clamp() const { |
| 2558 // TODO(johnmccutchan): Support clamping to non-smi ranges. |
2546 if (IsNegativeInfinity()) { | 2559 if (IsNegativeInfinity()) { |
2547 return MinSmi(); | 2560 return MinSmi(); |
2548 } else if (IsPositiveInfinity()) { | 2561 } |
| 2562 if (IsPositiveInfinity()) { |
2549 return MaxSmi(); | 2563 return MaxSmi(); |
2550 } else if (IsConstant()) { | 2564 } |
2551 if (value() < Smi::kMinValue) return MinSmi(); | 2565 if (IsConstant()) { |
2552 if (value() > Smi::kMaxValue) return MaxSmi(); | 2566 if (ConstantValue() < Smi::kMinValue) return MinSmi(); |
| 2567 if (ConstantValue() > Smi::kMaxValue) return MaxSmi(); |
2553 } | 2568 } |
2554 return *this; | 2569 return *this; |
2555 } | 2570 } |
2556 | 2571 |
| 2572 intptr_t kind() const { |
| 2573 return kind_; |
| 2574 } |
| 2575 |
| 2576 // Kind tests. |
2557 bool IsUnknown() const { return kind_ == kUnknown; } | 2577 bool IsUnknown() const { return kind_ == kUnknown; } |
2558 bool IsConstant() const { return kind_ == kConstant; } | 2578 bool IsConstant() const { return kind_ == kConstant; } |
2559 bool IsSymbol() const { return kind_ == kSymbol; } | 2579 bool IsSymbol() const { return kind_ == kSymbol; } |
2560 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } | 2580 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } |
2561 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } | 2581 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } |
2562 bool IsInfinity() const { | 2582 bool IsInfinity() const { |
2563 return IsNegativeInfinity() || IsPositiveInfinity(); | 2583 return IsNegativeInfinity() || IsPositiveInfinity(); |
2564 } | 2584 } |
2565 | 2585 bool IsConstantOrInfinity() const { |
2566 intptr_t value() const { | 2586 return IsConstant() || IsInfinity(); |
2567 ASSERT(IsConstant()); | |
2568 return value_; | |
2569 } | 2587 } |
2570 | 2588 |
| 2589 // Returns the value of a kConstant RangeBoundary. |
| 2590 intptr_t ConstantValue() const; |
| 2591 |
| 2592 // Returns the Definition associated with a kSymbol RangeBoundary. |
2571 Definition* symbol() const { | 2593 Definition* symbol() const { |
2572 ASSERT(IsSymbol()); | 2594 ASSERT(IsSymbol()); |
2573 return reinterpret_cast<Definition*>(value_); | 2595 return reinterpret_cast<Definition*>(value_); |
2574 } | 2596 } |
2575 | 2597 |
| 2598 // Offset from symbol. |
2576 intptr_t offset() const { | 2599 intptr_t offset() const { |
2577 return offset_; | 2600 return offset_; |
2578 } | 2601 } |
2579 | 2602 |
| 2603 // Computes the LowerBound of this. Three cases: |
| 2604 // IsInfinity() -> NegativeInfinity(). |
| 2605 // IsConstant() -> value(). |
| 2606 // IsSymbol() -> lower bound computed from definition + offset. |
2580 RangeBoundary LowerBound() const; | 2607 RangeBoundary LowerBound() const; |
| 2608 |
| 2609 // Computes the UpperBound of this. Three cases: |
| 2610 // IsInfinity() -> PositiveInfinity(). |
| 2611 // IsConstant() -> value(). |
| 2612 // IsSymbol() -> upper bound computed from definition + offset. |
2581 RangeBoundary UpperBound() const; | 2613 RangeBoundary UpperBound() const; |
2582 | 2614 |
2583 void PrintTo(BufferFormatter* f) const; | 2615 void PrintTo(BufferFormatter* f) const; |
2584 const char* ToCString() const; | 2616 const char* ToCString() const; |
2585 | 2617 |
2586 static RangeBoundary Add(const RangeBoundary& a, | 2618 static RangeBoundary Add(const RangeBoundary& a, |
2587 const RangeBoundary& b, | 2619 const RangeBoundary& b, |
2588 const RangeBoundary& overflow) { | 2620 const RangeBoundary& overflow); |
2589 ASSERT(a.IsConstant() && b.IsConstant()); | |
2590 | |
2591 intptr_t result = a.value() + b.value(); | |
2592 if (!Smi::IsValid(result)) { | |
2593 return overflow; | |
2594 } | |
2595 return RangeBoundary::FromConstant(result); | |
2596 } | |
2597 | 2621 |
2598 static RangeBoundary Sub(const RangeBoundary& a, | 2622 static RangeBoundary Sub(const RangeBoundary& a, |
2599 const RangeBoundary& b, | 2623 const RangeBoundary& b, |
2600 const RangeBoundary& overflow) { | 2624 const RangeBoundary& overflow); |
2601 ASSERT(a.IsConstant() && b.IsConstant()); | |
2602 | 2625 |
2603 intptr_t result = a.value() - b.value(); | 2626 // Attempts to calculate a + b when: |
2604 if (!Smi::IsValid(result)) { | 2627 // a is a symbol and b is a constant OR |
2605 return overflow; | 2628 // a is a constant and b is a symbol |
2606 } | 2629 // returns true if it succeeds, output is in result. |
2607 return RangeBoundary::FromConstant(result); | 2630 static bool SymbolicAdd(const RangeBoundary& a, |
2608 } | 2631 const RangeBoundary& b, |
| 2632 RangeBoundary* result); |
| 2633 |
| 2634 // Attempts to calculate a - b when: |
| 2635 // a is a symbol and b is a constant |
| 2636 // returns true if it succeeds, output is in result. |
| 2637 static bool SymbolicSub(const RangeBoundary& a, |
| 2638 const RangeBoundary& b, |
| 2639 RangeBoundary* result); |
| 2640 |
| 2641 bool Equals(const RangeBoundary& other) const; |
| 2642 |
| 2643 |
2609 | 2644 |
2610 private: | 2645 private: |
2611 RangeBoundary(Kind kind, intptr_t value, intptr_t offset) | 2646 RangeBoundary(Kind kind, intptr_t value, intptr_t offset) |
2612 : kind_(kind), value_(value), offset_(offset) { } | 2647 : kind_(kind), value_(value), offset_(offset) { } |
2613 | 2648 |
2614 Kind kind_; | 2649 Kind kind_; |
2615 intptr_t value_; | 2650 intptr_t value_; |
2616 intptr_t offset_; | 2651 intptr_t offset_; |
2617 }; | 2652 }; |
2618 | 2653 |
(...skipping 28 matching lines...) Expand all Loading... |
2647 | 2682 |
2648 // [0, +inf] | 2683 // [0, +inf] |
2649 bool IsPositive() const; | 2684 bool IsPositive() const; |
2650 | 2685 |
2651 // [-inf, 0) | 2686 // [-inf, 0) |
2652 bool IsNegative() const; | 2687 bool IsNegative() const; |
2653 | 2688 |
2654 // [-inf, val]. | 2689 // [-inf, val]. |
2655 bool OnlyLessThanOrEqualTo(intptr_t val) const; | 2690 bool OnlyLessThanOrEqualTo(intptr_t val) const; |
2656 | 2691 |
| 2692 // [val, +inf]. |
| 2693 bool OnlyGreaterThanOrEqualTo(intptr_t val) const; |
| 2694 |
2657 // Inclusive. | 2695 // Inclusive. |
2658 bool IsWithin(intptr_t min_int, intptr_t max_int) const; | 2696 bool IsWithin(intptr_t min_int, intptr_t max_int) const; |
2659 | 2697 |
2660 // Inclusive. | 2698 // Inclusive. |
2661 bool Overlaps(intptr_t min_int, intptr_t max_int) const; | 2699 bool Overlaps(intptr_t min_int, intptr_t max_int) const; |
2662 | 2700 |
2663 bool IsUnsatisfiable() const; | 2701 bool IsUnsatisfiable() const; |
2664 | 2702 |
| 2703 // Returns true if range is NULL or includes -inf. |
| 2704 static bool IncludesNegativeInfinity(const Range* range); |
| 2705 |
| 2706 // Returns true if range is NULL or includes +inf. |
| 2707 static bool IncludesPositiveInfinity(const Range* range); |
| 2708 |
| 2709 // Both the a and b ranges are >= 0. |
| 2710 static bool OnlyPositiveOrZero(const Range& a, const Range& b); |
| 2711 |
| 2712 // Both the a and b ranges are <= 0. |
| 2713 static bool OnlyNegativeOrZero(const Range& a, const Range& b); |
| 2714 |
| 2715 // Return the maximum absolute value included in range. |
| 2716 static int64_t ConstantAbsMax(const Range* range); |
| 2717 |
| 2718 static Range* BinaryOp(const Token::Kind op, |
| 2719 const RangeBoundary& left_min, |
| 2720 const RangeBoundary& left_max, |
| 2721 const Range* left_range, |
| 2722 const Range* right_range, |
| 2723 const Range* original_range); |
| 2724 |
2665 private: | 2725 private: |
2666 RangeBoundary min_; | 2726 RangeBoundary min_; |
2667 RangeBoundary max_; | 2727 RangeBoundary max_; |
2668 }; | 2728 }; |
2669 | 2729 |
2670 | 2730 |
2671 class ConstraintInstr : public TemplateDefinition<2> { | 2731 class ConstraintInstr : public TemplateDefinition<2> { |
2672 public: | 2732 public: |
2673 ConstraintInstr(Value* value, Range* constraint) | 2733 ConstraintInstr(Value* value, Range* constraint) |
2674 : constraint_(constraint), | 2734 : constraint_(constraint), |
(...skipping 5331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8006 ForwardInstructionIterator* current_iterator_; | 8066 ForwardInstructionIterator* current_iterator_; |
8007 | 8067 |
8008 private: | 8068 private: |
8009 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 8069 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
8010 }; | 8070 }; |
8011 | 8071 |
8012 | 8072 |
8013 } // namespace dart | 8073 } // namespace dart |
8014 | 8074 |
8015 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8075 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |