OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2114 | 2114 |
2115 RangeBoundary RangeBoundary::UpperBound() const { | 2115 RangeBoundary RangeBoundary::UpperBound() const { |
2116 if (IsConstant()) return *this; | 2116 if (IsConstant()) return *this; |
2117 if (symbol()->range() == NULL) return MaxSmi(); | 2117 if (symbol()->range() == NULL) return MaxSmi(); |
2118 return Add(symbol()->range()->max().UpperBound(), | 2118 return Add(symbol()->range()->max().UpperBound(), |
2119 RangeBoundary::FromConstant(offset_), | 2119 RangeBoundary::FromConstant(offset_), |
2120 MaxSmi()); | 2120 MaxSmi()); |
2121 } | 2121 } |
2122 | 2122 |
2123 | 2123 |
| 2124 static bool AreEqualDefinitions(Definition* a, Definition* b) { |
| 2125 return (a == b) || (!a->AffectedBySideEffect() && a->Equals(b)); |
| 2126 } |
| 2127 |
| 2128 |
2124 // Returns true if two range boundaries refer to the same symbol. | 2129 // Returns true if two range boundaries refer to the same symbol. |
2125 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { | 2130 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { |
2126 if (!a.IsSymbol() || !b.IsSymbol()) return false; | 2131 return a.IsSymbol() && b.IsSymbol() && |
2127 if (a.symbol() == b.symbol()) return true; | 2132 AreEqualDefinitions(a.symbol(), b.symbol()); |
2128 | |
2129 return !a.symbol()->AffectedBySideEffect() && | |
2130 a.symbol()->Equals(b.symbol()); | |
2131 } | 2133 } |
2132 | 2134 |
2133 | 2135 |
2134 // Returns true if range has a least specific minimum value. | 2136 // Returns true if range has a least specific minimum value. |
2135 static bool IsMinSmi(Range* range) { | 2137 static bool IsMinSmi(Range* range) { |
2136 return (range == NULL) || | 2138 return (range == NULL) || |
2137 (range->min().IsConstant() && | 2139 (range->min().IsConstant() && |
2138 (range->min().value() <= Smi::kMinValue)); | 2140 (range->min().value() <= Smi::kMinValue)); |
2139 } | 2141 } |
2140 | 2142 |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2446 | 2448 |
2447 | 2449 |
2448 static bool IsArrayLength(Definition* defn) { | 2450 static bool IsArrayLength(Definition* defn) { |
2449 LoadFieldInstr* load = defn->AsLoadField(); | 2451 LoadFieldInstr* load = defn->AsLoadField(); |
2450 return (load != NULL) && | 2452 return (load != NULL) && |
2451 ((load->recognized_kind() == MethodRecognizer::kObjectArrayLength) || | 2453 ((load->recognized_kind() == MethodRecognizer::kObjectArrayLength) || |
2452 (load->recognized_kind() == MethodRecognizer::kImmutableArrayLength)); | 2454 (load->recognized_kind() == MethodRecognizer::kImmutableArrayLength)); |
2453 } | 2455 } |
2454 | 2456 |
2455 | 2457 |
2456 static bool IsLengthOf(Definition* defn, Definition* array) { | |
2457 return IsArrayLength(defn) && | |
2458 (defn->AsLoadField()->value()->definition() == array); | |
2459 } | |
2460 | |
2461 | |
2462 void BinarySmiOpInstr::InferRange() { | 2458 void BinarySmiOpInstr::InferRange() { |
2463 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the | 2459 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the |
2464 // right and a non-constant on the left. | 2460 // right and a non-constant on the left. |
2465 Definition* left_defn = left()->definition(); | 2461 Definition* left_defn = left()->definition(); |
2466 | 2462 |
2467 Range* left_range = left_defn->range(); | 2463 Range* left_range = left_defn->range(); |
2468 Range* right_range = right()->definition()->range(); | 2464 Range* right_range = right()->definition()->range(); |
2469 | 2465 |
2470 if ((left_range == NULL) || (right_range == NULL)) { | 2466 if ((left_range == NULL) || (right_range == NULL)) { |
2471 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | 2467 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2527 ASSERT(!min.IsUnknown() && !max.IsUnknown()); | 2523 ASSERT(!min.IsUnknown() && !max.IsUnknown()); |
2528 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); | 2524 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); |
2529 | 2525 |
2530 if (min.IsConstant()) min.Clamp(); | 2526 if (min.IsConstant()) min.Clamp(); |
2531 if (max.IsConstant()) max.Clamp(); | 2527 if (max.IsConstant()) max.Clamp(); |
2532 | 2528 |
2533 range_ = new Range(min, max); | 2529 range_ = new Range(min, max); |
2534 } | 2530 } |
2535 | 2531 |
2536 | 2532 |
2537 bool CheckArrayBoundInstr::IsRedundant() { | 2533 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { |
2538 // Check that array has an immutable length. | 2534 // Check that array has an immutable length. |
2539 if ((array_type() != kArrayCid) && (array_type() != kImmutableArrayCid)) { | 2535 if ((array_type() != kArrayCid) && (array_type() != kImmutableArrayCid)) { |
2540 return false; | 2536 return false; |
2541 } | 2537 } |
2542 | 2538 |
2543 Range* index_range = index()->definition()->range(); | 2539 Range* index_range = index()->definition()->range(); |
2544 | 2540 |
2545 // Range of the index is unknown can't decide if the check is redundant. | 2541 // Range of the index is unknown can't decide if the check is redundant. |
2546 if (index_range == NULL) return false; | 2542 if (index_range == NULL) return false; |
2547 | 2543 |
2548 // Range of the index is not positive. Check can't be redundant. | 2544 // Range of the index is not positive. Check can't be redundant. |
2549 if (Range::ConstantMin(index_range).value() < 0) return false; | 2545 if (Range::ConstantMin(index_range).value() < 0) return false; |
2550 | 2546 |
2551 RangeBoundary max = CanonicalizeBoundary(index_range->max(), | 2547 RangeBoundary max = CanonicalizeBoundary(index_range->max(), |
2552 RangeBoundary::OverflowedMaxSmi()); | 2548 RangeBoundary::OverflowedMaxSmi()); |
| 2549 |
| 2550 if (max.Overflowed()) return false; |
| 2551 |
| 2552 // Try to compare constant boundaries. |
| 2553 if (max.UpperBound().value() < length.LowerBound().value()) { |
| 2554 return true; |
| 2555 } |
| 2556 |
| 2557 length = CanonicalizeBoundary(length, RangeBoundary::OverflowedMaxSmi()); |
| 2558 if (length.Overflowed()) return false; |
| 2559 |
| 2560 // Try symbolic comparison. |
2553 do { | 2561 do { |
2554 if (max.IsSymbol() && | 2562 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); |
2555 (max.offset() < 0) && | 2563 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); |
2556 IsLengthOf(max.symbol(), array()->definition())) { | |
2557 return true; | |
2558 } | |
2559 } while (CanonicalizeMaxBoundary(&max)); | |
2560 | 2564 |
2561 // Failed to prove that maximum is bounded with array length. | 2565 // Failed to prove that maximum is bounded with array length. |
2562 return false; | 2566 return false; |
2563 } | 2567 } |
2564 | 2568 |
2565 | 2569 |
2566 #undef __ | 2570 #undef __ |
2567 | 2571 |
2568 } // namespace dart | 2572 } // namespace dart |
OLD | NEW |