Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 11273111: Allow bound check elimination to eliminate checks when both array length and index boundaries are e… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Florian's comments Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698