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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1512303002: dart2js cps: Add instruction for bounds checks. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update gvn_test output Created 5 years 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
OLDNEW
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 library dart2js.ir_nodes; 4 library dart2js.ir_nodes;
5 5
6 import 'dart:collection'; 6 import 'dart:collection';
7 import '../constants/values.dart' as values; 7 import '../constants/values.dart' as values;
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../io/source_information.dart' show SourceInformation; 10 import '../io/source_information.dart' show SourceInformation;
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 704
705 accept(Visitor visitor) => visitor.visitRefinement(this); 705 accept(Visitor visitor) => visitor.visitRefinement(this);
706 706
707 Primitive get effectiveDefinition => value.definition.effectiveDefinition; 707 Primitive get effectiveDefinition => value.definition.effectiveDefinition;
708 708
709 void setParentPointers() { 709 void setParentPointers() {
710 value.parent = this; 710 value.parent = this;
711 } 711 }
712 } 712 }
713 713
714 /// Checks that [index] is a valid index on a given indexable [object].
715 ///
716 /// Compiles to the following, with a subset of the conditions in the `if`:
717 ///
718 /// if (index < 0 || index >= object.length || object.length === 0)
719 /// ThrowIndexOutOfRangeException(object, index);
720 ///
721 /// [index] must be an integer, and [object] must refer to null or an indexable
722 /// object, and [length] must be the length of [object] at the time of the
723 /// check.
724 ///
725 /// Returns [object] so the bounds check can be used to restrict code motion.
726 /// It is possible to have a bounds check node that performs no checks but
727 /// is retained to restrict code motion.
728 ///
729 /// The [index] reference may be null if there are no checks to perform,
730 /// and the [length] reference may be null if there is no upper bound or
731 /// emptiness check.
732 ///
733 /// If a separate code motion guard for the index is required, e.g. because it
734 /// must be known to be non-negative in an operator that does not involve
735 /// [object], a [Refinement] can be created for it with the non-negative integer
736 /// type.
737 class BoundsCheck extends Primitive {
738 final Reference<Primitive> object;
739 Reference<Primitive> index;
740 Reference<Primitive> length; // FIXME write docs for length
741 int checks;
742 final SourceInformation sourceInformation;
743
744 /// If true, check that `index >= 0`.
745 bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0;
746
747 /// If true, check that `index < object.length`.
748 bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0;
749
750 /// If true, check that `object.length !== 0`.
751 ///
752 /// Equivalent to a lower bound check with `object.length - 1` as the index,
753 /// but this check is faster.
754 ///
755 /// Although [index] is not used in the condition, it is used to generate
756 /// the thrown error. Currently it is always `-1` for emptiness checks,
757 /// because that corresponds to `object.length - 1` in the error case.
758 bool get hasEmptinessCheck => checks & EMPTINESS != 0;
759
760 /// True if the [length] is needed to perform the check.
761 bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0;
762
763 bool get hasNoChecks => checks == NONE;
764
765 static const int UPPER_BOUND = 1 << 0;
766 static const int LOWER_BOUND = 1 << 1;
767 static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck].
768 static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND;
769 static const int NONE = 0;
770
771 BoundsCheck(Primitive object, Primitive index, Primitive length,
772 [this.checks = BOTH_BOUNDS, this.sourceInformation])
773 : this.object = new Reference<Primitive>(object),
774 this.index = new Reference<Primitive>(index),
775 this.length = new Reference<Primitive>(length);
776
777 BoundsCheck.noCheck(Primitive object, [this.sourceInformation])
778 : this.object = new Reference<Primitive>(object),
779 this.checks = NONE;
780
781 accept(Visitor visitor) => visitor.visitBoundsCheck(this);
782
783 void setParentPointers() {
784 object.parent = this;
785 if (index != null) {
786 index.parent = this;
787 }
788 if (length != null) {
789 length.parent = this;
790 }
791 }
792
793 String get checkString {
794 if (hasUpperBoundCheck && hasLowerBoundCheck) {
795 return 'upper-lower-checks';
796 } else if (hasUpperBoundCheck) {
797 return 'upper-check';
798 } else if (hasLowerBoundCheck) {
799 return 'lower-check';
800 } else if (hasEmptinessCheck) {
801 return 'emptiness-check';
802 } else {
803 return 'no-check';
804 }
805 }
806
807 bool get isSafeForElimination => checks == NONE;
808 bool get isSafeForReordering => false;
809 bool get hasValue => true; // Can be referenced to restrict code motion.
810
811 Primitive get effectiveDefinition => object.definition.effectiveDefinition;
812 }
813
714 /// Throw an exception if [value] is `null`. 814 /// Throw an exception if [value] is `null`.
715 /// 815 ///
716 /// Returns [value] so this can be used to restrict code motion. 816 /// Returns [value] so this can be used to restrict code motion.
717 /// 817 ///
718 /// In the simplest form this compiles to `value.toString;`. 818 /// In the simplest form this compiles to `value.toString;`.
719 /// 819 ///
720 /// If [selector] is set, `toString` is replaced with the (possibly minified) 820 /// If [selector] is set, `toString` is replaced with the (possibly minified)
721 /// invocation name of the selector. This can be shorter and generate a more 821 /// invocation name of the selector. This can be shorter and generate a more
722 /// meaningful error message, but is expensive if [value] is non-null and does 822 /// meaningful error message, but is expensive if [value] is non-null and does
723 /// not have that property at runtime. 823 /// not have that property at runtime.
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 T visitTypeExpression(TypeExpression node); 1880 T visitTypeExpression(TypeExpression node);
1781 T visitCreateInvocationMirror(CreateInvocationMirror node); 1881 T visitCreateInvocationMirror(CreateInvocationMirror node);
1782 T visitTypeTest(TypeTest node); 1882 T visitTypeTest(TypeTest node);
1783 T visitTypeTestViaFlag(TypeTestViaFlag node); 1883 T visitTypeTestViaFlag(TypeTestViaFlag node);
1784 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); 1884 T visitApplyBuiltinOperator(ApplyBuiltinOperator node);
1785 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); 1885 T visitApplyBuiltinMethod(ApplyBuiltinMethod node);
1786 T visitGetLength(GetLength node); 1886 T visitGetLength(GetLength node);
1787 T visitGetIndex(GetIndex node); 1887 T visitGetIndex(GetIndex node);
1788 T visitSetIndex(SetIndex node); 1888 T visitSetIndex(SetIndex node);
1789 T visitRefinement(Refinement node); 1889 T visitRefinement(Refinement node);
1890 T visitBoundsCheck(BoundsCheck node);
1790 T visitNullCheck(NullCheck node); 1891 T visitNullCheck(NullCheck node);
1791 1892
1792 // Support for literal foreign code. 1893 // Support for literal foreign code.
1793 T visitForeignCode(ForeignCode node); 1894 T visitForeignCode(ForeignCode node);
1794 } 1895 }
1795 1896
1796 /// Recursively visits all children of a CPS term. 1897 /// Recursively visits all children of a CPS term.
1797 /// 1898 ///
1798 /// The user of the class is responsible for avoiding stack overflows from 1899 /// The user of the class is responsible for avoiding stack overflows from
1799 /// deep recursion, e.g. by overriding methods to cut off recursion at certain 1900 /// deep recursion, e.g. by overriding methods to cut off recursion at certain
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
2100 processReference(node.index); 2201 processReference(node.index);
2101 processReference(node.value); 2202 processReference(node.value);
2102 } 2203 }
2103 2204
2104 processRefinement(Refinement node) {} 2205 processRefinement(Refinement node) {}
2105 visitRefinement(Refinement node) { 2206 visitRefinement(Refinement node) {
2106 processRefinement(node); 2207 processRefinement(node);
2107 processReference(node.value); 2208 processReference(node.value);
2108 } 2209 }
2109 2210
2211 processBoundsCheck(BoundsCheck node) {}
2212 visitBoundsCheck(BoundsCheck node) {
2213 processBoundsCheck(node);
2214 processReference(node.object);
2215 if (node.index != null) {
2216 processReference(node.index);
2217 }
2218 if (node.length != null) {
2219 processReference(node.length);
2220 }
2221 }
2222
2110 processNullCheck(NullCheck node) {} 2223 processNullCheck(NullCheck node) {}
2111 visitNullCheck(NullCheck node) { 2224 visitNullCheck(NullCheck node) {
2112 processNullCheck(node); 2225 processNullCheck(node);
2113 processReference(node.value); 2226 processReference(node.value);
2114 if (node.condition != null) { 2227 if (node.condition != null) {
2115 processReference(node.condition); 2228 processReference(node.condition);
2116 } 2229 }
2117 } 2230 }
2118 } 2231 }
2119 2232
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 2354 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
2242 class RemovalVisitor extends TrampolineRecursiveVisitor { 2355 class RemovalVisitor extends TrampolineRecursiveVisitor {
2243 processReference(Reference reference) { 2356 processReference(Reference reference) {
2244 reference.unlink(); 2357 reference.unlink();
2245 } 2358 }
2246 2359
2247 static void remove(Node node) { 2360 static void remove(Node node) {
2248 (new RemovalVisitor()).visit(node); 2361 (new RemovalVisitor()).visit(node);
2249 } 2362 }
2250 } 2363 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_fragment.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698