Chromium Code Reviews| 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 '../constants/values.dart' as values show ConstantValue; | 6 import '../constants/values.dart' as values show ConstantValue; |
| 7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../io/source_information.dart' show SourceInformation; | 9 import '../io/source_information.dart' show SourceInformation; |
| 10 import '../types/types.dart' show TypeMask; | 10 import '../types/types.dart' show TypeMask; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 previous = current; | 112 previous = current; |
| 113 current = current.next; | 113 current = current.next; |
| 114 } while (current != null); | 114 } while (current != null); |
| 115 previous.next = firstRef; | 115 previous.next = firstRef; |
| 116 if (firstRef != null) firstRef.previous = previous; | 116 if (firstRef != null) firstRef.previous = previous; |
| 117 firstRef = other.firstRef; | 117 firstRef = other.firstRef; |
| 118 other.firstRef = null; | 118 other.firstRef = null; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 | 121 |
| 122 class EffectiveUseIterator extends Iterator<Reference<Primitive>> { | |
| 123 Reference<Primitive> current; | |
| 124 Reference<Primitive> next; | |
| 125 final List<Primitive> stack = <Primitive>[]; | |
| 126 | |
| 127 EffectiveUseIterator(Primitive prim) : next = prim.firstRef; | |
| 128 | |
| 129 bool moveNext() { | |
| 130 Reference<Primitive> ref = next; | |
| 131 while (true) { | |
| 132 if (ref == null) { | |
| 133 if (stack.isNotEmpty) { | |
| 134 ref = stack.removeLast().firstRef; | |
| 135 } else { | |
| 136 return false; | |
| 137 } | |
| 138 } else if (ref.parent is Refinement) { | |
| 139 stack.add(ref.parent); | |
| 140 ref = ref.next; | |
| 141 } else { | |
| 142 current = ref; | |
| 143 next = current.next; | |
| 144 return true; | |
| 145 } | |
| 146 } | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 class EffectiveUseIterable { | |
| 151 Primitive primitive; | |
| 152 EffectiveUseIterable(this.primitive); | |
| 153 EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive); | |
| 154 } | |
| 155 | |
| 122 /// A named value. | 156 /// A named value. |
| 123 /// | 157 /// |
| 124 /// The identity of the [Primitive] object is the name of the value. | 158 /// The identity of the [Primitive] object is the name of the value. |
| 125 /// The subclass describes how to compute the value. | 159 /// The subclass describes how to compute the value. |
| 126 /// | 160 /// |
| 127 /// All primitives except [Parameter] must be bound by a [LetPrim]. | 161 /// All primitives except [Parameter] must be bound by a [LetPrim]. |
| 128 abstract class Primitive extends Definition<Primitive> { | 162 abstract class Primitive extends Definition<Primitive> { |
| 129 /// The [VariableElement] or [ParameterElement] from which the primitive | 163 /// The [VariableElement] or [ParameterElement] from which the primitive |
| 130 /// binding originated. | 164 /// binding originated. |
| 131 Entity hint; | 165 Entity hint; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 146 /// observable side-effects. | 180 /// observable side-effects. |
| 147 bool get isSafeForElimination; | 181 bool get isSafeForElimination; |
| 148 | 182 |
| 149 /// True if time-of-evaluation is irrelevant for the given primitive, | 183 /// True if time-of-evaluation is irrelevant for the given primitive, |
| 150 /// assuming its inputs are the same values. | 184 /// assuming its inputs are the same values. |
| 151 bool get isSafeForReordering; | 185 bool get isSafeForReordering; |
| 152 | 186 |
| 153 /// The source information associated with this primitive. | 187 /// The source information associated with this primitive. |
| 154 // TODO(johnniwinther): Require source information for all primitives. | 188 // TODO(johnniwinther): Require source information for all primitives. |
| 155 SourceInformation get sourceInformation => null; | 189 SourceInformation get sourceInformation => null; |
| 190 | |
| 191 /// If this is a [Refinement] node, returns the value being refined. | |
| 192 Primitive get effectiveDefinition => this; | |
| 193 | |
| 194 /// True if the two primitives are (refinements of) the same value. | |
| 195 bool sameValue(Primitive other) { | |
| 196 return effectiveDefinition == other.effectiveDefinition; | |
| 197 } | |
| 198 | |
| 199 /// Iterates all non-refinement uses of the primitive and all uses of | |
| 200 /// a [Refinement] of this primitive (transitively). | |
| 201 /// | |
| 202 /// Notes regarding concurrent modification: | |
| 203 /// - The current reference may safely be unlinked. | |
| 204 /// - Yet unvisited references may not be unlinked. | |
| 205 /// - References to this primitive created during iteration will not be seen. | |
| 206 /// - References to a refinement of this primitive may not be created during | |
| 207 /// iteration. | |
| 208 EffectiveUseIterable get effectiveUses => new EffectiveUseIterable(this); | |
| 209 | |
| 210 bool get hasMultipleEffectiveUses { | |
| 211 Iterator it = effectiveUses.iterator; | |
| 212 return it.moveNext() && it.moveNext(); | |
| 213 } | |
| 214 | |
| 215 bool get hasNoEffectiveUses { | |
| 216 return !effectiveUses.iterator.moveNext(); | |
|
sra1
2015/09/02 18:24:52
effectiveUses.isEmpty does the same.
asgerf
2015/09/02 18:46:58
I originally couldn't bother to import dart:collec
| |
| 217 } | |
| 156 } | 218 } |
| 157 | 219 |
| 158 /// Operands to invocations and primitives are always variables. They point to | 220 /// Operands to invocations and primitives are always variables. They point to |
| 159 /// their definition and are doubly-linked into a list of occurrences. | 221 /// their definition and are doubly-linked into a list of occurrences. |
| 160 class Reference<T extends Definition<T>> { | 222 class Reference<T extends Definition<T>> { |
| 161 T definition; | 223 T definition; |
| 162 Reference<T> previous; | 224 Reference<T> previous; |
| 163 Reference<T> next; | 225 Reference<T> next; |
| 164 | 226 |
| 165 /// A pointer to the parent node. Is null until set by optimization passes. | 227 /// A pointer to the parent node. Is null until set by optimization passes. |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 this.selector, | 494 this.selector, |
| 433 List<Primitive> args, | 495 List<Primitive> args, |
| 434 Continuation cont, | 496 Continuation cont, |
| 435 this.sourceInformation) | 497 this.sourceInformation) |
| 436 : arguments = _referenceList(args), | 498 : arguments = _referenceList(args), |
| 437 continuation = new Reference<Continuation>(cont); | 499 continuation = new Reference<Continuation>(cont); |
| 438 | 500 |
| 439 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 501 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
| 440 } | 502 } |
| 441 | 503 |
| 504 /// An alias for [value] in a context where the value is known to satisfy | |
| 505 /// [type]. | |
| 506 /// | |
| 507 /// Refinement nodes are inserted before the type propagator pass and removed | |
| 508 /// afterwards, so as not to complicate passes that don't reason about types, | |
| 509 /// but need to reason about value references being identical (i.e. referring | |
| 510 /// to the same primitive). | |
| 511 class Refinement extends Primitive { | |
| 512 Reference<Primitive> value; | |
| 513 final TypeMask type; | |
| 514 | |
| 515 Refinement(Primitive value, this.type) | |
| 516 : value = new Reference<Primitive>(value); | |
| 517 | |
| 518 bool get isSafeForElimination => true; | |
| 519 bool get isSafeForReordering => false; | |
|
sra1
2015/09/02 18:24:52
Is this adequate to keep it in order with respect
asgerf
2015/09/02 18:46:58
Yes, but we might need the witness reference when
| |
| 520 | |
| 521 accept(Visitor visitor) => visitor.visitRefinement(this); | |
| 522 | |
| 523 Primitive get effectiveDefinition => value.definition.effectiveDefinition; | |
| 524 } | |
| 525 | |
| 442 /// An "is" type test. | 526 /// An "is" type test. |
| 443 /// | 527 /// |
| 444 /// Returns `true` if [value] is an instance of [type]. | 528 /// Returns `true` if [value] is an instance of [type]. |
| 445 /// | 529 /// |
| 446 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might | 530 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might |
| 447 /// be a type variable containing one of these types). This design is chosen | 531 /// be a type variable containing one of these types). This design is chosen |
| 448 /// to simplify code generation for type tests. | 532 /// to simplify code generation for type tests. |
| 449 class TypeTest extends Primitive { | 533 class TypeTest extends Primitive { |
| 450 Reference<Primitive> value; | 534 Reference<Primitive> value; |
| 451 final DartType type; | 535 final DartType type; |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1194 T visitReifyRuntimeType(ReifyRuntimeType node); | 1278 T visitReifyRuntimeType(ReifyRuntimeType node); |
| 1195 T visitReadTypeVariable(ReadTypeVariable node); | 1279 T visitReadTypeVariable(ReadTypeVariable node); |
| 1196 T visitTypeExpression(TypeExpression node); | 1280 T visitTypeExpression(TypeExpression node); |
| 1197 T visitCreateInvocationMirror(CreateInvocationMirror node); | 1281 T visitCreateInvocationMirror(CreateInvocationMirror node); |
| 1198 T visitTypeTest(TypeTest node); | 1282 T visitTypeTest(TypeTest node); |
| 1199 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); | 1283 T visitApplyBuiltinOperator(ApplyBuiltinOperator node); |
| 1200 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); | 1284 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); |
| 1201 T visitGetLength(GetLength node); | 1285 T visitGetLength(GetLength node); |
| 1202 T visitGetIndex(GetIndex node); | 1286 T visitGetIndex(GetIndex node); |
| 1203 T visitSetIndex(SetIndex node); | 1287 T visitSetIndex(SetIndex node); |
| 1288 T visitRefinement(Refinement node); | |
| 1204 | 1289 |
| 1205 // Support for literal foreign code. | 1290 // Support for literal foreign code. |
| 1206 T visitForeignCode(ForeignCode node); | 1291 T visitForeignCode(ForeignCode node); |
| 1207 } | 1292 } |
| 1208 | 1293 |
| 1209 /// Visits all non-recursive children of a CPS term, i.e. anything | 1294 /// Visits all non-recursive children of a CPS term, i.e. anything |
| 1210 /// not of type [Expression] or [Continuation]. | 1295 /// not of type [Expression] or [Continuation]. |
| 1211 /// | 1296 /// |
| 1212 /// The `process*` methods are called in pre-order for every node visited. | 1297 /// The `process*` methods are called in pre-order for every node visited. |
| 1213 /// These can be overridden without disrupting the visitor traversal. | 1298 /// These can be overridden without disrupting the visitor traversal. |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 processReference(node.index); | 1582 processReference(node.index); |
| 1498 } | 1583 } |
| 1499 | 1584 |
| 1500 processSetIndex(SetIndex node) {} | 1585 processSetIndex(SetIndex node) {} |
| 1501 visitSetIndex(SetIndex node) { | 1586 visitSetIndex(SetIndex node) { |
| 1502 processSetIndex(node); | 1587 processSetIndex(node); |
| 1503 processReference(node.object); | 1588 processReference(node.object); |
| 1504 processReference(node.index); | 1589 processReference(node.index); |
| 1505 processReference(node.value); | 1590 processReference(node.value); |
| 1506 } | 1591 } |
| 1592 | |
| 1593 processRefinement(Refinement node) {} | |
| 1594 visitRefinement(Refinement node) { | |
| 1595 processRefinement(node); | |
| 1596 processReference(node.value); | |
| 1597 } | |
| 1507 } | 1598 } |
| 1508 | 1599 |
| 1509 typedef void StackAction(); | 1600 typedef void StackAction(); |
| 1510 | 1601 |
| 1511 /// Calls `process*` for all nodes in a tree. | 1602 /// Calls `process*` for all nodes in a tree. |
| 1512 /// For simple usage, only override the `process*` methods. | 1603 /// For simple usage, only override the `process*` methods. |
| 1513 /// | 1604 /// |
| 1514 /// To avoid deep recursion, this class uses an "action stack" containing | 1605 /// To avoid deep recursion, this class uses an "action stack" containing |
| 1515 /// callbacks to be invoked after the processing of some term has finished. | 1606 /// callbacks to be invoked after the processing of some term has finished. |
| 1516 /// | 1607 /// |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1628 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 1719 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 1629 class RemovalVisitor extends RecursiveVisitor { | 1720 class RemovalVisitor extends RecursiveVisitor { |
| 1630 processReference(Reference reference) { | 1721 processReference(Reference reference) { |
| 1631 reference.unlink(); | 1722 reference.unlink(); |
| 1632 } | 1723 } |
| 1633 | 1724 |
| 1634 static void remove(Node node) { | 1725 static void remove(Node node) { |
| 1635 (new RemovalVisitor()).visit(node); | 1726 (new RemovalVisitor()).visit(node); |
| 1636 } | 1727 } |
| 1637 } | 1728 } |
| OLD | NEW |