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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_nodes.dart

Issue 705023002: dart2js: Add a type parameter to class Reference in the CPS IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4
5 // IrNodes are kept in a separate library to have precise control over their 5 // IrNodes are kept in a separate library to have precise control over their
6 // dependencies on other parts of the system. 6 // dependencies on other parts of the system.
7 library dart2js.ir_nodes; 7 library dart2js.ir_nodes;
8 8
9 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
10 import '../constants/values.dart' as values show ConstantValue; 10 import '../constants/values.dart' as values show ConstantValue;
(...skipping 11 matching lines...) Expand all
22 22
23 accept(Visitor visitor); 23 accept(Visitor visitor);
24 } 24 }
25 25
26 abstract class Expression extends Node { 26 abstract class Expression extends Node {
27 Expression plug(Expression expr) => throw 'impossible'; 27 Expression plug(Expression expr) => throw 'impossible';
28 } 28 }
29 29
30 /// The base class of things that variables can refer to: primitives, 30 /// The base class of things that variables can refer to: primitives,
31 /// continuations, function and continuation parameters, etc. 31 /// continuations, function and continuation parameters, etc.
32 abstract class Definition extends Node { 32 abstract class Definition<T extends Definition<T>> extends Node {
Kevin Millikin (Google) 2014/11/06 10:35:50 Is T the canonical type variable name?
karlklose 2014/11/06 11:33:51 I think it is used in most Dart code. Some tests u
33 // The head of a linked-list of occurrences, in no particular order. 33 // The head of a linked-list of occurrences, in no particular order.
34 Reference firstRef = null; 34 Reference<T> firstRef;
35 35
36 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null; 36 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null;
37 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null; 37 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null;
38 bool get hasAtLeastOneUse => firstRef != null; 38 bool get hasAtLeastOneUse => firstRef != null;
39 bool get hasMultipleUses => !hasAtMostOneUse; 39 bool get hasMultipleUses => !hasAtMostOneUse;
40 40
41 void substituteFor(Definition other) { 41 void substituteFor(Definition other) {
42 if (other.firstRef == null) return; 42 if (other.firstRef == null) return;
43 Reference previous, current = other.firstRef; 43 Reference<T> previous, current = other.firstRef;
44 do { 44 do {
45 current.definition = this; 45 current.definition = this;
46 previous = current; 46 previous = current;
47 current = current.next; 47 current = current.next;
48 } while (current != null); 48 } while (current != null);
49 previous.next = firstRef; 49 previous.next = firstRef;
50 if (firstRef != null) firstRef.previous = previous; 50 if (firstRef != null) firstRef.previous = previous;
51 firstRef = other.firstRef; 51 firstRef = other.firstRef;
52 } 52 }
53 } 53 }
54 54
55 /// An expression that cannot throw or diverge and has no side-effects. 55 /// An expression that cannot throw or diverge and has no side-effects.
56 /// All primitives are named using the identity of the [Primitive] object. 56 /// All primitives are named using the identity of the [Primitive] object.
57 /// 57 ///
58 /// Primitives may allocate objects, this is not considered side-effect here. 58 /// Primitives may allocate objects, this is not considered side-effect here.
59 /// 59 ///
60 /// Although primitives may not mutate state, they may depend on state. 60 /// Although primitives may not mutate state, they may depend on state.
61 abstract class Primitive extends Definition { 61 abstract class Primitive extends Definition<Primitive> {
62 /// The [VariableElement] or [ParameterElement] from which the primitive 62 /// The [VariableElement] or [ParameterElement] from which the primitive
63 /// binding originated. 63 /// binding originated.
64 Element hint; 64 Element hint;
65 65
66 /// Register in which the variable binding this primitive can be allocated. 66 /// Register in which the variable binding this primitive can be allocated.
67 /// Separate register spaces are used for primitives with different [element]. 67 /// Separate register spaces are used for primitives with different [element].
68 /// Assigned by [RegisterAllocator], is null before that phase. 68 /// Assigned by [RegisterAllocator], is null before that phase.
69 int registerIndex; 69 int registerIndex;
70 70
71 /// Use the given element as a hint for naming this primitive. 71 /// Use the given element as a hint for naming this primitive.
72 /// 72 ///
73 /// Has no effect if this primitive already has a non-null [element]. 73 /// Has no effect if this primitive already has a non-null [element].
74 void useElementAsHint(Element hint) { 74 void useElementAsHint(Element hint) {
75 if (this.hint == null) { 75 if (this.hint == null) {
76 this.hint = hint; 76 this.hint = hint;
77 } 77 }
78 } 78 }
79 } 79 }
80 80
81 /// Operands to invocations and primitives are always variables. They point to 81 /// Operands to invocations and primitives are always variables. They point to
82 /// their definition and are doubly-linked into a list of occurrences. 82 /// their definition and are doubly-linked into a list of occurrences.
83 class Reference { 83 class Reference<T extends Definition<T>> {
84 Definition definition; 84 T definition;
85 Reference previous = null; 85 Reference<T> previous;
86 Reference next = null; 86 Reference<T> next;
87 87
88 /// A pointer to the parent node. Is null until set by optimization passes. 88 /// A pointer to the parent node. Is null until set by optimization passes.
89 Node parent; 89 Node parent;
90 90
91 Reference(this.definition) { 91 Reference(this.definition) {
92 next = definition.firstRef; 92 next = definition.firstRef;
93 if (next != null) next.previous = this; 93 if (next != null) next.previous = this;
94 definition.firstRef = this; 94 definition.firstRef = this;
95 } 95 }
96 96
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 Expression plug(Expression expr) { 139 Expression plug(Expression expr) {
140 assert(continuation != null && continuation.body == null); 140 assert(continuation != null && continuation.body == null);
141 return continuation.body = expr; 141 return continuation.body = expr;
142 } 142 }
143 143
144 accept(Visitor visitor) => visitor.visitLetCont(this); 144 accept(Visitor visitor) => visitor.visitLetCont(this);
145 } 145 }
146 146
147 abstract class Invoke { 147 abstract class Invoke {
148 Selector get selector; 148 Selector get selector;
149 List<Reference> get arguments; 149 List<Reference<Primitive>> get arguments;
150 } 150 }
151 151
152 /// Represents a node with a child node, which can be accessed through the 152 /// Represents a node with a child node, which can be accessed through the
153 /// `body` member. A typical usage is when removing a node from the CPS graph: 153 /// `body` member. A typical usage is when removing a node from the CPS graph:
154 /// 154 ///
155 /// Node child = node.body; 155 /// Node child = node.body;
156 /// InteriorNode parent = node.parent; 156 /// InteriorNode parent = node.parent;
157 /// 157 ///
158 /// child.parent = parent; 158 /// child.parent = parent;
159 /// parent.body = child; 159 /// parent.body = child;
160 abstract class InteriorNode implements Node { 160 abstract class InteriorNode implements Node {
161 Expression body; 161 Expression body;
162 } 162 }
163 163
164 /// Invoke a static function or static field getter/setter. 164 /// Invoke a static function or static field getter/setter.
165 class InvokeStatic extends Expression implements Invoke { 165 class InvokeStatic extends Expression implements Invoke {
166 /// [FunctionElement] or [FieldElement]. 166 /// [FunctionElement] or [FieldElement].
167 final Entity target; 167 final Entity target;
168 168
169 /** 169 /**
170 * The selector encodes how the function is invoked: number of positional 170 * The selector encodes how the function is invoked: number of positional
171 * arguments, names used in named arguments. This information is required 171 * arguments, names used in named arguments. This information is required
172 * to build the [StaticCallSiteTypeInformation] for the inference graph. 172 * to build the [StaticCallSiteTypeInformation] for the inference graph.
173 */ 173 */
174 final Selector selector; 174 final Selector selector;
175 175
176 final Reference continuation; 176 final Reference<Continuation> continuation;
177 final List<Reference> arguments; 177 final List<Reference<Primitive>> arguments;
178 178
179 InvokeStatic(this.target, this.selector, Continuation cont, 179 InvokeStatic(this.target, this.selector, Continuation cont,
180 List<Definition> args) 180 List<Primitive> args)
181 : continuation = new Reference(cont), 181 : continuation = new Reference<Continuation>(cont),
182 arguments = _referenceList(args) { 182 arguments = _referenceList(args) {
183 assert(target is ErroneousElement || selector.name == target.name); 183 assert(target is ErroneousElement || selector.name == target.name);
184 } 184 }
185 185
186 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 186 accept(Visitor visitor) => visitor.visitInvokeStatic(this);
187 } 187 }
188 188
189 /// Invoke a method, operator, getter, setter, or index getter/setter. 189 /// Invoke a method, operator, getter, setter, or index getter/setter.
190 /// Converting a method to a function object is treated as a getter invocation. 190 /// Converting a method to a function object is treated as a getter invocation.
191 class InvokeMethod extends Expression implements Invoke { 191 class InvokeMethod extends Expression implements Invoke {
192 final Reference receiver; 192 final Reference<Primitive> receiver;
193 final Selector selector; 193 final Selector selector;
194 final Reference continuation; 194 final Reference<Continuation> continuation;
195 final List<Reference> arguments; 195 final List<Reference<Primitive>> arguments;
196 196
197 InvokeMethod(Definition receiver, 197 InvokeMethod(Primitive receiver,
198 this.selector, 198 this.selector,
199 Continuation cont, 199 Continuation cont,
200 List<Definition> args) 200 List<Primitive> args)
201 : receiver = new Reference(receiver), 201 : receiver = new Reference<Primitive>(receiver),
202 continuation = new Reference(cont), 202 continuation = new Reference<Continuation>(cont),
203 arguments = _referenceList(args) { 203 arguments = _referenceList(args) {
204 assert(selector != null); 204 assert(selector != null);
205 assert(selector.kind == SelectorKind.CALL || 205 assert(selector.kind == SelectorKind.CALL ||
206 selector.kind == SelectorKind.OPERATOR || 206 selector.kind == SelectorKind.OPERATOR ||
207 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) || 207 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) ||
208 (selector.kind == SelectorKind.SETTER && arguments.length == 1) || 208 (selector.kind == SelectorKind.SETTER && arguments.length == 1) ||
209 (selector.kind == SelectorKind.INDEX && arguments.length == 1) || 209 (selector.kind == SelectorKind.INDEX && arguments.length == 1) ||
210 (selector.kind == SelectorKind.INDEX && arguments.length == 2)); 210 (selector.kind == SelectorKind.INDEX && arguments.length == 2));
211 } 211 }
212 212
213 accept(Visitor visitor) => visitor.visitInvokeMethod(this); 213 accept(Visitor visitor) => visitor.visitInvokeMethod(this);
214 } 214 }
215 215
216 /// Invoke a method, operator, getter, setter, or index getter/setter from the 216 /// Invoke a method, operator, getter, setter, or index getter/setter from the
217 /// super class in tail position. 217 /// super class in tail position.
218 class InvokeSuperMethod extends Expression implements Invoke { 218 class InvokeSuperMethod extends Expression implements Invoke {
219 final Selector selector; 219 final Selector selector;
220 final Reference continuation; 220 final Reference<Continuation> continuation;
221 final List<Reference> arguments; 221 final List<Reference<Primitive>> arguments;
222 222
223 InvokeSuperMethod(this.selector, 223 InvokeSuperMethod(this.selector,
224 Continuation cont, 224 Continuation cont,
225 List<Definition> args) 225 List<Primitive> args)
226 : continuation = new Reference(cont), 226 : continuation = new Reference<Continuation>(cont),
227 arguments = _referenceList(args) { 227 arguments = _referenceList(args) {
228 assert(selector != null); 228 assert(selector != null);
229 assert(selector.kind == SelectorKind.CALL || 229 assert(selector.kind == SelectorKind.CALL ||
230 selector.kind == SelectorKind.OPERATOR || 230 selector.kind == SelectorKind.OPERATOR ||
231 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) || 231 (selector.kind == SelectorKind.GETTER && arguments.isEmpty) ||
232 (selector.kind == SelectorKind.SETTER && arguments.length == 1) || 232 (selector.kind == SelectorKind.SETTER && arguments.length == 1) ||
233 (selector.kind == SelectorKind.INDEX && arguments.length == 1) || 233 (selector.kind == SelectorKind.INDEX && arguments.length == 1) ||
234 (selector.kind == SelectorKind.INDEX && arguments.length == 2)); 234 (selector.kind == SelectorKind.INDEX && arguments.length == 2));
235 } 235 }
236 236
237 accept(Visitor visitor) => visitor.visitInvokeSuperMethod(this); 237 accept(Visitor visitor) => visitor.visitInvokeSuperMethod(this);
238 } 238 }
239 239
240 /// Non-const call to a constructor. The [target] may be a generative 240 /// Non-const call to a constructor. The [target] may be a generative
241 /// constructor, factory, or redirecting factory. 241 /// constructor, factory, or redirecting factory.
242 class InvokeConstructor extends Expression implements Invoke { 242 class InvokeConstructor extends Expression implements Invoke {
243 final DartType type; 243 final DartType type;
244 final FunctionElement target; 244 final FunctionElement target;
245 final Reference continuation; 245 final Reference<Continuation> continuation;
246 final List<Reference> arguments; 246 final List<Reference<Primitive>> arguments;
247 final Selector selector; 247 final Selector selector;
248 248
249 /// The class being instantiated. This is the same as `target.enclosingClass` 249 /// The class being instantiated. This is the same as `target.enclosingClass`
250 /// and `type.element`. 250 /// and `type.element`.
251 ClassElement get targetClass => target.enclosingElement; 251 ClassElement get targetClass => target.enclosingElement;
252 252
253 /// True if this is an invocation of a factory constructor. 253 /// True if this is an invocation of a factory constructor.
254 bool get isFactory => target.isFactoryConstructor; 254 bool get isFactory => target.isFactoryConstructor;
255 255
256 InvokeConstructor(this.type, 256 InvokeConstructor(this.type,
257 this.target, 257 this.target,
258 this.selector, 258 this.selector,
259 Continuation cont, 259 Continuation cont,
260 List<Definition> args) 260 List<Primitive> args)
261 : continuation = new Reference(cont), 261 : continuation = new Reference<Continuation>(cont),
262 arguments = _referenceList(args) { 262 arguments = _referenceList(args) {
263 assert(dart2js.invariant(target, 263 assert(dart2js.invariant(target,
264 target.isErroneous || target.isConstructor, 264 target.isErroneous || target.isConstructor,
265 message: "Constructor invocation target is not a constructor: " 265 message: "Constructor invocation target is not a constructor: "
266 "$target.")); 266 "$target."));
267 assert(dart2js.invariant(target, 267 assert(dart2js.invariant(target,
268 target.isErroneous || 268 target.isErroneous ||
269 type.isDynamic || 269 type.isDynamic ||
270 type.element == target.enclosingClass.declaration, 270 type.element == target.enclosingClass.declaration,
271 message: "Constructor invocation type ${type} does not match enclosing " 271 message: "Constructor invocation type ${type} does not match enclosing "
(...skipping 23 matching lines...) Expand all
295 assert(isTypeTest != null); 295 assert(isTypeTest != null);
296 } 296 }
297 297
298 bool get isTypeCast => !isTypeTest; 298 bool get isTypeCast => !isTypeTest;
299 299
300 accept(Visitor visitor) => visitor.visitTypeOperator(this); 300 accept(Visitor visitor) => visitor.visitTypeOperator(this);
301 } 301 }
302 302
303 /// Invoke [toString] on each argument and concatenate the results. 303 /// Invoke [toString] on each argument and concatenate the results.
304 class ConcatenateStrings extends Expression { 304 class ConcatenateStrings extends Expression {
305 final Reference continuation; 305 final Reference<Continuation> continuation;
306 final List<Reference> arguments; 306 final List<Reference<Definition>> arguments;
307 307
308 ConcatenateStrings(Continuation cont, List<Definition> args) 308 ConcatenateStrings(Continuation cont, List<Primitive> args)
309 : continuation = new Reference(cont), 309 : continuation = new Reference<Continuation>(cont),
310 arguments = _referenceList(args); 310 arguments = _referenceList(args);
311 311
312 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); 312 accept(Visitor visitor) => visitor.visitConcatenateStrings(this);
313 } 313 }
314 314
315 /// Gets the value from a closure variable. The identity of the variable is 315 /// Gets the value from a closure variable. The identity of the variable is
316 /// determined by a [Local]. 316 /// determined by a [Local].
317 /// 317 ///
318 /// Closure variables can be seen as ref cells that are not first-class values. 318 /// Closure variables can be seen as ref cells that are not first-class values.
319 /// A [LetPrim] with a [GetClosureVariable] can then be seen as: 319 /// A [LetPrim] with a [GetClosureVariable] can then be seen as:
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 Parameter(Element element) { 521 Parameter(Element element) {
522 super.hint = element; 522 super.hint = element;
523 } 523 }
524 524
525 accept(Visitor visitor) => visitor.visitParameter(this); 525 accept(Visitor visitor) => visitor.visitParameter(this);
526 } 526 }
527 527
528 /// Continuations are normally bound by 'let cont'. A continuation with one 528 /// Continuations are normally bound by 'let cont'. A continuation with one
529 /// parameter and no body is used to represent a function's return continuation. 529 /// parameter and no body is used to represent a function's return continuation.
530 /// The return continuation is bound by the Function, not by 'let cont'. 530 /// The return continuation is bound by the Function, not by 'let cont'.
531 class Continuation extends Definition implements InteriorNode { 531 class Continuation extends Definition<Continuation> implements InteriorNode {
532 final List<Parameter> parameters; 532 final List<Parameter> parameters;
533 Expression body = null; 533 Expression body = null;
534 534
535 // A continuation is recursive if it has any recursive invocations. 535 // A continuation is recursive if it has any recursive invocations.
536 bool isRecursive = false; 536 bool isRecursive = false;
537 537
538 bool get isReturnContinuation => body == null; 538 bool get isReturnContinuation => body == null;
539 539
540 Continuation(this.parameters); 540 Continuation(this.parameters);
541 541
(...skipping 26 matching lines...) Expand all
568 568
569 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); 569 accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
570 570
571 /// Returns `true` if this function is abstract. 571 /// Returns `true` if this function is abstract.
572 /// 572 ///
573 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] 573 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants]
574 /// is empty. 574 /// is empty.
575 bool get isAbstract => body == null; 575 bool get isAbstract => body == null;
576 } 576 }
577 577
578 List<Reference> _referenceList(Iterable<Definition> definitions) { 578 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
579 return definitions.map((e) => new Reference(e)).toList(); 579 return definitions.map((e) => new Reference<Primitive>(e)).toList();
580 } 580 }
581 581
582 abstract class Visitor<T> { 582 abstract class Visitor<T> {
583 T visit(Node node) => node.accept(this); 583 T visit(Node node) => node.accept(this);
584 // Abstract classes. 584 // Abstract classes.
585 T visitNode(Node node) => null; 585 T visitNode(Node node) => null;
586 T visitExpression(Expression node) => visitNode(node); 586 T visitExpression(Expression node) => visitNode(node);
587 T visitDefinition(Definition node) => visitNode(node); 587 T visitDefinition(Definition node) => visitNode(node);
588 T visitPrimitive(Primitive node) => visitDefinition(node); 588 T visitPrimitive(Primitive node) => visitDefinition(node);
589 T visitCondition(Condition node) => visitNode(node); 589 T visitCondition(Condition node) => visitNode(node);
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 release(node.parameters[i]); 945 release(node.parameters[i]);
946 } 946 }
947 } 947 }
948 948
949 void visitIsTrue(IsTrue node) { 949 void visitIsTrue(IsTrue node) {
950 visitReference(node.value); 950 visitReference(node.value);
951 } 951 }
952 952
953 } 953 }
954 954
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698