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 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 bool get isSafeForElimination; | 227 bool get isSafeForElimination; |
228 | 228 |
229 /// True if time-of-evaluation is irrelevant for the given primitive, | 229 /// True if time-of-evaluation is irrelevant for the given primitive, |
230 /// assuming its inputs are the same values. | 230 /// assuming its inputs are the same values. |
231 bool get isSafeForReordering; | 231 bool get isSafeForReordering; |
232 | 232 |
233 /// The source information associated with this primitive. | 233 /// The source information associated with this primitive. |
234 // TODO(johnniwinther): Require source information for all primitives. | 234 // TODO(johnniwinther): Require source information for all primitives. |
235 SourceInformation get sourceInformation => null; | 235 SourceInformation get sourceInformation => null; |
236 | 236 |
237 /// If this is a [Refinement] node, returns the value being refined. | 237 /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the |
| 238 /// value being refined, the indexable object being checked, or the value |
| 239 /// that was checked to be non-null, respectively. |
| 240 /// |
| 241 /// Those instructions all return the corresponding operand directly, and |
| 242 /// this getter can be used to get (closer to) where the value came from. |
| 243 // |
| 244 // TODO(asgerf): Also do this for [TypeCast]? |
238 Primitive get effectiveDefinition => this; | 245 Primitive get effectiveDefinition => this; |
239 | 246 |
240 /// True if the two primitives are (refinements of) the same value. | 247 /// True if the two primitives are (refinements of) the same value. |
241 bool sameValue(Primitive other) { | 248 bool sameValue(Primitive other) { |
242 return effectiveDefinition == other.effectiveDefinition; | 249 return effectiveDefinition == other.effectiveDefinition; |
243 } | 250 } |
244 | 251 |
245 /// Iterates all non-refinement uses of the primitive and all uses of | 252 /// Iterates all non-refinement uses of the primitive and all uses of |
246 /// a [Refinement] of this primitive (transitively). | 253 /// a [Refinement] of this primitive (transitively). |
247 /// | 254 /// |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 | 704 |
698 accept(Visitor visitor) => visitor.visitRefinement(this); | 705 accept(Visitor visitor) => visitor.visitRefinement(this); |
699 | 706 |
700 Primitive get effectiveDefinition => value.definition.effectiveDefinition; | 707 Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
701 | 708 |
702 void setParentPointers() { | 709 void setParentPointers() { |
703 value.parent = this; | 710 value.parent = this; |
704 } | 711 } |
705 } | 712 } |
706 | 713 |
| 714 /// Throw an exception if [value] is `null`. |
| 715 /// |
| 716 /// Returns [value] so this can be used to restrict code motion. |
| 717 /// |
| 718 /// In the simplest form this compiles to `value.toString;`. |
| 719 /// |
| 720 /// 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 |
| 722 /// meaningful error message, but is expensive if [value] is non-null and does |
| 723 /// not have that property at runtime. |
| 724 /// |
| 725 /// If [condition] is set, it is assumed that [condition] is true if and only |
| 726 /// if [value] is null. The check then compiles to: |
| 727 /// |
| 728 /// if (condition) value.toString; (or .selector if non-null) |
| 729 /// |
| 730 /// The latter form is useful when [condition] is a form understood by the JS |
| 731 /// runtime, such as a `typeof` test. |
| 732 class NullCheck extends Primitive { |
| 733 final Reference<Primitive> value; |
| 734 Selector selector; |
| 735 Reference<Primitive> condition; |
| 736 final SourceInformation sourceInformation; |
| 737 |
| 738 NullCheck(Primitive value, this.sourceInformation) |
| 739 : this.value = new Reference<Primitive>(value); |
| 740 |
| 741 NullCheck.guarded(Primitive condition, Primitive value, this.selector, |
| 742 this.sourceInformation) |
| 743 : this.condition = new Reference<Primitive>(condition), |
| 744 this.value = new Reference<Primitive>(value); |
| 745 |
| 746 bool get isSafeForElimination => false; |
| 747 bool get isSafeForReordering => false; |
| 748 bool get hasValue => true; |
| 749 |
| 750 accept(Visitor visitor) => visitor.visitNullCheck(this); |
| 751 |
| 752 void setParentPointers() { |
| 753 value.parent = this; |
| 754 if (condition != null) { |
| 755 condition.parent = this; |
| 756 } |
| 757 } |
| 758 |
| 759 Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
| 760 } |
| 761 |
707 /// An "is" type test. | 762 /// An "is" type test. |
708 /// | 763 /// |
709 /// Returns `true` if [value] is an instance of [type]. | 764 /// Returns `true` if [value] is an instance of [type]. |
710 /// | 765 /// |
711 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might | 766 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might |
712 /// be a type variable containing one of these types). This design is chosen | 767 /// be a type variable containing one of these types). This design is chosen |
713 /// to simplify code generation for type tests. | 768 /// to simplify code generation for type tests. |
714 class TypeTest extends Primitive { | 769 class TypeTest extends Primitive { |
715 Reference<Primitive> value; | 770 Reference<Primitive> value; |
716 final DartType dartType; | 771 final DartType dartType; |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 bool get isSafeForElimination => objectIsNotNull; | 1141 bool get isSafeForElimination => objectIsNotNull; |
1087 bool get isSafeForReordering => false; | 1142 bool get isSafeForReordering => false; |
1088 | 1143 |
1089 accept(Visitor v) => v.visitGetLength(this); | 1144 accept(Visitor v) => v.visitGetLength(this); |
1090 | 1145 |
1091 void setParentPointers() { | 1146 void setParentPointers() { |
1092 object.parent = this; | 1147 object.parent = this; |
1093 } | 1148 } |
1094 } | 1149 } |
1095 | 1150 |
1096 /// Read an entry from a string or native list. | 1151 /// Read an entry from an indexable object. |
1097 /// | 1152 /// |
1098 /// [object] must be null or a native list or a string, and [index] must be | 1153 /// [object] must be null or an indexable object, and [index] must be |
1099 /// an integer. | 1154 /// an integer where `0 <= index < object.length`. |
1100 class GetIndex extends Primitive { | 1155 class GetIndex extends Primitive { |
1101 final Reference<Primitive> object; | 1156 final Reference<Primitive> object; |
1102 final Reference<Primitive> index; | 1157 final Reference<Primitive> index; |
1103 | 1158 |
1104 /// True if the object is known not to be null. | 1159 /// True if the object is known not to be null. |
1105 bool objectIsNotNull = false; | 1160 bool objectIsNotNull = false; |
1106 | 1161 |
1107 GetIndex(Primitive object, Primitive index) | 1162 GetIndex(Primitive object, Primitive index) |
1108 : this.object = new Reference<Primitive>(object), | 1163 : this.object = new Reference<Primitive>(object), |
1109 this.index = new Reference<Primitive>(index); | 1164 this.index = new Reference<Primitive>(index); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 T visitTypeExpression(TypeExpression node); | 1780 T visitTypeExpression(TypeExpression node); |
1726 T visitCreateInvocationMirror(CreateInvocationMirror node); | 1781 T visitCreateInvocationMirror(CreateInvocationMirror node); |
1727 T visitTypeTest(TypeTest node); | 1782 T visitTypeTest(TypeTest node); |
1728 T visitTypeTestViaFlag(TypeTestViaFlag node); | 1783 T visitTypeTestViaFlag(TypeTestViaFlag node); |
1729 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); | 1784 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); |
1730 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); | 1785 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); |
1731 T visitGetLength(GetLength node); | 1786 T visitGetLength(GetLength node); |
1732 T visitGetIndex(GetIndex node); | 1787 T visitGetIndex(GetIndex node); |
1733 T visitSetIndex(SetIndex node); | 1788 T visitSetIndex(SetIndex node); |
1734 T visitRefinement(Refinement node); | 1789 T visitRefinement(Refinement node); |
| 1790 T visitNullCheck(NullCheck node); |
1735 | 1791 |
1736 // Support for literal foreign code. | 1792 // Support for literal foreign code. |
1737 T visitForeignCode(ForeignCode node); | 1793 T visitForeignCode(ForeignCode node); |
1738 } | 1794 } |
1739 | 1795 |
1740 /// Recursively visits all children of a CPS term. | 1796 /// Recursively visits all children of a CPS term. |
1741 /// | 1797 /// |
1742 /// The user of the class is responsible for avoiding stack overflows from | 1798 /// The user of the class is responsible for avoiding stack overflows from |
1743 /// deep recursion, e.g. by overriding methods to cut off recursion at certain | 1799 /// deep recursion, e.g. by overriding methods to cut off recursion at certain |
1744 /// points. | 1800 /// points. |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2043 processReference(node.object); | 2099 processReference(node.object); |
2044 processReference(node.index); | 2100 processReference(node.index); |
2045 processReference(node.value); | 2101 processReference(node.value); |
2046 } | 2102 } |
2047 | 2103 |
2048 processRefinement(Refinement node) {} | 2104 processRefinement(Refinement node) {} |
2049 visitRefinement(Refinement node) { | 2105 visitRefinement(Refinement node) { |
2050 processRefinement(node); | 2106 processRefinement(node); |
2051 processReference(node.value); | 2107 processReference(node.value); |
2052 } | 2108 } |
| 2109 |
| 2110 processNullCheck(NullCheck node) {} |
| 2111 visitNullCheck(NullCheck node) { |
| 2112 processNullCheck(node); |
| 2113 processReference(node.value); |
| 2114 if (node.condition != null) { |
| 2115 processReference(node.condition); |
| 2116 } |
| 2117 } |
2053 } | 2118 } |
2054 | 2119 |
2055 typedef void StackAction(); | 2120 typedef void StackAction(); |
2056 | 2121 |
2057 /// Calls `process*` for all nodes in a tree. | 2122 /// Calls `process*` for all nodes in a tree. |
2058 /// For simple usage, only override the `process*` methods. | 2123 /// For simple usage, only override the `process*` methods. |
2059 /// | 2124 /// |
2060 /// To avoid deep recursion, this class uses an "action stack" containing | 2125 /// To avoid deep recursion, this class uses an "action stack" containing |
2061 /// callbacks to be invoked after the processing of some term has finished. | 2126 /// callbacks to be invoked after the processing of some term has finished. |
2062 /// | 2127 /// |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2176 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 2241 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
2177 class RemovalVisitor extends TrampolineRecursiveVisitor { | 2242 class RemovalVisitor extends TrampolineRecursiveVisitor { |
2178 processReference(Reference reference) { | 2243 processReference(Reference reference) { |
2179 reference.unlink(); | 2244 reference.unlink(); |
2180 } | 2245 } |
2181 | 2246 |
2182 static void remove(Node node) { | 2247 static void remove(Node node) { |
2183 (new RemovalVisitor()).visit(node); | 2248 (new RemovalVisitor()).visit(node); |
2184 } | 2249 } |
2185 } | 2250 } |
OLD | NEW |