| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/flow_graph_range_analysis.h" | 5 #include "vm/flow_graph_range_analysis.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| (...skipping 2523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2534 ASSERT(right_range != NULL); | 2534 ASSERT(right_range != NULL); |
| 2535 ASSERT(result_min != NULL); | 2535 ASSERT(result_min != NULL); |
| 2536 ASSERT(result_max != NULL); | 2536 ASSERT(result_max != NULL); |
| 2537 | 2537 |
| 2538 const int64_t left_max = ConstantAbsMax(left_range); | 2538 const int64_t left_max = ConstantAbsMax(left_range); |
| 2539 const int64_t right_max = ConstantAbsMax(right_range); | 2539 const int64_t right_max = ConstantAbsMax(right_range); |
| 2540 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) && | 2540 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) && |
| 2541 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) { | 2541 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) { |
| 2542 // Product of left and right max values stays in 64 bit range. | 2542 // Product of left and right max values stays in 64 bit range. |
| 2543 const int64_t mul_max = left_max * right_max; | 2543 const int64_t mul_max = left_max * right_max; |
| 2544 const int64_t r_min = | 2544 if (OnlyPositiveOrZero(*left_range, *right_range) || |
| 2545 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -mul_max; | 2545 OnlyNegativeOrZero(*left_range, *right_range)) { |
| 2546 *result_min = RangeBoundary::FromConstant(r_min); | 2546 // If both ranges are of the same sign then the range of the result |
| 2547 const int64_t r_max = | 2547 // is positive and is between multiplications of absolute minimums |
| 2548 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : mul_max; | 2548 // and absolute maximums. |
| 2549 *result_max = RangeBoundary::FromConstant(r_max); | 2549 const int64_t mul_min = |
| 2550 ConstantAbsMin(left_range) * ConstantAbsMin(right_range); |
| 2551 *result_min = RangeBoundary::FromConstant(mul_min); |
| 2552 *result_max = RangeBoundary::FromConstant(mul_max); |
| 2553 } else { |
| 2554 // If ranges have mixed signs then use conservative approximation: |
| 2555 // absolute value of the result is less or equal to multiplication |
| 2556 // of absolute maximums. |
| 2557 *result_min = RangeBoundary::FromConstant(-mul_max); |
| 2558 *result_max = RangeBoundary::FromConstant(mul_max); |
| 2559 } |
| 2550 return; | 2560 return; |
| 2551 } | 2561 } |
| 2552 | 2562 |
| 2553 // TODO(vegorov): handle mixed sign case that leads to (-Infinity, 0] range. | 2563 // TODO(vegorov): handle mixed sign case that leads to (-Infinity, 0] range. |
| 2554 if (OnlyPositiveOrZero(*left_range, *right_range) || | 2564 if (OnlyPositiveOrZero(*left_range, *right_range) || |
| 2555 OnlyNegativeOrZero(*left_range, *right_range)) { | 2565 OnlyNegativeOrZero(*left_range, *right_range)) { |
| 2556 *result_min = RangeBoundary::FromConstant(0); | 2566 *result_min = RangeBoundary::FromConstant(0); |
| 2557 *result_max = RangeBoundary::PositiveInfinity(); | 2567 *result_max = RangeBoundary::PositiveInfinity(); |
| 2558 return; | 2568 return; |
| 2559 } | 2569 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2579 int64_t Range::ConstantAbsMax(const Range* range) { | 2589 int64_t Range::ConstantAbsMax(const Range* range) { |
| 2580 if (range == NULL) { | 2590 if (range == NULL) { |
| 2581 return RangeBoundary::kMax; | 2591 return RangeBoundary::kMax; |
| 2582 } | 2592 } |
| 2583 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); | 2593 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); |
| 2584 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); | 2594 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); |
| 2585 return Utils::Maximum(abs_min, abs_max); | 2595 return Utils::Maximum(abs_min, abs_max); |
| 2586 } | 2596 } |
| 2587 | 2597 |
| 2588 | 2598 |
| 2599 // Return the minimum absolute value included in range. |
| 2600 int64_t Range::ConstantAbsMin(const Range* range) { |
| 2601 if (range == NULL) { |
| 2602 return 0; |
| 2603 } |
| 2604 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); |
| 2605 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); |
| 2606 return Utils::Minimum(abs_min, abs_max); |
| 2607 } |
| 2608 |
| 2609 |
| 2589 void Range::BinaryOp(const Token::Kind op, | 2610 void Range::BinaryOp(const Token::Kind op, |
| 2590 const Range* left_range, | 2611 const Range* left_range, |
| 2591 const Range* right_range, | 2612 const Range* right_range, |
| 2592 Definition* left_defn, | 2613 Definition* left_defn, |
| 2593 Range* result) { | 2614 Range* result) { |
| 2594 ASSERT(left_range != NULL); | 2615 ASSERT(left_range != NULL); |
| 2595 ASSERT(right_range != NULL); | 2616 ASSERT(right_range != NULL); |
| 2596 | 2617 |
| 2597 // Both left and right ranges are finite. | 2618 // Both left and right ranges are finite. |
| 2598 ASSERT(left_range->IsFinite()); | 2619 ASSERT(left_range->IsFinite()); |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3143 } | 3164 } |
| 3144 } while (CanonicalizeMaxBoundary(&max) || | 3165 } while (CanonicalizeMaxBoundary(&max) || |
| 3145 CanonicalizeMinBoundary(&canonical_length)); | 3166 CanonicalizeMinBoundary(&canonical_length)); |
| 3146 | 3167 |
| 3147 // Failed to prove that maximum is bounded with array length. | 3168 // Failed to prove that maximum is bounded with array length. |
| 3148 return false; | 3169 return false; |
| 3149 } | 3170 } |
| 3150 | 3171 |
| 3151 | 3172 |
| 3152 } // namespace dart | 3173 } // namespace dart |
| OLD | NEW |