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

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

Issue 1458703007: dart2js cps: Refactor CallExpressions into Primitives. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 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
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 'dart:collection';
7 import '../constants/values.dart' as values; 7 import '../constants/values.dart' as values;
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; 8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../io/source_information.dart' show SourceInformation; 10 import '../io/source_information.dart' show SourceInformation;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 assert(parent == null); 116 assert(parent == null);
117 assert(body == null); 117 assert(body == null);
118 Expression child = newParent.body; 118 Expression child = newParent.body;
119 newParent.body = this; 119 newParent.body = this;
120 this.body = child; 120 this.body = child;
121 child.parent = this; 121 child.parent = this;
122 this.parent = newParent; 122 this.parent = newParent;
123 } 123 }
124 } 124 }
125 125
126 /// An expression that passes a continuation to a call.
127 abstract class CallExpression extends Expression {
128 Reference<Continuation> get continuation;
129 Expression get next => continuation.definition.body;
130 }
131
132 /// An expression without a continuation or a subexpression body. 126 /// An expression without a continuation or a subexpression body.
133 /// 127 ///
134 /// These break straight-line control flow and can be thought of as ending a 128 /// These break straight-line control flow and can be thought of as ending a
135 /// basic block. 129 /// basic block.
136 abstract class TailExpression extends Expression { 130 abstract class TailExpression extends Expression {
137 Expression get next => null; 131 Expression get next => null;
138 } 132 }
139 133
140 /// The base class of things that variables can refer to: primitives, 134 /// The base class of things that variables can refer to: primitives,
141 /// continuations, function and continuation parameters, etc. 135 /// continuations, function and continuation parameters, etc.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 255
262 bool get hasNoEffectiveUses { 256 bool get hasNoEffectiveUses {
263 return effectiveUses.isEmpty; 257 return effectiveUses.isEmpty;
264 } 258 }
265 259
266 /// Unlinks all references contained in this node. 260 /// Unlinks all references contained in this node.
267 void destroy() { 261 void destroy() {
268 assert(hasNoUses); 262 assert(hasNoUses);
269 RemovalVisitor.remove(this); 263 RemovalVisitor.remove(this);
270 } 264 }
265
266 /// Replaces this definition, both at the binding site and at all uses sites.
sra1 2015/11/19 21:41:46 Then maybe call it 'replaceWith'.
asgerf 2015/11/20 16:23:54 I would like that name, but 'substituteFor' and 'r
267 ///
268 /// This can be thought of as changing the definition of a `let` while
269 /// preserving the variable name:
270 ///
271 /// let x = OLD in BODY
272 /// ==>
273 /// let x = NEW in BODY
274 ///
275 void redefineAs(Primitive newDefinition) {
sra1 2015/11/19 21:41:45 assert(newDefinition.parent == null); assert there
asgerf 2015/11/20 16:23:53 There are uses. They are being replaced with uses
276 newDefinition.substituteFor(this);
277 destroy();
278 LetPrim let = parent;
279 let.primitive = newDefinition;
280 newDefinition.parent = let;
281 newDefinition.useElementAsHint(hint);
282 }
283 }
284
285 /// A primitive that is generally not safe for elimination, but may be marked
286 /// as safe by type propagation
287 //
288 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this
289 // class.
290 abstract class UnsafePrimitive extends Primitive {
291 bool isSafeForElimination = false;
271 } 292 }
272 293
273 /// Operands to invocations and primitives are always variables. They point to 294 /// Operands to invocations and primitives are always variables. They point to
274 /// their definition and are doubly-linked into a list of occurrences. 295 /// their definition and are doubly-linked into a list of occurrences.
275 class Reference<T extends Definition<T>> { 296 class Reference<T extends Definition<T>> {
276 T definition; 297 T definition;
277 Reference<T> previous; 298 Reference<T> previous;
278 Reference<T> next; 299 Reference<T> next;
279 300
280 /// A pointer to the parent node. Is null until set by optimization passes. 301 /// A pointer to the parent node. Is null until set by optimization passes.
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 } 449 }
429 450
430 /// Invoke a static function. 451 /// Invoke a static function.
431 /// 452 ///
432 /// All optional arguments declared by [target] are passed in explicitly, and 453 /// All optional arguments declared by [target] are passed in explicitly, and
433 /// occur at the end of [arguments] list, in normalized order. 454 /// occur at the end of [arguments] list, in normalized order.
434 /// 455 ///
435 /// Discussion: 456 /// Discussion:
436 /// All information in the [selector] is technically redundant; it will likely 457 /// All information in the [selector] is technically redundant; it will likely
437 /// be removed. 458 /// be removed.
438 class InvokeStatic extends CallExpression { 459 class InvokeStatic extends UnsafePrimitive {
439 final FunctionElement target; 460 final FunctionElement target;
440 final Selector selector; 461 final Selector selector;
441 final List<Reference<Primitive>> arguments; 462 final List<Reference<Primitive>> arguments;
442 final Reference<Continuation> continuation;
443 final SourceInformation sourceInformation; 463 final SourceInformation sourceInformation;
444 464
465 bool get isSafeForReordering => isSafeForElimination;
466
445 InvokeStatic(this.target, 467 InvokeStatic(this.target,
446 this.selector, 468 this.selector,
447 List<Primitive> args, 469 List<Primitive> args,
448 Continuation cont,
449 [this.sourceInformation]) 470 [this.sourceInformation])
450 : arguments = _referenceList(args), 471 : arguments = _referenceList(args);
451 continuation = new Reference<Continuation>(cont);
452 472
453 InvokeStatic.byReference(this.target, 473 InvokeStatic.byReference(this.target,
454 this.selector, 474 this.selector,
455 this.arguments, 475 this.arguments,
456 this.continuation,
457 [this.sourceInformation]); 476 [this.sourceInformation]);
458 477
459 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 478 accept(Visitor visitor) => visitor.visitInvokeStatic(this);
460 479
461 void setParentPointers() { 480 void setParentPointers() {
462 _setParentsOnList(arguments, this); 481 _setParentsOnList(arguments, this);
463 continuation.parent = this;
464 } 482 }
465 } 483 }
466 484
485 enum CallingConvention {
sra1 2015/11/19 21:41:45 Just a thought: We might want to make this a hand
asgerf 2015/11/20 16:23:54 I don't know that "interceptor position" means, bu
486 /// JS receiver is the Dart receiver, there are no extra arguments.
487 ///
488 /// For example: `foo.bar$1(x)`
489 Normal,
sra1 2015/11/19 21:41:45 Maybe 'Direct'. 'Normal' implies abnormal but inte
asgerf 2015/11/20 16:23:54 I would also consider NonIntercepted to be "direct
490
491 /// JS receiver is an interceptor, the first argument is the Dart receiver.
492 ///
493 /// For example: `getInterceptor(foo).bar$1(foo, x)`
494 Intercepted,
495
496 /// JS receiver is the Dart receiver, the first argument is a dummy value.
497 ///
498 /// For example: `foo.bar$1(0, x)`
499 DummyIntercepted,
500 }
501
467 /// Invoke a method on an object. 502 /// Invoke a method on an object.
468 /// 503 ///
469 /// This includes getters, setters, operators, and index getter/setters. 504 /// This includes getters, setters, operators, and index getter/setters.
470 /// 505 ///
471 /// Tearing off a method is treated like a getter invocation (getters and 506 /// Tearing off a method is treated like a getter invocation (getters and
472 /// tear-offs cannot be distinguished at compile-time). 507 /// tear-offs cannot be distinguished at compile-time).
473 /// 508 ///
474 /// The [selector] records the names of named arguments. The value of named 509 /// The [selector] records the names of named arguments. The value of named
475 /// arguments occur at the end of the [arguments] list, in normalized order. 510 /// arguments occur at the end of the [arguments] list, in normalized order.
476 class InvokeMethod extends CallExpression { 511 class InvokeMethod extends UnsafePrimitive {
477 Reference<Primitive> receiver; 512 Reference<Primitive> receiver;
478 Selector selector; 513 Selector selector;
479 TypeMask mask; 514 TypeMask mask;
480 final List<Reference<Primitive>> arguments; 515 final List<Reference<Primitive>> arguments;
481 final Reference<Continuation> continuation;
482 final SourceInformation sourceInformation; 516 final SourceInformation sourceInformation;
483 517
484 /// If true, the [receiver] is intercepted and the actual receiver is in 518 CallingConvention callingConvention = CallingConvention.Normal;
485 /// the first argument. Otherwise, the [receiver] is the actual receiver. 519
486 /// 520 bool get receiverIsIntercepted {
sra1 2015/11/19 21:41:45 I'm wondering if there are any inconsistencies bet
asgerf 2015/11/20 16:23:54 Done.
487 /// This flag is always false for non-intercepted selectors, but it may also 521 return callingConvention == CallingConvention.Intercepted;
488 /// be false for intercepted selectors after dummy receiver optimization 522 }
489 /// (in this case the first argument is a dummy value). 523
490 /// 524 Reference<Primitive> get dartReceiverRef {
sra1 2015/11/19 21:41:46 We try to use full words where possible, e.g. dart
asgerf 2015/11/20 16:23:54 Done.
491 /// It is always false before the unsugaring pass, where interceptors have 525 return callingConvention == CallingConvention.Intercepted
492 /// not yet been introduced. 526 ? arguments[0]
493 bool receiverIsIntercepted = false; 527 : receiver;
528 }
529
530 Primitive get dartReceiver => dartReceiverRef.definition;
531
532 Reference<Primitive> getDartArgumentRef(int n) {
sra1 2015/11/19 21:41:45 can we drop the 'get' on these methods for symmetr
asgerf 2015/11/20 16:23:53 Done.
533 return callingConvention == CallingConvention.Normal
534 ? arguments[n]
535 : arguments[n + 1];
536 }
537
538 Primitive getDartArgument(int n) => getDartArgumentRef(n).definition;
494 539
495 /// If true, it is known that the receiver cannot be `null`. 540 /// If true, it is known that the receiver cannot be `null`.
496 bool receiverIsNotNull = false; 541 bool receiverIsNotNull = false;
497 542
543 bool get isSafeForReordering => isSafeForElimination;
sra1 2015/11/19 21:41:46 This feels backwards. I'd rather this was a separ
asgerf 2015/11/20 16:23:53 Done.
544
498 InvokeMethod(Primitive receiver, 545 InvokeMethod(Primitive receiver,
499 this.selector, 546 this.selector,
500 this.mask, 547 this.mask,
501 List<Primitive> arguments, 548 List<Primitive> arguments,
502 Continuation continuation,
503 [this.sourceInformation]) 549 [this.sourceInformation])
504 : this.receiver = new Reference<Primitive>(receiver), 550 : this.receiver = new Reference<Primitive>(receiver),
505 this.arguments = _referenceList(arguments), 551 this.arguments = _referenceList(arguments);
506 this.continuation = new Reference<Continuation>(continuation);
507 552
508 InvokeMethod.byReference(this.receiver, 553 InvokeMethod.byReference(this.receiver,
509 this.selector, 554 this.selector,
510 this.mask, 555 this.mask,
511 this.arguments, 556 this.arguments,
512 this.continuation,
513 this.sourceInformation); 557 this.sourceInformation);
514 558
515 accept(Visitor visitor) => visitor.visitInvokeMethod(this); 559 accept(Visitor visitor) => visitor.visitInvokeMethod(this);
516 560
517 void setParentPointers() { 561 void setParentPointers() {
518 receiver.parent = this; 562 receiver.parent = this;
519 _setParentsOnList(arguments, this); 563 _setParentsOnList(arguments, this);
520 continuation.parent = this;
521 } 564 }
522 } 565 }
523 566
524 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. 567 /// Invoke [target] on [receiver], bypassing dispatch and override semantics.
525 /// 568 ///
526 /// That is, if [receiver] is an instance of a class that overrides [target] 569 /// That is, if [receiver] is an instance of a class that overrides [target]
527 /// with a different implementation, the overriding implementation is bypassed 570 /// with a different implementation, the overriding implementation is bypassed
528 /// and [target]'s implementation is invoked. 571 /// and [target]'s implementation is invoked.
529 /// 572 ///
530 /// As with [InvokeMethod], this can be used to invoke a method, operator, 573 /// As with [InvokeMethod], this can be used to invoke a method, operator,
531 /// getter, setter, or index getter/setter. 574 /// getter, setter, or index getter/setter.
532 /// 575 ///
533 /// If it is known that [target] does not use its receiver argument, then 576 /// If it is known that [target] does not use its receiver argument, then
534 /// [receiver] may refer to a null constant primitive. This happens for direct 577 /// [receiver] may refer to a null constant primitive. This happens for direct
535 /// invocations to intercepted methods, where the effective receiver is instead 578 /// invocations to intercepted methods, where the effective receiver is instead
536 /// passed as a formal parameter. 579 /// passed as a formal parameter.
537 /// 580 ///
538 /// TODO(sra): Review. A direct call to a method that is mixed into a native 581 /// TODO(sra): Review. A direct call to a method that is mixed into a native
539 /// class will still require an explicit argument. 582 /// class will still require an explicit argument.
540 /// 583 ///
541 /// All optional arguments declared by [target] are passed in explicitly, and 584 /// All optional arguments declared by [target] are passed in explicitly, and
542 /// occur at the end of [arguments] list, in normalized order. 585 /// occur at the end of [arguments] list, in normalized order.
543 class InvokeMethodDirectly extends CallExpression { 586 class InvokeMethodDirectly extends UnsafePrimitive {
544 Reference<Primitive> receiver; 587 Reference<Primitive> receiver;
545 final FunctionElement target; 588 final FunctionElement target;
546 final Selector selector; 589 final Selector selector;
547 final List<Reference<Primitive>> arguments; 590 final List<Reference<Primitive>> arguments;
548 final Reference<Continuation> continuation;
549 final SourceInformation sourceInformation; 591 final SourceInformation sourceInformation;
550 592
593 CallingConvention callingConvention = CallingConvention.Normal;
594
595 bool get receiverIsIntercepted {
596 return callingConvention == CallingConvention.Intercepted;
597 }
598
599 Reference<Primitive> get dartReceiverRef {
600 return callingConvention == CallingConvention.Intercepted
601 ? arguments[0]
602 : receiver;
603 }
604
605 Primitive get dartReceiver => dartReceiverRef.definition;
606
607 Reference<Primitive> getDartArgumentRef(int n) {
608 return callingConvention == CallingConvention.Normal
609 ? arguments[n]
610 : arguments[n + 1];
611 }
612
613 Primitive getDartArgument(int n) => getDartArgumentRef(n).definition;
614
615 bool get isSafeForReordering => isSafeForElimination;
616
551 InvokeMethodDirectly(Primitive receiver, 617 InvokeMethodDirectly(Primitive receiver,
552 this.target, 618 this.target,
553 this.selector, 619 this.selector,
554 List<Primitive> arguments, 620 List<Primitive> arguments,
555 Continuation continuation,
556 this.sourceInformation) 621 this.sourceInformation)
557 : this.receiver = new Reference<Primitive>(receiver), 622 : this.receiver = new Reference<Primitive>(receiver),
558 this.arguments = _referenceList(arguments), 623 this.arguments = _referenceList(arguments);
559 this.continuation = new Reference<Continuation>(continuation);
560 624
561 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); 625 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);
562 626
563 void setParentPointers() { 627 void setParentPointers() {
564 receiver.parent = this; 628 receiver.parent = this;
565 _setParentsOnList(arguments, this); 629 _setParentsOnList(arguments, this);
566 continuation.parent = this;
567 } 630 }
568 } 631 }
569 632
570 /// Non-const call to a constructor. 633 /// Non-const call to a constructor.
571 /// 634 ///
572 /// The [target] may be a generative constructor (forwarding or normal) 635 /// The [target] may be a generative constructor (forwarding or normal)
573 /// or a non-redirecting factory. 636 /// or a non-redirecting factory.
574 /// 637 ///
575 /// All optional arguments declared by [target] are passed in explicitly, and 638 /// All optional arguments declared by [target] are passed in explicitly, and
576 /// occur in the [arguments] list, in normalized order. 639 /// occur in the [arguments] list, in normalized order.
577 /// 640 ///
578 /// Last in the [arguments] list, after the mandatory and optional arguments, 641 /// Last in the [arguments] list, after the mandatory and optional arguments,
579 /// the internal representation of each type argument occurs, unless it could 642 /// the internal representation of each type argument occurs, unless it could
580 /// be determined at build-time that the constructed class has no need for its 643 /// be determined at build-time that the constructed class has no need for its
581 /// runtime type information. 644 /// runtime type information.
582 /// 645 ///
583 /// Note that [InvokeConstructor] does it itself allocate an object. 646 /// Note that [InvokeConstructor] does it itself allocate an object.
584 /// The invoked constructor will do that using [CreateInstance]. 647 /// The invoked constructor will do that using [CreateInstance].
585 class InvokeConstructor extends CallExpression { 648 class InvokeConstructor extends UnsafePrimitive {
586 final DartType dartType; 649 final DartType dartType;
587 final ConstructorElement target; 650 final ConstructorElement target;
588 final List<Reference<Primitive>> arguments; 651 final List<Reference<Primitive>> arguments;
589 final Reference<Continuation> continuation;
590 final Selector selector; 652 final Selector selector;
591 final SourceInformation sourceInformation; 653 final SourceInformation sourceInformation;
592 654
655 bool get isSafeForReordering => isSafeForElimination;
656
593 /// If non-null, this is an allocation site-specific type that is potentially 657 /// If non-null, this is an allocation site-specific type that is potentially
594 /// better than the inferred return type of [target]. 658 /// better than the inferred return type of [target].
595 /// 659 ///
596 /// In particular, container type masks depend on the allocation site and 660 /// In particular, container type masks depend on the allocation site and
597 /// can therefore not be inferred solely based on the call target. 661 /// can therefore not be inferred solely based on the call target.
598 TypeMask allocationSiteType; 662 TypeMask allocationSiteType;
599 663
600 InvokeConstructor(this.dartType, 664 InvokeConstructor(this.dartType,
601 this.target, 665 this.target,
602 this.selector, 666 this.selector,
603 List<Primitive> args, 667 List<Primitive> args,
604 Continuation cont,
605 this.sourceInformation, 668 this.sourceInformation,
606 {this.allocationSiteType}) 669 {this.allocationSiteType})
607 : arguments = _referenceList(args), 670 : arguments = _referenceList(args);
608 continuation = new Reference<Continuation>(cont);
609 671
610 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); 672 accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
611 673
612 void setParentPointers() { 674 void setParentPointers() {
613 _setParentsOnList(arguments, this); 675 _setParentsOnList(arguments, this);
614 continuation.parent = this;
615 } 676 }
616 } 677 }
617 678
618 /// An alias for [value] in a context where the value is known to satisfy 679 /// An alias for [value] in a context where the value is known to satisfy
619 /// [type]. 680 /// [type].
620 /// 681 ///
621 /// Refinement nodes are inserted before the type propagator pass and removed 682 /// Refinement nodes are inserted before the type propagator pass and removed
622 /// afterwards, so as not to complicate passes that don't reason about types, 683 /// afterwards, so as not to complicate passes that don't reason about types,
623 /// but need to reason about value references being identical (i.e. referring 684 /// but need to reason about value references being identical (i.e. referring
624 /// to the same primitive). 685 /// to the same primitive).
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 /// An "as" type cast. 773 /// An "as" type cast.
713 /// 774 ///
714 /// If [value] is `null` or is an instance of [type], [continuation] is invoked 775 /// If [value] is `null` or is an instance of [type], [continuation] is invoked
715 /// with [value] as argument. Otherwise, a [CastError] is thrown. 776 /// with [value] as argument. Otherwise, a [CastError] is thrown.
716 /// 777 ///
717 /// Discussion: 778 /// Discussion:
718 /// The parameter to [continuation] is redundant since it will always equal 779 /// The parameter to [continuation] is redundant since it will always equal
719 /// [value], which is typically in scope in the continuation. However, it might 780 /// [value], which is typically in scope in the continuation. However, it might
720 /// simplify type propagation, since a better type can be computed for the 781 /// simplify type propagation, since a better type can be computed for the
721 /// continuation parameter without needing flow-sensitive analysis. 782 /// continuation parameter without needing flow-sensitive analysis.
722 class TypeCast extends CallExpression { 783 class TypeCast extends UnsafePrimitive {
723 Reference<Primitive> value; 784 Reference<Primitive> value;
724 final DartType dartType; 785 final DartType dartType;
725 786
726 /// See the corresponding field on [TypeTest]. 787 /// See the corresponding field on [TypeTest].
727 final List<Reference<Primitive>> typeArguments; 788 final List<Reference<Primitive>> typeArguments;
728 final Reference<Continuation> continuation; 789
790 bool get isSafeForReordering => isSafeForElimination;
729 791
730 TypeCast(Primitive value, 792 TypeCast(Primitive value,
731 this.dartType, 793 this.dartType,
732 List<Primitive> typeArguments, 794 List<Primitive> typeArguments)
733 Continuation cont)
734 : this.value = new Reference<Primitive>(value), 795 : this.value = new Reference<Primitive>(value),
735 this.typeArguments = _referenceList(typeArguments), 796 this.typeArguments = _referenceList(typeArguments);
736 this.continuation = new Reference<Continuation>(cont);
737 797
738 accept(Visitor visitor) => visitor.visitTypeCast(this); 798 accept(Visitor visitor) => visitor.visitTypeCast(this);
739 799
740 void setParentPointers() { 800 void setParentPointers() {
741 value.parent = this; 801 value.parent = this;
802 _setParentsOnList(typeArguments, this);
742 } 803 }
743 } 804 }
744 805
745 /// Apply a built-in operator. 806 /// Apply a built-in operator.
746 /// 807 ///
747 /// It must be known that the arguments have the proper types. 808 /// It must be known that the arguments have the proper types.
748 class ApplyBuiltinOperator extends Primitive { 809 class ApplyBuiltinOperator extends Primitive {
749 BuiltinOperator operator; 810 BuiltinOperator operator;
750 List<Reference<Primitive>> arguments; 811 List<Reference<Primitive>> arguments;
751 final SourceInformation sourceInformation; 812 final SourceInformation sourceInformation;
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 1180
1120 void setParentPointers() { 1181 void setParentPointers() {
1121 value.parent = this; 1182 value.parent = this;
1122 } 1183 }
1123 } 1184 }
1124 1185
1125 /// Reads the value of a lazily initialized static field. 1186 /// Reads the value of a lazily initialized static field.
1126 /// 1187 ///
1127 /// If the field has not yet been initialized, its initializer is evaluated 1188 /// If the field has not yet been initialized, its initializer is evaluated
1128 /// and assigned to the field. 1189 /// and assigned to the field.
1129 /// 1190 class GetLazyStatic extends UnsafePrimitive {
1130 /// [continuation] is then invoked with the value of the field as argument.
1131 class GetLazyStatic extends CallExpression {
1132 final FieldElement element; 1191 final FieldElement element;
1133 final Reference<Continuation> continuation;
1134 final SourceInformation sourceInformation; 1192 final SourceInformation sourceInformation;
1135 1193
1136 GetLazyStatic(this.element, 1194 bool get isSafeForReordering => isSafeForElimination;
1137 Continuation continuation, 1195
1138 [this.sourceInformation]) 1196 GetLazyStatic(this.element, [this.sourceInformation]);
1139 : continuation = new Reference<Continuation>(continuation);
1140 1197
1141 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); 1198 accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
1142 1199
1143 void setParentPointers() { 1200 void setParentPointers() {
1144 continuation.parent = this;
1145 } 1201 }
1146 } 1202 }
1147 1203
1148 /// Creates an object for holding boxed variables captured by a closure. 1204 /// Creates an object for holding boxed variables captured by a closure.
1149 class CreateBox extends Primitive { 1205 class CreateBox extends Primitive {
1150 accept(Visitor visitor) => visitor.visitCreateBox(this); 1206 accept(Visitor visitor) => visitor.visitCreateBox(this);
1151 1207
1152 bool get isSafeForElimination => true; 1208 bool get isSafeForElimination => true;
1153 bool get isSafeForReordering => true; 1209 bool get isSafeForReordering => true;
1154 1210
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); 1352 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
1297 1353
1298 bool get isSafeForElimination => true; 1354 bool get isSafeForElimination => true;
1299 bool get isSafeForReordering => true; 1355 bool get isSafeForReordering => true;
1300 1356
1301 void setParentPointers() { 1357 void setParentPointers() {
1302 _setParentsOnList(arguments, this); 1358 _setParentsOnList(arguments, this);
1303 } 1359 }
1304 } 1360 }
1305 1361
1306 class ForeignCode extends CallExpression { 1362 class ForeignCode extends UnsafePrimitive {
1307 final js.Template codeTemplate; 1363 final js.Template codeTemplate;
1308 final TypeMask type; 1364 final TypeMask type;
1309 final List<Reference<Primitive>> arguments; 1365 final List<Reference<Primitive>> arguments;
1310 final native.NativeBehavior nativeBehavior; 1366 final native.NativeBehavior nativeBehavior;
1311 final FunctionElement dependency; 1367 final FunctionElement dependency;
1312 final Reference<Continuation> continuation; 1368
1369 bool get isSafeForReordering => isSafeForElimination;
1313 1370
1314 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, 1371 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
1315 this.nativeBehavior, Continuation continuation, {this.dependency}) 1372 this.nativeBehavior, {this.dependency})
1316 : this.arguments = _referenceList(arguments), 1373 : this.arguments = _referenceList(arguments);
1317 this.continuation = new Reference<Continuation>(continuation);
1318 1374
1319 accept(Visitor visitor) => visitor.visitForeignCode(this); 1375 accept(Visitor visitor) => visitor.visitForeignCode(this);
1320 1376
1321 void setParentPointers() { 1377 void setParentPointers() {
1322 _setParentsOnList(arguments, this); 1378 _setParentsOnList(arguments, this);
1323 continuation.parent = this;
1324 } 1379 }
1325 } 1380 }
1326 1381
1327 class Constant extends Primitive { 1382 class Constant extends Primitive {
1328 final values.ConstantValue value; 1383 final values.ConstantValue value;
1329 final SourceInformation sourceInformation; 1384 final SourceInformation sourceInformation;
1330 1385
1331 Constant(this.value, {this.sourceInformation}) { 1386 Constant(this.value, {this.sourceInformation}) {
1332 assert(value != null); 1387 assert(value != null);
1333 } 1388 }
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 } 1624 }
1570 1625
1571 bool get isSafeForElimination => true; 1626 bool get isSafeForElimination => true;
1572 bool get isSafeForReordering => true; 1627 bool get isSafeForReordering => true;
1573 1628
1574 void setParentPointers() { 1629 void setParentPointers() {
1575 _setParentsOnList(arguments, this); 1630 _setParentsOnList(arguments, this);
1576 } 1631 }
1577 } 1632 }
1578 1633
1579 class Await extends CallExpression { 1634 class Await extends UnsafePrimitive {
1580 final Reference<Primitive> input; 1635 final Reference<Primitive> input;
1581 final Reference<Continuation> continuation;
1582 1636
1583 Await(Primitive input, Continuation continuation) 1637 bool get isSafeForReordering => isSafeForElimination;
1584 : this.input = new Reference<Primitive>(input), 1638
1585 this.continuation = new Reference<Continuation>(continuation); 1639 Await(Primitive input)
1640 : this.input = new Reference<Primitive>(input);
1586 1641
1587 @override 1642 @override
1588 accept(Visitor visitor) { 1643 accept(Visitor visitor) {
1589 return visitor.visitAwait(this); 1644 return visitor.visitAwait(this);
1590 } 1645 }
1591 1646
1592 void setParentPointers() { 1647 void setParentPointers() {
1593 input.parent = this; 1648 input.parent = this;
1594 continuation.parent = this;
1595 } 1649 }
1596 } 1650 }
1597 1651
1598 class Yield extends CallExpression { 1652 class Yield extends UnsafePrimitive {
1599 final Reference<Primitive> input; 1653 final Reference<Primitive> input;
1600 final Reference<Continuation> continuation;
1601 final bool hasStar; 1654 final bool hasStar;
1602 1655
1603 Yield(Primitive input, this.hasStar, Continuation continuation) 1656 bool get isSafeForReordering => isSafeForElimination;
1604 : this.input = new Reference<Primitive>(input), 1657
1605 this.continuation = new Reference<Continuation>(continuation); 1658 Yield(Primitive input, this.hasStar)
1659 : this.input = new Reference<Primitive>(input);
1606 1660
1607 @override 1661 @override
1608 accept(Visitor visitor) { 1662 accept(Visitor visitor) {
1609 return visitor.visitYield(this); 1663 return visitor.visitYield(this);
1610 } 1664 }
1611 1665
1612 void setParentPointers() { 1666 void setParentPointers() {
1613 input.parent = this; 1667 input.parent = this;
1614 continuation.parent = this;
1615 } 1668 }
1616 } 1669 }
1617 1670
1618 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { 1671 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
1619 return definitions.map((e) => new Reference<Primitive>(e)).toList(); 1672 return definitions.map((e) => new Reference<Primitive>(e)).toList();
1620 } 1673 }
1621 1674
1622 void _setParentsOnNodes(List<Node> nodes, Node parent) { 1675 void _setParentsOnNodes(List<Node> nodes, Node parent) {
1623 for (Node node in nodes) { 1676 for (Node node in nodes) {
1624 node.parent = parent; 1677 node.parent = parent;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 visitLetMutable(LetMutable node) { 1806 visitLetMutable(LetMutable node) {
1754 processLetMutable(node); 1807 processLetMutable(node);
1755 visit(node.variable); 1808 visit(node.variable);
1756 processReference(node.value); 1809 processReference(node.value);
1757 visit(node.body); 1810 visit(node.body);
1758 } 1811 }
1759 1812
1760 processInvokeStatic(InvokeStatic node) {} 1813 processInvokeStatic(InvokeStatic node) {}
1761 visitInvokeStatic(InvokeStatic node) { 1814 visitInvokeStatic(InvokeStatic node) {
1762 processInvokeStatic(node); 1815 processInvokeStatic(node);
1763 processReference(node.continuation);
1764 node.arguments.forEach(processReference); 1816 node.arguments.forEach(processReference);
1765 } 1817 }
1766 1818
1767 processInvokeContinuation(InvokeContinuation node) {} 1819 processInvokeContinuation(InvokeContinuation node) {}
1768 visitInvokeContinuation(InvokeContinuation node) { 1820 visitInvokeContinuation(InvokeContinuation node) {
1769 processInvokeContinuation(node); 1821 processInvokeContinuation(node);
1770 processReference(node.continuation); 1822 processReference(node.continuation);
1771 node.arguments.forEach(processReference); 1823 node.arguments.forEach(processReference);
1772 } 1824 }
1773 1825
1774 processInvokeMethod(InvokeMethod node) {} 1826 processInvokeMethod(InvokeMethod node) {}
1775 visitInvokeMethod(InvokeMethod node) { 1827 visitInvokeMethod(InvokeMethod node) {
1776 processInvokeMethod(node); 1828 processInvokeMethod(node);
1777 processReference(node.receiver); 1829 processReference(node.receiver);
1778 processReference(node.continuation);
1779 node.arguments.forEach(processReference); 1830 node.arguments.forEach(processReference);
1780 } 1831 }
1781 1832
1782 processInvokeMethodDirectly(InvokeMethodDirectly node) {} 1833 processInvokeMethodDirectly(InvokeMethodDirectly node) {}
1783 visitInvokeMethodDirectly(InvokeMethodDirectly node) { 1834 visitInvokeMethodDirectly(InvokeMethodDirectly node) {
1784 processInvokeMethodDirectly(node); 1835 processInvokeMethodDirectly(node);
1785 processReference(node.receiver); 1836 processReference(node.receiver);
1786 processReference(node.continuation);
1787 node.arguments.forEach(processReference); 1837 node.arguments.forEach(processReference);
1788 } 1838 }
1789 1839
1790 processInvokeConstructor(InvokeConstructor node) {} 1840 processInvokeConstructor(InvokeConstructor node) {}
1791 visitInvokeConstructor(InvokeConstructor node) { 1841 visitInvokeConstructor(InvokeConstructor node) {
1792 processInvokeConstructor(node); 1842 processInvokeConstructor(node);
1793 processReference(node.continuation);
1794 node.arguments.forEach(processReference); 1843 node.arguments.forEach(processReference);
1795 } 1844 }
1796 1845
1797 processThrow(Throw node) {} 1846 processThrow(Throw node) {}
1798 visitThrow(Throw node) { 1847 visitThrow(Throw node) {
1799 processThrow(node); 1848 processThrow(node);
1800 processReference(node.value); 1849 processReference(node.value);
1801 } 1850 }
1802 1851
1803 processRethrow(Rethrow node) {} 1852 processRethrow(Rethrow node) {}
1804 visitRethrow(Rethrow node) { 1853 visitRethrow(Rethrow node) {
1805 processRethrow(node); 1854 processRethrow(node);
1806 } 1855 }
1807 1856
1808 processBranch(Branch node) {} 1857 processBranch(Branch node) {}
1809 visitBranch(Branch node) { 1858 visitBranch(Branch node) {
1810 processBranch(node); 1859 processBranch(node);
1811 processReference(node.trueContinuation); 1860 processReference(node.trueContinuation);
1812 processReference(node.falseContinuation); 1861 processReference(node.falseContinuation);
1813 processReference(node.condition); 1862 processReference(node.condition);
1814 } 1863 }
1815 1864
1816 processTypeCast(TypeCast node) {} 1865 processTypeCast(TypeCast node) {}
1817 visitTypeCast(TypeCast node) { 1866 visitTypeCast(TypeCast node) {
1818 processTypeCast(node); 1867 processTypeCast(node);
1819 processReference(node.continuation);
1820 processReference(node.value); 1868 processReference(node.value);
1821 node.typeArguments.forEach(processReference); 1869 node.typeArguments.forEach(processReference);
1822 } 1870 }
1823 1871
1824 processTypeTest(TypeTest node) {} 1872 processTypeTest(TypeTest node) {}
1825 visitTypeTest(TypeTest node) { 1873 visitTypeTest(TypeTest node) {
1826 processTypeTest(node); 1874 processTypeTest(node);
1827 processReference(node.value); 1875 processReference(node.value);
1828 if (node.interceptor != null) processReference(node.interceptor); 1876 if (node.interceptor != null) processReference(node.interceptor);
1829 node.typeArguments.forEach(processReference); 1877 node.typeArguments.forEach(processReference);
1830 } 1878 }
1831 1879
1832 processTypeTestViaFlag(TypeTestViaFlag node) {} 1880 processTypeTestViaFlag(TypeTestViaFlag node) {}
1833 visitTypeTestViaFlag(TypeTestViaFlag node) { 1881 visitTypeTestViaFlag(TypeTestViaFlag node) {
1834 processTypeTestViaFlag(node); 1882 processTypeTestViaFlag(node);
1835 processReference(node.interceptor); 1883 processReference(node.interceptor);
1836 } 1884 }
1837 1885
1838 processSetMutable(SetMutable node) {} 1886 processSetMutable(SetMutable node) {}
1839 visitSetMutable(SetMutable node) { 1887 visitSetMutable(SetMutable node) {
1840 processSetMutable(node); 1888 processSetMutable(node);
1841 processReference(node.variable); 1889 processReference(node.variable);
1842 processReference(node.value); 1890 processReference(node.value);
1843 } 1891 }
1844 1892
1845 processGetLazyStatic(GetLazyStatic node) {} 1893 processGetLazyStatic(GetLazyStatic node) {}
1846 visitGetLazyStatic(GetLazyStatic node) { 1894 visitGetLazyStatic(GetLazyStatic node) {
1847 processGetLazyStatic(node); 1895 processGetLazyStatic(node);
1848 processReference(node.continuation);
1849 } 1896 }
1850 1897
1851 processLiteralList(LiteralList node) {} 1898 processLiteralList(LiteralList node) {}
1852 visitLiteralList(LiteralList node) { 1899 visitLiteralList(LiteralList node) {
1853 processLiteralList(node); 1900 processLiteralList(node);
1854 node.values.forEach(processReference); 1901 node.values.forEach(processReference);
1855 } 1902 }
1856 1903
1857 processLiteralMap(LiteralMap node) {} 1904 processLiteralMap(LiteralMap node) {}
1858 visitLiteralMap(LiteralMap node) { 1905 visitLiteralMap(LiteralMap node) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 processApplyBuiltinMethod(ApplyBuiltinMethod node) {} 2012 processApplyBuiltinMethod(ApplyBuiltinMethod node) {}
1966 visitApplyBuiltinMethod(ApplyBuiltinMethod node) { 2013 visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
1967 processApplyBuiltinMethod(node); 2014 processApplyBuiltinMethod(node);
1968 processReference(node.receiver); 2015 processReference(node.receiver);
1969 node.arguments.forEach(processReference); 2016 node.arguments.forEach(processReference);
1970 } 2017 }
1971 2018
1972 processForeignCode(ForeignCode node) {} 2019 processForeignCode(ForeignCode node) {}
1973 visitForeignCode(ForeignCode node) { 2020 visitForeignCode(ForeignCode node) {
1974 processForeignCode(node); 2021 processForeignCode(node);
1975 if (node.continuation != null) {
1976 processReference(node.continuation);
1977 }
1978 node.arguments.forEach(processReference); 2022 node.arguments.forEach(processReference);
1979 } 2023 }
1980 2024
1981 processUnreachable(Unreachable node) {} 2025 processUnreachable(Unreachable node) {}
1982 visitUnreachable(Unreachable node) { 2026 visitUnreachable(Unreachable node) {
1983 processUnreachable(node); 2027 processUnreachable(node);
1984 } 2028 }
1985 2029
1986 processAwait(Await node) {} 2030 processAwait(Await node) {}
1987 visitAwait(Await node) { 2031 visitAwait(Await node) {
1988 processAwait(node); 2032 processAwait(node);
1989 processReference(node.input); 2033 processReference(node.input);
1990 processReference(node.continuation);
1991 } 2034 }
1992 2035
1993 processYield(Yield node) {} 2036 processYield(Yield node) {}
1994 visitYield(Yield node) { 2037 visitYield(Yield node) {
1995 processYield(node); 2038 processYield(node);
1996 processReference(node.input); 2039 processReference(node.input);
1997 processReference(node.continuation);
1998 } 2040 }
1999 2041
2000 processGetLength(GetLength node) {} 2042 processGetLength(GetLength node) {}
2001 visitGetLength(GetLength node) { 2043 visitGetLength(GetLength node) {
2002 processGetLength(node); 2044 processGetLength(node);
2003 processReference(node.object); 2045 processReference(node.object);
2004 } 2046 }
2005 2047
2006 processGetIndex(GetIndex node) {} 2048 processGetIndex(GetIndex node) {}
2007 visitGetIndex(GetIndex node) { 2049 visitGetIndex(GetIndex node) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 2191 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
2150 class RemovalVisitor extends TrampolineRecursiveVisitor { 2192 class RemovalVisitor extends TrampolineRecursiveVisitor {
2151 processReference(Reference reference) { 2193 processReference(Reference reference) {
2152 reference.unlink(); 2194 reference.unlink();
2153 } 2195 }
2154 2196
2155 static void remove(Node node) { 2197 static void remove(Node node) {
2156 (new RemovalVisitor()).visit(node); 2198 (new RemovalVisitor()).visit(node);
2157 } 2199 }
2158 } 2200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698