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

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

Issue 1234753003: dart2js cps: Rewrite mutable variables to continuation parameters. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Add tests and fix an assertion Created 5 years, 5 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 '../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 18 matching lines...) Expand all
29 /// Expressions can be evaluated, and may diverge, throw, and/or have 29 /// Expressions can be evaluated, and may diverge, throw, and/or have
30 /// side-effects. 30 /// side-effects.
31 /// 31 ///
32 /// Evaluation continues by stepping into a sub-expression, invoking a 32 /// Evaluation continues by stepping into a sub-expression, invoking a
33 /// continuation, or throwing an exception. 33 /// continuation, or throwing an exception.
34 /// 34 ///
35 /// Expressions do not a return value. Expressions that produce values should 35 /// Expressions do not a return value. Expressions that produce values should
36 /// invoke a [Continuation] with the result as argument. Alternatively, values 36 /// invoke a [Continuation] with the result as argument. Alternatively, values
37 /// that can be obtained without side-effects, divergence, or throwing 37 /// that can be obtained without side-effects, divergence, or throwing
38 /// exceptions can be built using a [LetPrim]. 38 /// exceptions can be built using a [LetPrim].
39 ///
40 /// All subclasses implement exactly one of [CallExpression],
41 /// [InteriorExpression], or [TailExpression].
39 abstract class Expression extends Node { 42 abstract class Expression extends Node {
40 InteriorNode get parent; // Only InteriorNodes may contain expressions. 43 InteriorNode get parent; // Only InteriorNodes may contain expressions.
41 44
42 Expression plug(Expression expr) => throw 'impossible'; 45 Expression plug(Expression expr) => throw 'impossible';
46
47 /// The next expression in the basic block.
48 ///
49 /// For [InteriorExpression]s this is the body, for [CallExpressions] it is
50 /// the body of the continuation, and for [TailExpressions] it is `null`.
51 Expression get next;
52 }
53
54 /// Represents a node with a child node, which can be accessed through the
55 /// `body` member. A typical usage is when removing a node from the CPS graph:
56 ///
57 /// Node child = node.body;
58 /// InteriorNode parent = node.parent;
59 ///
60 /// child.parent = parent;
61 /// parent.body = child;
62 abstract class InteriorNode extends Node {
63 Expression get body;
64 void set body(Expression body);
65 }
66
67 /// An expression with a subexpression as body.
68 abstract class InteriorExpression extends Expression implements InteriorNode {
69 Expression get next => body;
70 }
71
72 /// An expression that passes a continuation to a call.
73 abstract class CallExpression extends Expression {
74 Reference<Continuation> get continuation;
75 Expression get next => continuation.definition.body;
76 }
77
78 /// An expression without a continuation or a subexpression body.
79 ///
80 /// These break straight-line control flow and can be throught of as ending a
81 /// basic block.
82 abstract class TailExpression extends Expression {
83 Expression get next => null;
43 } 84 }
44 85
45 /// The base class of things that variables can refer to: primitives, 86 /// The base class of things that variables can refer to: primitives,
46 /// continuations, function and continuation parameters, etc. 87 /// continuations, function and continuation parameters, etc.
47 abstract class Definition<T extends Definition<T>> extends Node { 88 abstract class Definition<T extends Definition<T>> extends Node {
48 // The head of a linked-list of occurrences, in no particular order. 89 // The head of a linked-list of occurrences, in no particular order.
49 Reference<T> firstRef; 90 Reference<T> firstRef;
50 91
51 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null; 92 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null;
52 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null; 93 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 definition.firstRef = this; 181 definition.firstRef = this;
141 } 182 }
142 } 183 }
143 184
144 /// Evaluates a primitive and binds it to variable: `let val x = V in E`. 185 /// Evaluates a primitive and binds it to variable: `let val x = V in E`.
145 /// 186 ///
146 /// The bound value is in scope in the body. 187 /// The bound value is in scope in the body.
147 /// 188 ///
148 /// During one-pass construction a LetPrim with an empty body is used to 189 /// During one-pass construction a LetPrim with an empty body is used to
149 /// represent the one-hole context `let val x = V in []`. 190 /// represent the one-hole context `let val x = V in []`.
150 class LetPrim extends Expression implements InteriorNode { 191 class LetPrim extends InteriorExpression {
151 Primitive primitive; 192 Primitive primitive;
152 Expression body; 193 Expression body;
153 194
154 LetPrim(this.primitive, [this.body = null]); 195 LetPrim(this.primitive, [this.body = null]);
155 196
156 Expression plug(Expression expr) { 197 Expression plug(Expression expr) {
157 assert(body == null); 198 assert(body == null);
158 return body = expr; 199 return body = expr;
159 } 200 }
160 201
161 accept(Visitor visitor) => visitor.visitLetPrim(this); 202 accept(Visitor visitor) => visitor.visitLetPrim(this);
162 } 203 }
163 204
164 205
165 /// Binding continuations. 206 /// Binding continuations.
166 /// 207 ///
167 /// let cont k0(v0 ...) = E0 208 /// let cont k0(v0 ...) = E0
168 /// k1(v1 ...) = E1 209 /// k1(v1 ...) = E1
169 /// ... 210 /// ...
170 /// in E 211 /// in E
171 /// 212 ///
172 /// The bound continuations are in scope in the body and the continuation 213 /// The bound continuations are in scope in the body and the continuation
173 /// parameters are in scope in the respective continuation bodies. 214 /// parameters are in scope in the respective continuation bodies.
174 /// 215 ///
175 /// During one-pass construction a LetCont whose first continuation has an empty 216 /// During one-pass construction a LetCont whose first continuation has an empty
176 /// body is used to represent the one-hole context 217 /// body is used to represent the one-hole context
177 /// `let cont ... k(v) = [] ... in E`. 218 /// `let cont ... k(v) = [] ... in E`.
178 class LetCont extends Expression implements InteriorNode { 219 class LetCont extends InteriorExpression {
179 List<Continuation> continuations; 220 List<Continuation> continuations;
180 Expression body; 221 Expression body;
181 222
182 LetCont(Continuation continuation, this.body) 223 LetCont(Continuation continuation, this.body)
183 : continuations = <Continuation>[continuation]; 224 : continuations = <Continuation>[continuation];
184 225
185 LetCont.two(Continuation first, Continuation second, this.body) 226 LetCont.two(Continuation first, Continuation second, this.body)
186 : continuations = <Continuation>[first, second]; 227 : continuations = <Continuation>[first, second];
187 228
188 LetCont.many(this.continuations, this.body); 229 LetCont.many(this.continuations, this.body);
(...skipping 10 matching lines...) Expand all
199 240
200 // Binding an exception handler. 241 // Binding an exception handler.
201 // 242 //
202 // let handler h(v0, v1) = E0 in E1 243 // let handler h(v0, v1) = E0 in E1
203 // 244 //
204 // The handler is a two-argument (exception, stack trace) continuation which 245 // The handler is a two-argument (exception, stack trace) continuation which
205 // is implicitly the error continuation of all the code in its body E1. 246 // is implicitly the error continuation of all the code in its body E1.
206 // [LetHandler] differs from a [LetCont] binding in that it (1) has the 247 // [LetHandler] differs from a [LetCont] binding in that it (1) has the
207 // runtime semantics of pushing/popping a handler from the dynamic exception 248 // runtime semantics of pushing/popping a handler from the dynamic exception
208 // handler stack and (2) it does not have any explicit invocations. 249 // handler stack and (2) it does not have any explicit invocations.
209 class LetHandler extends Expression implements InteriorNode { 250 class LetHandler extends InteriorExpression {
210 Continuation handler; 251 Continuation handler;
211 Expression body; 252 Expression body;
212 253
213 LetHandler(this.handler, this.body); 254 LetHandler(this.handler, this.body);
214 255
215 accept(Visitor visitor) => visitor.visitLetHandler(this); 256 accept(Visitor visitor) => visitor.visitLetHandler(this);
216 } 257 }
217 258
218 /// Binding mutable variables. 259 /// Binding mutable variables.
219 /// 260 ///
220 /// let mutable v = P in E 261 /// let mutable v = P in E
221 /// 262 ///
222 /// [MutableVariable]s can be seen as ref cells that are not first-class 263 /// [MutableVariable]s can be seen as ref cells that are not first-class
223 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] 264 /// values. They are therefore not [Primitive]s and not bound by [LetPrim]
224 /// to prevent unrestricted use of references to them. During one-pass 265 /// to prevent unrestricted use of references to them. During one-pass
225 /// construction, a [LetMutable] with an empty body is use to represent the 266 /// construction, a [LetMutable] with an empty body is use to represent the
226 /// one-hole context 'let mutable v = P in []'. 267 /// one-hole context 'let mutable v = P in []'.
227 class LetMutable extends Expression implements InteriorNode { 268 class LetMutable extends InteriorExpression {
228 final MutableVariable variable; 269 final MutableVariable variable;
229 final Reference<Primitive> value; 270 final Reference<Primitive> value;
230 Expression body; 271 Expression body;
231 272
232 LetMutable(this.variable, Primitive value) 273 LetMutable(this.variable, Primitive value)
233 : this.value = new Reference<Primitive>(value); 274 : this.value = new Reference<Primitive>(value);
234 275
235 Expression plug(Expression expr) { 276 Expression plug(Expression expr) {
236 return body = expr; 277 return body = expr;
237 } 278 }
238 279
239 accept(Visitor visitor) => visitor.visitLetMutable(this); 280 accept(Visitor visitor) => visitor.visitLetMutable(this);
240 } 281 }
241 282
242 abstract class Invoke implements Expression {
243 Selector get selector;
244 List<Reference<Primitive>> get arguments;
245 Reference<Continuation> get continuation;
246 }
247
248 /// Represents a node with a child node, which can be accessed through the
249 /// `body` member. A typical usage is when removing a node from the CPS graph:
250 ///
251 /// Node child = node.body;
252 /// InteriorNode parent = node.parent;
253 ///
254 /// child.parent = parent;
255 /// parent.body = child;
256 abstract class InteriorNode extends Node {
257 Expression get body;
258 void set body(Expression body);
259 }
260
261 /// Invoke a static function. 283 /// Invoke a static function.
262 /// 284 ///
263 /// All optional arguments declared by [target] are passed in explicitly, and 285 /// All optional arguments declared by [target] are passed in explicitly, and
264 /// occur at the end of [arguments] list, in normalized order. 286 /// occur at the end of [arguments] list, in normalized order.
265 /// 287 ///
266 /// Discussion: 288 /// Discussion:
267 /// All information in the [selector] is technically redundant; it will likely 289 /// All information in the [selector] is technically redundant; it will likely
268 /// be removed. 290 /// be removed.
269 class InvokeStatic extends Expression implements Invoke { 291 class InvokeStatic extends CallExpression {
270 final FunctionElement target; 292 final FunctionElement target;
271 final Selector selector; 293 final Selector selector;
272 final List<Reference<Primitive>> arguments; 294 final List<Reference<Primitive>> arguments;
273 final Reference<Continuation> continuation; 295 final Reference<Continuation> continuation;
274 final SourceInformation sourceInformation; 296 final SourceInformation sourceInformation;
275 297
276 InvokeStatic(this.target, 298 InvokeStatic(this.target,
277 this.selector, 299 this.selector,
278 List<Primitive> args, 300 List<Primitive> args,
279 Continuation cont, 301 Continuation cont,
(...skipping 12 matching lines...) Expand all
292 314
293 /// Invoke a method on an object. 315 /// Invoke a method on an object.
294 /// 316 ///
295 /// This includes getters, setters, operators, and index getter/setters. 317 /// This includes getters, setters, operators, and index getter/setters.
296 /// 318 ///
297 /// Tearing off a method is treated like a getter invocation (getters and 319 /// Tearing off a method is treated like a getter invocation (getters and
298 /// tear-offs cannot be distinguished at compile-time). 320 /// tear-offs cannot be distinguished at compile-time).
299 /// 321 ///
300 /// The [selector] records the names of named arguments. The value of named 322 /// The [selector] records the names of named arguments. The value of named
301 /// arguments occur at the end of the [arguments] list, in normalized order. 323 /// arguments occur at the end of the [arguments] list, in normalized order.
302 class InvokeMethod extends Expression implements Invoke { 324 class InvokeMethod extends CallExpression {
303 Reference<Primitive> receiver; 325 Reference<Primitive> receiver;
304 Selector selector; 326 Selector selector;
305 TypeMask mask; 327 TypeMask mask;
306 final List<Reference<Primitive>> arguments; 328 final List<Reference<Primitive>> arguments;
307 final Reference<Continuation> continuation; 329 final Reference<Continuation> continuation;
308 final SourceInformation sourceInformation; 330 final SourceInformation sourceInformation;
309 331
310 /// If true, it is known that the receiver cannot be `null`. 332 /// If true, it is known that the receiver cannot be `null`.
311 bool receiverIsNotNull = false; 333 bool receiverIsNotNull = false;
312 334
(...skipping 29 matching lines...) Expand all
342 /// If it is known that [target] does not use its receiver argument, then 364 /// If it is known that [target] does not use its receiver argument, then
343 /// [receiver] may refer to a null constant primitive. This happens for direct 365 /// [receiver] may refer to a null constant primitive. This happens for direct
344 /// invocations to intercepted methods, where the effective receiver is instead 366 /// invocations to intercepted methods, where the effective receiver is instead
345 /// passed as a formal parameter. 367 /// passed as a formal parameter.
346 /// 368 ///
347 /// TODO(sra): Review. A direct call to a method that is mixed into a native 369 /// TODO(sra): Review. A direct call to a method that is mixed into a native
348 /// class will still require an explicit argument. 370 /// class will still require an explicit argument.
349 /// 371 ///
350 /// All optional arguments declared by [target] are passed in explicitly, and 372 /// All optional arguments declared by [target] are passed in explicitly, and
351 /// occur at the end of [arguments] list, in normalized order. 373 /// occur at the end of [arguments] list, in normalized order.
352 class InvokeMethodDirectly extends Expression implements Invoke { 374 class InvokeMethodDirectly extends CallExpression {
353 Reference<Primitive> receiver; 375 Reference<Primitive> receiver;
354 final FunctionElement target; 376 final FunctionElement target;
355 final Selector selector; 377 final Selector selector;
356 final List<Reference<Primitive>> arguments; 378 final List<Reference<Primitive>> arguments;
357 final Reference<Continuation> continuation; 379 final Reference<Continuation> continuation;
358 final SourceInformation sourceInformation; 380 final SourceInformation sourceInformation;
359 381
360 InvokeMethodDirectly(Primitive receiver, 382 InvokeMethodDirectly(Primitive receiver,
361 this.target, 383 this.target,
362 this.selector, 384 this.selector,
(...skipping 15 matching lines...) Expand all
378 /// All optional arguments declared by [target] are passed in explicitly, and 400 /// All optional arguments declared by [target] are passed in explicitly, and
379 /// occur in the [arguments] list, in normalized order. 401 /// occur in the [arguments] list, in normalized order.
380 /// 402 ///
381 /// Last in the [arguments] list, after the mandatory and optional arguments, 403 /// Last in the [arguments] list, after the mandatory and optional arguments,
382 /// the internal representation of each type argument occurs, unless it could 404 /// the internal representation of each type argument occurs, unless it could
383 /// be determined at build-time that the constructed class has no need for its 405 /// be determined at build-time that the constructed class has no need for its
384 /// runtime type information. 406 /// runtime type information.
385 /// 407 ///
386 /// Note that [InvokeConstructor] does it itself allocate an object. 408 /// Note that [InvokeConstructor] does it itself allocate an object.
387 /// The invoked constructor will do that using [CreateInstance]. 409 /// The invoked constructor will do that using [CreateInstance].
388 class InvokeConstructor extends Expression implements Invoke { 410 class InvokeConstructor extends CallExpression {
389 final DartType type; 411 final DartType type;
390 final ConstructorElement target; 412 final ConstructorElement target;
391 final List<Reference<Primitive>> arguments; 413 final List<Reference<Primitive>> arguments;
392 final Reference<Continuation> continuation; 414 final Reference<Continuation> continuation;
393 final Selector selector; 415 final Selector selector;
394 final SourceInformation sourceInformation; 416 final SourceInformation sourceInformation;
395 417
396 InvokeConstructor(this.type, 418 InvokeConstructor(this.type,
397 this.target, 419 this.target,
398 this.selector, 420 this.selector,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 /// An "as" type cast. 466 /// An "as" type cast.
445 /// 467 ///
446 /// If [value] is `null` or is an instance of [type], [continuation] is invoked 468 /// If [value] is `null` or is an instance of [type], [continuation] is invoked
447 /// with [value] as argument. Otherwise, a [CastError] is thrown. 469 /// with [value] as argument. Otherwise, a [CastError] is thrown.
448 /// 470 ///
449 /// Discussion: 471 /// Discussion:
450 /// The parameter to [continuation] is redundant since it will always equal 472 /// The parameter to [continuation] is redundant since it will always equal
451 /// [value], which is typically in scope in the continuation. However, it might 473 /// [value], which is typically in scope in the continuation. However, it might
452 /// simplify type propagation, since a better type can be computed for the 474 /// simplify type propagation, since a better type can be computed for the
453 /// continuation parameter without needing flow-sensitive analysis. 475 /// continuation parameter without needing flow-sensitive analysis.
454 class TypeCast extends Expression { 476 class TypeCast extends CallExpression {
455 Reference<Primitive> value; 477 Reference<Primitive> value;
456 final DartType type; 478 final DartType type;
457 479
458 /// See the corresponding field on [TypeTest]. 480 /// See the corresponding field on [TypeTest].
459 final List<Reference<Primitive>> typeArguments; 481 final List<Reference<Primitive>> typeArguments;
460 final Reference<Continuation> continuation; 482 final Reference<Continuation> continuation;
461 483
462 TypeCast(Primitive value, 484 TypeCast(Primitive value,
463 this.type, 485 this.type,
464 List<Primitive> typeArguments, 486 List<Primitive> typeArguments,
(...skipping 18 matching lines...) Expand all
483 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); 505 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);
484 506
485 bool get isSafeForElimination => true; 507 bool get isSafeForElimination => true;
486 bool get isSafeForReordering => true; 508 bool get isSafeForReordering => true;
487 } 509 }
488 510
489 /// Throw a value. 511 /// Throw a value.
490 /// 512 ///
491 /// Throw is an expression, i.e., it always occurs in tail position with 513 /// Throw is an expression, i.e., it always occurs in tail position with
492 /// respect to a body or expression. 514 /// respect to a body or expression.
493 class Throw extends Expression { 515 class Throw extends TailExpression {
494 Reference<Primitive> value; 516 Reference<Primitive> value;
495 517
496 Throw(Primitive value) : value = new Reference<Primitive>(value); 518 Throw(Primitive value) : value = new Reference<Primitive>(value);
497 519
498 accept(Visitor visitor) => visitor.visitThrow(this); 520 accept(Visitor visitor) => visitor.visitThrow(this);
499 } 521 }
500 522
501 /// Rethrow 523 /// Rethrow
502 /// 524 ///
503 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It 525 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It
504 /// implicitly throws the exception parameter of the enclosing handler with 526 /// implicitly throws the exception parameter of the enclosing handler with
505 /// the same stack trace as the enclosing handler. 527 /// the same stack trace as the enclosing handler.
506 class Rethrow extends Expression { 528 class Rethrow extends TailExpression {
507 accept(Visitor visitor) => visitor.visitRethrow(this); 529 accept(Visitor visitor) => visitor.visitRethrow(this);
508 } 530 }
509 531
510 /// A throw occurring in non-tail position. 532 /// A throw occurring in non-tail position.
511 /// 533 ///
512 /// The CPS translation of an expression produces a primitive as the value 534 /// The CPS translation of an expression produces a primitive as the value
513 /// of the expression. For convenience in the implementation of the 535 /// of the expression. For convenience in the implementation of the
514 /// translation, a [NonTailThrow] is used as that value. A cleanup pass 536 /// translation, a [NonTailThrow] is used as that value. A cleanup pass
515 /// removes these and replaces them with [Throw] expressions. 537 /// removes these and replaces them with [Throw] expressions.
516 class NonTailThrow extends Primitive { 538 class NonTailThrow extends Primitive {
517 final Reference<Primitive> value; 539 final Reference<Primitive> value;
518 540
519 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); 541 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value);
520 542
521 accept(Visitor visitor) => visitor.visitNonTailThrow(this); 543 accept(Visitor visitor) => visitor.visitNonTailThrow(this);
522 544
523 bool get isSafeForElimination => false; 545 bool get isSafeForElimination => false;
524 bool get isSafeForReordering => false; 546 bool get isSafeForReordering => false;
525 } 547 }
526 548
527 /// An expression that is known to be unreachable. 549 /// An expression that is known to be unreachable.
528 /// 550 ///
529 /// This can be placed as the body of a call continuation, when the caller is 551 /// This can be placed as the body of a call continuation, when the caller is
530 /// known never to invoke it, e.g. because the calling expression always throws. 552 /// known never to invoke it, e.g. because the calling expression always throws.
531 class Unreachable extends Expression { 553 class Unreachable extends TailExpression {
532 accept(Visitor visitor) => visitor.visitUnreachable(this); 554 accept(Visitor visitor) => visitor.visitUnreachable(this);
533 } 555 }
534 556
535 /// Gets the value from a [MutableVariable]. 557 /// Gets the value from a [MutableVariable].
536 /// 558 ///
537 /// [MutableVariable]s can be seen as ref cells that are not first-class 559 /// [MutableVariable]s can be seen as ref cells that are not first-class
538 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: 560 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as:
539 /// 561 ///
540 /// let prim p = ![variable] in [body] 562 /// let prim p = ![variable] in [body]
541 /// 563 ///
542 class GetMutableVariable extends Primitive { 564 class GetMutableVariable extends Primitive {
543 final Reference<MutableVariable> variable; 565 final Reference<MutableVariable> variable;
544 566
545 GetMutableVariable(MutableVariable variable) 567 GetMutableVariable(MutableVariable variable)
546 : this.variable = new Reference<MutableVariable>(variable); 568 : this.variable = new Reference<MutableVariable>(variable);
547 569
548 accept(Visitor visitor) => visitor.visitGetMutableVariable(this); 570 accept(Visitor visitor) => visitor.visitGetMutableVariable(this);
549 571
550 bool get isSafeForElimination => true; 572 bool get isSafeForElimination => true;
551 bool get isSafeForReordering => false; 573 bool get isSafeForReordering => false;
552 } 574 }
553 575
554 /// Assign a [MutableVariable]. 576 /// Assign a [MutableVariable].
555 /// 577 ///
556 /// [MutableVariable]s can be seen as ref cells that are not first-class 578 /// [MutableVariable]s can be seen as ref cells that are not first-class
557 /// values. This can be seen as a dereferencing assignment: 579 /// values. This can be seen as a dereferencing assignment:
558 /// 580 ///
559 /// { [variable] := [value]; [body] } 581 /// { [variable] := [value]; [body] }
560 class SetMutableVariable extends Expression implements InteriorNode { 582 class SetMutableVariable extends InteriorExpression {
561 final Reference<MutableVariable> variable; 583 final Reference<MutableVariable> variable;
562 final Reference<Primitive> value; 584 final Reference<Primitive> value;
563 Expression body; 585 Expression body;
564 586
565 SetMutableVariable(MutableVariable variable, Primitive value) 587 SetMutableVariable(MutableVariable variable, Primitive value)
566 : this.variable = new Reference<MutableVariable>(variable), 588 : this.variable = new Reference<MutableVariable>(variable),
567 this.value = new Reference<Primitive>(value); 589 this.value = new Reference<Primitive>(value);
568 590
569 accept(Visitor visitor) => visitor.visitSetMutableVariable(this); 591 accept(Visitor visitor) => visitor.visitSetMutableVariable(this);
570 592
571 Expression plug(Expression expr) { 593 Expression plug(Expression expr) {
572 assert(body == null); 594 assert(body == null);
573 return body = expr; 595 return body = expr;
574 } 596 }
575 } 597 }
576 598
577 /// Invoke a continuation in tail position. 599 /// Invoke a continuation in tail position.
578 class InvokeContinuation extends Expression { 600 class InvokeContinuation extends TailExpression {
579 Reference<Continuation> continuation; 601 Reference<Continuation> continuation;
580 List<Reference<Primitive>> arguments; 602 List<Reference<Primitive>> arguments;
581 SourceInformation sourceInformation; 603 SourceInformation sourceInformation;
582 604
583 // An invocation of a continuation is recursive if it occurs in the body of 605 // An invocation of a continuation is recursive if it occurs in the body of
584 // the continuation itself. 606 // the continuation itself.
585 bool isRecursive; 607 bool isRecursive;
586 608
587 /// True if this invocation escapes from the body of a [LetHandler] 609 /// True if this invocation escapes from the body of a [LetHandler]
588 /// (i.e. a try block). Notably, such an invocation cannot be inlined. 610 /// (i.e. a try block). Notably, such an invocation cannot be inlined.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 final Reference<Primitive> value; 642 final Reference<Primitive> value;
621 643
622 IsTrue(Primitive val) : value = new Reference<Primitive>(val); 644 IsTrue(Primitive val) : value = new Reference<Primitive>(val);
623 645
624 accept(Visitor visitor) => visitor.visitIsTrue(this); 646 accept(Visitor visitor) => visitor.visitIsTrue(this);
625 } 647 }
626 648
627 /// Choose between a pair of continuations based on a condition value. 649 /// Choose between a pair of continuations based on a condition value.
628 /// 650 ///
629 /// The two continuations must not declare any parameters. 651 /// The two continuations must not declare any parameters.
630 class Branch extends Expression { 652 class Branch extends TailExpression {
631 final Condition condition; 653 final Condition condition;
632 final Reference<Continuation> trueContinuation; 654 final Reference<Continuation> trueContinuation;
633 final Reference<Continuation> falseContinuation; 655 final Reference<Continuation> falseContinuation;
634 656
635 Branch(this.condition, Continuation trueCont, Continuation falseCont) 657 Branch(this.condition, Continuation trueCont, Continuation falseCont)
636 : trueContinuation = new Reference<Continuation>(trueCont), 658 : trueContinuation = new Reference<Continuation>(trueCont),
637 falseContinuation = new Reference<Continuation>(falseCont); 659 falseContinuation = new Reference<Continuation>(falseCont);
638 660
639 accept(Visitor visitor) => visitor.visitBranch(this); 661 accept(Visitor visitor) => visitor.visitBranch(this);
640 } 662 }
641 663
642 /// Directly assigns to a field on a given object. 664 /// Directly assigns to a field on a given object.
643 class SetField extends Expression implements InteriorNode { 665 class SetField extends InteriorExpression {
644 final Reference<Primitive> object; 666 final Reference<Primitive> object;
645 FieldElement field; 667 FieldElement field;
646 final Reference<Primitive> value; 668 final Reference<Primitive> value;
647 Expression body; 669 Expression body;
648 670
649 SetField(Primitive object, this.field, Primitive value) 671 SetField(Primitive object, this.field, Primitive value)
650 : this.object = new Reference<Primitive>(object), 672 : this.object = new Reference<Primitive>(object),
651 this.value = new Reference<Primitive>(value); 673 this.value = new Reference<Primitive>(value);
652 674
653 Expression plug(Expression expr) { 675 Expression plug(Expression expr) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 771
750 bool get isSafeForElimination { 772 bool get isSafeForElimination {
751 return true; 773 return true;
752 } 774 }
753 bool get isSafeForReordering { 775 bool get isSafeForReordering {
754 return element is FunctionElement || element.isFinal; 776 return element is FunctionElement || element.isFinal;
755 } 777 }
756 } 778 }
757 779
758 /// Sets the value of a static field. 780 /// Sets the value of a static field.
759 class SetStatic extends Expression implements InteriorNode { 781 class SetStatic extends InteriorExpression {
760 final FieldElement element; 782 final FieldElement element;
761 final Reference<Primitive> value; 783 final Reference<Primitive> value;
762 Expression body; 784 Expression body;
763 final SourceInformation sourceInformation; 785 final SourceInformation sourceInformation;
764 786
765 SetStatic(this.element, Primitive value, [this.sourceInformation]) 787 SetStatic(this.element, Primitive value, [this.sourceInformation])
766 : this.value = new Reference<Primitive>(value); 788 : this.value = new Reference<Primitive>(value);
767 789
768 Expression plug(Expression expr) { 790 Expression plug(Expression expr) {
769 assert(body == null); 791 assert(body == null);
770 return body = expr; 792 return body = expr;
771 } 793 }
772 794
773 accept(Visitor visitor) => visitor.visitSetStatic(this); 795 accept(Visitor visitor) => visitor.visitSetStatic(this);
774 } 796 }
775 797
776 /// Reads the value of a lazily initialized static field. 798 /// Reads the value of a lazily initialized static field.
777 /// 799 ///
778 /// If the field has not yet been initialized, its initializer is evaluated 800 /// If the field has not yet been initialized, its initializer is evaluated
779 /// and assigned to the field. 801 /// and assigned to the field.
780 /// 802 ///
781 /// [continuation] is then invoked with the value of the field as argument. 803 /// [continuation] is then invoked with the value of the field as argument.
782 class GetLazyStatic extends Expression { 804 class GetLazyStatic extends CallExpression {
783 final FieldElement element; 805 final FieldElement element;
784 final Reference<Continuation> continuation; 806 final Reference<Continuation> continuation;
785 final SourceInformation sourceInformation; 807 final SourceInformation sourceInformation;
786 808
787 GetLazyStatic(this.element, 809 GetLazyStatic(this.element,
788 Continuation continuation, 810 Continuation continuation,
789 [this.sourceInformation]) 811 [this.sourceInformation])
790 : continuation = new Reference<Continuation>(continuation); 812 : continuation = new Reference<Continuation>(continuation);
791 813
792 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); 814 accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 870
849 CreateInvocationMirror(this.selector, List<Primitive> arguments) 871 CreateInvocationMirror(this.selector, List<Primitive> arguments)
850 : this.arguments = _referenceList(arguments); 872 : this.arguments = _referenceList(arguments);
851 873
852 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); 874 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
853 875
854 bool get isSafeForElimination => true; 876 bool get isSafeForElimination => true;
855 bool get isSafeForReordering => true; 877 bool get isSafeForReordering => true;
856 } 878 }
857 879
858 class ForeignCode extends Expression { 880 class ForeignCode extends CallExpression {
859 final js.Template codeTemplate; 881 final js.Template codeTemplate;
860 final TypeMask type; 882 final TypeMask type;
861 final List<Reference<Primitive>> arguments; 883 final List<Reference<Primitive>> arguments;
862 final native.NativeBehavior nativeBehavior; 884 final native.NativeBehavior nativeBehavior;
863 final FunctionElement dependency; 885 final FunctionElement dependency;
864
865 /// The continuation, if the foreign code is not a JavaScript 'throw',
866 /// otherwise null.
867 final Reference<Continuation> continuation; 886 final Reference<Continuation> continuation;
868 887
869 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, 888 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
870 this.nativeBehavior, {Continuation continuation, this.dependency}) 889 this.nativeBehavior, Continuation continuation, {this.dependency})
871 : arguments = _referenceList(arguments), 890 : this.arguments = _referenceList(arguments),
872 continuation = continuation == null ? null 891 this.continuation = new Reference<Continuation>(continuation);
873 : new Reference<Continuation>(continuation);
874 892
875 accept(Visitor visitor) => visitor.visitForeignCode(this); 893 accept(Visitor visitor) => visitor.visitForeignCode(this);
876 } 894 }
877 895
878 class Constant extends Primitive { 896 class Constant extends Primitive {
879 final values.ConstantValue value; 897 final values.ConstantValue value;
880 final SourceInformation sourceInformation; 898 final SourceInformation sourceInformation;
881 899
882 Constant(this.value, {this.sourceInformation}); 900 Constant(this.value, {this.sourceInformation});
883 901
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 : parameters = <Parameter>[new Parameter(null)], 1003 : parameters = <Parameter>[new Parameter(null)],
986 isRecursive = false; 1004 isRecursive = false;
987 1005
988 accept(Visitor visitor) => visitor.visitContinuation(this); 1006 accept(Visitor visitor) => visitor.visitContinuation(this);
989 } 1007 }
990 1008
991 /// Identifies a mutable variable. 1009 /// Identifies a mutable variable.
992 class MutableVariable extends Definition { 1010 class MutableVariable extends Definition {
993 Entity hint; 1011 Entity hint;
994 1012
995 MutableVariable(this.hint); 1013 MutableVariable(this.hint);
996 1014
997 accept(Visitor v) => v.visitMutableVariable(this); 1015 accept(Visitor v) => v.visitMutableVariable(this);
998 } 1016 }
999 1017
1000 /// A function definition, consisting of parameters and a body. 1018 /// A function definition, consisting of parameters and a body.
1001 /// 1019 ///
1002 /// There is an explicit parameter for the `this` argument, and a return 1020 /// There is an explicit parameter for the `this` argument, and a return
1003 /// continuation to invoke when returning from the function. 1021 /// continuation to invoke when returning from the function.
1004 class FunctionDefinition extends InteriorNode { 1022 class FunctionDefinition extends InteriorNode {
1005 final ExecutableElement element; 1023 final ExecutableElement element;
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 const RemovalVisitor(); 1473 const RemovalVisitor();
1456 1474
1457 processReference(Reference reference) { 1475 processReference(Reference reference) {
1458 reference.unlink(); 1476 reference.unlink();
1459 } 1477 }
1460 1478
1461 static void remove(Node node) { 1479 static void remove(Node node) {
1462 (const RemovalVisitor()).visit(node); 1480 (const RemovalVisitor()).visit(node);
1463 } 1481 }
1464 } 1482 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698