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

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

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

Powered by Google App Engine
This is Rietveld 408576698