| 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 'cps_fragment.dart' show CpsFragment; | 7 import 'cps_fragment.dart' show CpsFragment; |
| 8 import 'cps_ir_nodes_sexpr.dart'; |
| 8 import '../constants/values.dart' as values; | 9 import '../constants/values.dart' as values; |
| 9 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
| 10 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
| 11 import '../io/source_information.dart' show SourceInformation; | 12 import '../io/source_information.dart' show SourceInformation; |
| 12 import '../types/types.dart' show TypeMask; | 13 import '../types/types.dart' show TypeMask; |
| 13 import '../universe/selector.dart' show Selector; | 14 import '../universe/selector.dart' show Selector; |
| 14 | 15 |
| 15 import 'builtin_operator.dart'; | 16 import 'builtin_operator.dart'; |
| 16 export 'builtin_operator.dart'; | 17 export 'builtin_operator.dart'; |
| 17 | 18 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 32 Node() { | 33 Node() { |
| 33 setParentPointers(); | 34 setParentPointers(); |
| 34 } | 35 } |
| 35 | 36 |
| 36 accept(Visitor visitor); | 37 accept(Visitor visitor); |
| 37 | 38 |
| 38 /// Updates the [parent] of the immediate children to refer to this node. | 39 /// Updates the [parent] of the immediate children to refer to this node. |
| 39 /// | 40 /// |
| 40 /// All constructors call this method to initialize parent pointers. | 41 /// All constructors call this method to initialize parent pointers. |
| 41 void setParentPointers(); | 42 void setParentPointers(); |
| 43 |
| 44 /// Returns the SExpression for the subtree rooted at this node. |
| 45 /// |
| 46 /// [annotations] maps strings to nodes and/or nodes to values that will be |
| 47 /// converted to strings. Each binding causes the annotation to appear on the |
| 48 /// given node. |
| 49 /// |
| 50 /// For example, the following could be used to diagnose a problem with nodes |
| 51 /// not appearing in an environment map: |
| 52 /// |
| 53 /// if (environment[node] == null) |
| 54 /// root.debugPrint({ |
| 55 /// 'currentNode': node, |
| 56 /// 'caller': someContinuation |
| 57 /// }); |
| 58 /// throw 'Node was not in environment'; |
| 59 /// } |
| 60 /// |
| 61 /// If two strings map to the same node, it will be given both annotations. |
| 62 /// |
| 63 /// Avoid using nodes as keys if there is a chance that two keys are the |
| 64 /// same node. |
| 65 String debugString([Map annotations]) { |
| 66 return new SExpressionStringifier() |
| 67 .withAnnotations(annotations).visit(this); |
| 68 } |
| 69 |
| 70 /// Prints the result of [debugString]. |
| 71 void debugPrint([Map annotations]) { |
| 72 print(debugString(annotations)); |
| 73 } |
| 42 } | 74 } |
| 43 | 75 |
| 44 /// Expressions can be evaluated, and may diverge, throw, and/or have | 76 /// Expressions can be evaluated, and may diverge, throw, and/or have |
| 45 /// side-effects. | 77 /// side-effects. |
| 46 /// | 78 /// |
| 47 /// Evaluation continues by stepping into a sub-expression, invoking a | 79 /// Evaluation continues by stepping into a sub-expression, invoking a |
| 48 /// continuation, or throwing an exception. | 80 /// continuation, or throwing an exception. |
| 49 /// | 81 /// |
| 50 /// Expressions do not a return value. Expressions that produce values should | 82 /// Expressions do not a return value. Expressions that produce values should |
| 51 /// invoke a [Continuation] with the result as argument. Alternatively, values | 83 /// invoke a [Continuation] with the result as argument. Alternatively, values |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 ref = ref.next; | 220 ref = ref.next; |
| 189 } else { | 221 } else { |
| 190 current = ref; | 222 current = ref; |
| 191 next = current.next; | 223 next = current.next; |
| 192 return true; | 224 return true; |
| 193 } | 225 } |
| 194 } | 226 } |
| 195 } | 227 } |
| 196 } | 228 } |
| 197 | 229 |
| 198 class EffectiveUseIterable extends IterableBase<Reference<Primitive>> { | 230 class RefinedUseIterable extends IterableBase<Reference<Primitive>> { |
| 199 Primitive primitive; | 231 Primitive primitive; |
| 200 EffectiveUseIterable(this.primitive); | 232 RefinedUseIterable(this.primitive); |
| 201 EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive); | 233 EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive); |
| 202 } | 234 } |
| 203 | 235 |
| 204 /// A named value. | 236 /// A named value. |
| 205 /// | 237 /// |
| 206 /// The identity of the [Primitive] object is the name of the value. | 238 /// The identity of the [Primitive] object is the name of the value. |
| 207 /// The subclass describes how to compute the value. | 239 /// The subclass describes how to compute the value. |
| 208 /// | 240 /// |
| 209 /// All primitives except [Parameter] must be bound by a [LetPrim]. | 241 /// All primitives except [Parameter] must be bound by a [LetPrim]. |
| 210 abstract class Primitive extends Variable<Primitive> { | 242 abstract class Primitive extends Variable<Primitive> { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 231 /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the | 263 /// If this is a [Refinement], [BoundsCheck] or [NullCheck] node, returns the |
| 232 /// value being refined, the indexable object being checked, or the value | 264 /// value being refined, the indexable object being checked, or the value |
| 233 /// that was checked to be non-null, respectively. | 265 /// that was checked to be non-null, respectively. |
| 234 /// | 266 /// |
| 235 /// Those instructions all return the corresponding operand directly, and | 267 /// Those instructions all return the corresponding operand directly, and |
| 236 /// this getter can be used to get (closer to) where the value came from. | 268 /// this getter can be used to get (closer to) where the value came from. |
| 237 // | 269 // |
| 238 // TODO(asgerf): Also do this for [TypeCast]? | 270 // TODO(asgerf): Also do this for [TypeCast]? |
| 239 Primitive get effectiveDefinition => this; | 271 Primitive get effectiveDefinition => this; |
| 240 | 272 |
| 273 /// Like [effectiveDefinition] but only unfolds [Refinement] nodes. |
| 274 Primitive get unrefined => this; |
| 275 |
| 241 /// True if the two primitives are (refinements of) the same value. | 276 /// True if the two primitives are (refinements of) the same value. |
| 242 bool sameValue(Primitive other) { | 277 bool sameValue(Primitive other) { |
| 243 return effectiveDefinition == other.effectiveDefinition; | 278 return effectiveDefinition == other.effectiveDefinition; |
| 244 } | 279 } |
| 245 | 280 |
| 246 /// Iterates all non-refinement uses of the primitive and all uses of | 281 /// Iterates all non-refinement uses of the primitive and all uses of |
| 247 /// a [Refinement] of this primitive (transitively). | 282 /// a [Refinement] of this primitive (transitively). |
| 248 /// | 283 /// |
| 249 /// Notes regarding concurrent modification: | 284 /// Notes regarding concurrent modification: |
| 250 /// - The current reference may safely be unlinked. | 285 /// - The current reference may safely be unlinked. |
| 251 /// - Yet unvisited references may not be unlinked. | 286 /// - Yet unvisited references may not be unlinked. |
| 252 /// - References to this primitive created during iteration will not be seen. | 287 /// - References to this primitive created during iteration will not be seen. |
| 253 /// - References to a refinement of this primitive may not be created during | 288 /// - References to a refinement of this primitive may not be created during |
| 254 /// iteration. | 289 /// iteration. |
| 255 EffectiveUseIterable get effectiveUses => new EffectiveUseIterable(this); | 290 RefinedUseIterable get refinedUses => new RefinedUseIterable(this); |
| 256 | 291 |
| 257 bool get hasMultipleEffectiveUses { | 292 bool get hasMultipleRefinedUses { |
| 258 Iterator it = effectiveUses.iterator; | 293 Iterator it = refinedUses.iterator; |
| 259 return it.moveNext() && it.moveNext(); | 294 return it.moveNext() && it.moveNext(); |
| 260 } | 295 } |
| 261 | 296 |
| 262 bool get hasNoEffectiveUses { | 297 bool get hasNoRefinedUses { |
| 263 return effectiveUses.isEmpty; | 298 return refinedUses.isEmpty; |
| 264 } | 299 } |
| 265 | 300 |
| 266 /// Unlinks all references contained in this node. | 301 /// Unlinks all references contained in this node. |
| 267 void destroy() { | 302 void destroy() { |
| 268 assert(hasNoUses); | 303 assert(hasNoUses); |
| 269 RemovalVisitor.remove(this); | 304 RemovalVisitor.remove(this); |
| 270 } | 305 } |
| 271 | 306 |
| 272 /// Replaces this definition, both at the binding site and at all uses sites. | 307 /// Replaces this definition, both at the binding site and at all uses sites. |
| 273 /// | 308 /// |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 : value = new Reference<Primitive>(value); | 762 : value = new Reference<Primitive>(value); |
| 728 | 763 |
| 729 bool get hasValue => true; | 764 bool get hasValue => true; |
| 730 bool get isSafeForElimination => false; | 765 bool get isSafeForElimination => false; |
| 731 bool get isSafeForReordering => false; | 766 bool get isSafeForReordering => false; |
| 732 | 767 |
| 733 accept(Visitor visitor) => visitor.visitRefinement(this); | 768 accept(Visitor visitor) => visitor.visitRefinement(this); |
| 734 | 769 |
| 735 Primitive get effectiveDefinition => value.definition.effectiveDefinition; | 770 Primitive get effectiveDefinition => value.definition.effectiveDefinition; |
| 736 | 771 |
| 772 Primitive get unrefined => value.definition.unrefined; |
| 773 |
| 737 void setParentPointers() { | 774 void setParentPointers() { |
| 738 value.parent = this; | 775 value.parent = this; |
| 739 } | 776 } |
| 740 } | 777 } |
| 741 | 778 |
| 742 /// Checks that [index] is a valid index on a given indexable [object]. | 779 /// Checks that [index] is a valid index on a given indexable [object]. |
| 743 /// | 780 /// |
| 744 /// Compiles to the following, with a subset of the conditions in the `if`: | 781 /// Compiles to the following, with a subset of the conditions in the `if`: |
| 745 /// | 782 /// |
| 746 /// if (index < 0 || index >= object.length || object.length === 0) | 783 /// if (index < 0 || index >= object.length || object.length === 0) |
| (...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 /// Continuations are normally bound by 'let cont'. A continuation with one | 1652 /// Continuations are normally bound by 'let cont'. A continuation with one |
| 1616 /// parameter and no body is used to represent a function's return continuation. | 1653 /// parameter and no body is used to represent a function's return continuation. |
| 1617 /// The return continuation is bound by the function, not by 'let cont'. | 1654 /// The return continuation is bound by the function, not by 'let cont'. |
| 1618 class Continuation extends Definition<Continuation> implements InteriorNode { | 1655 class Continuation extends Definition<Continuation> implements InteriorNode { |
| 1619 final List<Parameter> parameters; | 1656 final List<Parameter> parameters; |
| 1620 Expression body = null; | 1657 Expression body = null; |
| 1621 | 1658 |
| 1622 // A continuation is recursive if it has any recursive invocations. | 1659 // A continuation is recursive if it has any recursive invocations. |
| 1623 bool isRecursive; | 1660 bool isRecursive; |
| 1624 | 1661 |
| 1662 /// True if this is the return continuation. The return continuation is bound |
| 1663 /// by [FunctionDefinition]. |
| 1625 bool get isReturnContinuation => body == null; | 1664 bool get isReturnContinuation => body == null; |
| 1626 | 1665 |
| 1666 /// True if this is a branch continuation. Branch continuations are bound |
| 1667 /// by [LetCont] and can only have one use. |
| 1668 bool get isBranchContinuation => firstRef?.parent is Branch; |
| 1669 |
| 1670 /// True if this is the exception handler bound by a [LetHandler]. |
| 1671 bool get isHandlerContinuation => parent is LetHandler; |
| 1672 |
| 1673 /// True if this is a non-return continuation that can be targeted by |
| 1674 /// [InvokeContinuation]. |
| 1675 bool get isJoinContinuation { |
| 1676 return body != null && |
| 1677 parent is! LetHandler && |
| 1678 (firstRef == null || firstRef.parent is InvokeContinuation); |
| 1679 } |
| 1680 |
| 1627 Continuation(this.parameters, {this.isRecursive: false}); | 1681 Continuation(this.parameters, {this.isRecursive: false}); |
| 1628 | 1682 |
| 1629 Continuation.retrn() | 1683 Continuation.retrn() |
| 1630 : parameters = <Parameter>[new Parameter(null)], | 1684 : parameters = <Parameter>[new Parameter(null)], |
| 1631 isRecursive = false; | 1685 isRecursive = false; |
| 1632 | 1686 |
| 1633 accept(BlockVisitor visitor) => visitor.visitContinuation(this); | 1687 accept(BlockVisitor visitor) => visitor.visitContinuation(this); |
| 1634 | 1688 |
| 1635 void setParentPointers() { | 1689 void setParentPointers() { |
| 1636 _setParentsOnNodes(parameters, this); | 1690 _setParentsOnNodes(parameters, this); |
| (...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2787 plug(new Branch.loose(_definitions.getCopy(node.condition), | 2841 plug(new Branch.loose(_definitions.getCopy(node.condition), |
| 2788 _copies[node.trueContinuation.definition], | 2842 _copies[node.trueContinuation.definition], |
| 2789 _copies[node.falseContinuation.definition]) | 2843 _copies[node.falseContinuation.definition]) |
| 2790 ..isStrictCheck = node.isStrictCheck); | 2844 ..isStrictCheck = node.isStrictCheck); |
| 2791 } | 2845 } |
| 2792 | 2846 |
| 2793 visitUnreachable(Unreachable node) { | 2847 visitUnreachable(Unreachable node) { |
| 2794 plug(new Unreachable()); | 2848 plug(new Unreachable()); |
| 2795 } | 2849 } |
| 2796 } | 2850 } |
| OLD | NEW |