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

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: Another minor fix 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.
142 abstract class Definition<T extends Definition<T>> extends Node { 136 abstract class Definition<T extends Definition<T>> extends Node {
143 // The head of a linked-list of occurrences, in no particular order. 137 // The head of a linked-list of occurrences, in no particular order.
144 Reference<T> firstRef; 138 Reference<T> firstRef;
145 139
146 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null; 140 bool get hasAtMostOneUse => firstRef == null || firstRef.next == null;
147 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null; 141 bool get hasExactlyOneUse => firstRef != null && firstRef.next == null;
148 bool get hasNoUses => firstRef == null; 142 bool get hasNoUses => firstRef == null;
149 bool get hasAtLeastOneUse => firstRef != null; 143 bool get hasAtLeastOneUse => firstRef != null;
150 bool get hasMultipleUses => !hasAtMostOneUse; 144 bool get hasMultipleUses => !hasAtMostOneUse;
151 145
152 void substituteFor(Definition<T> other) { 146 void replaceUsesWith(Definition<T> newDefinition) {
153 if (other == this) return; 147 if (newDefinition == this) return;
154 if (other.hasNoUses) return; 148 if (hasNoUses) return;
155 Reference<T> previous, current = other.firstRef; 149 Reference<T> previous, current = firstRef;
156 do { 150 do {
157 current.definition = this; 151 current.definition = newDefinition;
158 previous = current; 152 previous = current;
159 current = current.next; 153 current = current.next;
160 } while (current != null); 154 } while (current != null);
161 previous.next = firstRef; 155 previous.next = newDefinition.firstRef;
162 if (firstRef != null) firstRef.previous = previous; 156 if (newDefinition.firstRef != null) {
163 firstRef = other.firstRef; 157 newDefinition.firstRef.previous = previous;
164 other.firstRef = null; 158 }
159 newDefinition.firstRef = firstRef;
160 firstRef = null;
165 } 161 }
166 } 162 }
167 163
168 class EffectiveUseIterator extends Iterator<Reference<Primitive>> { 164 class EffectiveUseIterator extends Iterator<Reference<Primitive>> {
169 Reference<Primitive> current; 165 Reference<Primitive> current;
170 Reference<Primitive> next; 166 Reference<Primitive> next;
171 final List<Refinement> stack = <Refinement>[]; 167 final List<Refinement> stack = <Refinement>[];
172 168
173 EffectiveUseIterator(Primitive prim) : next = prim.firstRef; 169 EffectiveUseIterator(Primitive prim) : next = prim.firstRef;
174 170
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 257
262 bool get hasNoEffectiveUses { 258 bool get hasNoEffectiveUses {
263 return effectiveUses.isEmpty; 259 return effectiveUses.isEmpty;
264 } 260 }
265 261
266 /// Unlinks all references contained in this node. 262 /// Unlinks all references contained in this node.
267 void destroy() { 263 void destroy() {
268 assert(hasNoUses); 264 assert(hasNoUses);
269 RemovalVisitor.remove(this); 265 RemovalVisitor.remove(this);
270 } 266 }
267
268 /// Replaces this definition, both at the binding site and at all uses sites.
269 ///
270 /// This can be thought of as changing the definition of a `let` while
271 /// preserving the variable name:
272 ///
273 /// let x = OLD in BODY
274 /// ==>
275 /// let x = NEW in BODY
276 ///
277 void replaceWith(Primitive newDefinition) {
278 assert(this is! Parameter);
279 assert(newDefinition is! Parameter);
280 assert(newDefinition.parent == null);
281 replaceUsesWith(newDefinition);
282 destroy();
283 LetPrim let = parent;
284 let.primitive = newDefinition;
285 newDefinition.parent = let;
286 newDefinition.useElementAsHint(hint);
287 }
288 }
289
290 /// A primitive that is generally not safe for elimination, but may be marked
291 /// as safe by type propagation
292 //
293 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this
294 // class.
295 abstract class UnsafePrimitive extends Primitive {
296 bool isSafeForElimination = false;
297 bool isSafeForReordering = false;
271 } 298 }
272 299
273 /// Operands to invocations and primitives are always variables. They point to 300 /// Operands to invocations and primitives are always variables. They point to
274 /// their definition and are doubly-linked into a list of occurrences. 301 /// their definition and are doubly-linked into a list of occurrences.
275 class Reference<T extends Definition<T>> { 302 class Reference<T extends Definition<T>> {
276 T definition; 303 T definition;
277 Reference<T> previous; 304 Reference<T> previous;
278 Reference<T> next; 305 Reference<T> next;
279 306
280 /// A pointer to the parent node. Is null until set by optimization passes. 307 /// 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 } 455 }
429 456
430 /// Invoke a static function. 457 /// Invoke a static function.
431 /// 458 ///
432 /// All optional arguments declared by [target] are passed in explicitly, and 459 /// All optional arguments declared by [target] are passed in explicitly, and
433 /// occur at the end of [arguments] list, in normalized order. 460 /// occur at the end of [arguments] list, in normalized order.
434 /// 461 ///
435 /// Discussion: 462 /// Discussion:
436 /// All information in the [selector] is technically redundant; it will likely 463 /// All information in the [selector] is technically redundant; it will likely
437 /// be removed. 464 /// be removed.
438 class InvokeStatic extends CallExpression { 465 class InvokeStatic extends UnsafePrimitive {
439 final FunctionElement target; 466 final FunctionElement target;
440 final Selector selector; 467 final Selector selector;
441 final List<Reference<Primitive>> arguments; 468 final List<Reference<Primitive>> arguments;
442 final Reference<Continuation> continuation;
443 final SourceInformation sourceInformation; 469 final SourceInformation sourceInformation;
444 470
445 InvokeStatic(this.target, 471 InvokeStatic(this.target,
446 this.selector, 472 this.selector,
447 List<Primitive> args, 473 List<Primitive> args,
448 Continuation cont,
449 [this.sourceInformation]) 474 [this.sourceInformation])
450 : arguments = _referenceList(args), 475 : arguments = _referenceList(args);
451 continuation = new Reference<Continuation>(cont);
452 476
453 InvokeStatic.byReference(this.target, 477 InvokeStatic.byReference(this.target,
454 this.selector, 478 this.selector,
455 this.arguments, 479 this.arguments,
456 this.continuation,
457 [this.sourceInformation]); 480 [this.sourceInformation]);
458 481
459 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 482 accept(Visitor visitor) => visitor.visitInvokeStatic(this);
460 483
461 void setParentPointers() { 484 void setParentPointers() {
462 _setParentsOnList(arguments, this); 485 _setParentsOnList(arguments, this);
463 continuation.parent = this;
464 } 486 }
465 } 487 }
466 488
489 enum CallingConvention {
490 /// JS receiver is the Dart receiver, there are no extra arguments.
491 ///
492 /// For example: `foo.bar$1(x)`
493 Normal,
494
495 /// JS receiver is an interceptor, the first argument is the Dart receiver.
496 ///
497 /// For example: `getInterceptor(foo).bar$1(foo, x)`
498 Intercepted,
499
500 /// JS receiver is the Dart receiver, the first argument is a dummy value.
501 ///
502 /// For example: `foo.bar$1(0, x)`
503 DummyIntercepted,
504 }
505
467 /// Invoke a method on an object. 506 /// Invoke a method on an object.
468 /// 507 ///
469 /// This includes getters, setters, operators, and index getter/setters. 508 /// This includes getters, setters, operators, and index getter/setters.
470 /// 509 ///
471 /// Tearing off a method is treated like a getter invocation (getters and 510 /// Tearing off a method is treated like a getter invocation (getters and
472 /// tear-offs cannot be distinguished at compile-time). 511 /// tear-offs cannot be distinguished at compile-time).
473 /// 512 ///
474 /// The [selector] records the names of named arguments. The value of named 513 /// 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. 514 /// arguments occur at the end of the [arguments] list, in normalized order.
476 class InvokeMethod extends CallExpression { 515 class InvokeMethod extends UnsafePrimitive {
477 Reference<Primitive> receiver; 516 Reference<Primitive> receiver;
478 Selector selector; 517 Selector selector;
479 TypeMask mask; 518 TypeMask mask;
480 final List<Reference<Primitive>> arguments; 519 final List<Reference<Primitive>> arguments;
481 final Reference<Continuation> continuation;
482 final SourceInformation sourceInformation; 520 final SourceInformation sourceInformation;
483 521
484 /// If true, the [receiver] is intercepted and the actual receiver is in 522 CallingConvention callingConvention = CallingConvention.Normal;
485 /// the first argument. Otherwise, the [receiver] is the actual receiver. 523
486 /// 524 Reference<Primitive> get dartReceiverReference {
487 /// This flag is always false for non-intercepted selectors, but it may also 525 return callingConvention == CallingConvention.Intercepted
488 /// be false for intercepted selectors after dummy receiver optimization 526 ? arguments[0]
489 /// (in this case the first argument is a dummy value). 527 : receiver;
490 /// 528 }
491 /// It is always false before the unsugaring pass, where interceptors have 529
492 /// not yet been introduced. 530 Primitive get dartReceiver => dartReceiverReference.definition;
493 bool receiverIsIntercepted = false; 531
532 Reference<Primitive> dartArgumentReference(int n) {
533 return callingConvention == CallingConvention.Normal
534 ? arguments[n]
535 : arguments[n + 1];
536 }
537
538 Primitive dartArgument(int n) => dartArgumentReference(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
498 InvokeMethod(Primitive receiver, 543 InvokeMethod(Primitive receiver,
499 this.selector, 544 this.selector,
500 this.mask, 545 this.mask,
501 List<Primitive> arguments, 546 List<Primitive> arguments,
502 Continuation continuation,
503 [this.sourceInformation]) 547 [this.sourceInformation])
504 : this.receiver = new Reference<Primitive>(receiver), 548 : this.receiver = new Reference<Primitive>(receiver),
505 this.arguments = _referenceList(arguments), 549 this.arguments = _referenceList(arguments);
506 this.continuation = new Reference<Continuation>(continuation);
507 550
508 InvokeMethod.byReference(this.receiver, 551 InvokeMethod.byReference(this.receiver,
509 this.selector, 552 this.selector,
510 this.mask, 553 this.mask,
511 this.arguments, 554 this.arguments,
512 this.continuation,
513 this.sourceInformation); 555 this.sourceInformation);
514 556
515 accept(Visitor visitor) => visitor.visitInvokeMethod(this); 557 accept(Visitor visitor) => visitor.visitInvokeMethod(this);
516 558
517 void setParentPointers() { 559 void setParentPointers() {
518 receiver.parent = this; 560 receiver.parent = this;
519 _setParentsOnList(arguments, this); 561 _setParentsOnList(arguments, this);
520 continuation.parent = this;
521 } 562 }
522 } 563 }
523 564
524 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. 565 /// Invoke [target] on [receiver], bypassing dispatch and override semantics.
525 /// 566 ///
526 /// That is, if [receiver] is an instance of a class that overrides [target] 567 /// That is, if [receiver] is an instance of a class that overrides [target]
527 /// with a different implementation, the overriding implementation is bypassed 568 /// with a different implementation, the overriding implementation is bypassed
528 /// and [target]'s implementation is invoked. 569 /// and [target]'s implementation is invoked.
529 /// 570 ///
530 /// As with [InvokeMethod], this can be used to invoke a method, operator, 571 /// As with [InvokeMethod], this can be used to invoke a method, operator,
531 /// getter, setter, or index getter/setter. 572 /// getter, setter, or index getter/setter.
532 /// 573 ///
533 /// If it is known that [target] does not use its receiver argument, then 574 /// 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 575 /// [receiver] may refer to a null constant primitive. This happens for direct
535 /// invocations to intercepted methods, where the effective receiver is instead 576 /// invocations to intercepted methods, where the effective receiver is instead
536 /// passed as a formal parameter. 577 /// passed as a formal parameter.
537 /// 578 ///
538 /// TODO(sra): Review. A direct call to a method that is mixed into a native 579 /// TODO(sra): Review. A direct call to a method that is mixed into a native
539 /// class will still require an explicit argument. 580 /// class will still require an explicit argument.
540 /// 581 ///
541 /// All optional arguments declared by [target] are passed in explicitly, and 582 /// All optional arguments declared by [target] are passed in explicitly, and
542 /// occur at the end of [arguments] list, in normalized order. 583 /// occur at the end of [arguments] list, in normalized order.
543 class InvokeMethodDirectly extends CallExpression { 584 class InvokeMethodDirectly extends UnsafePrimitive {
544 Reference<Primitive> receiver; 585 Reference<Primitive> receiver;
545 final FunctionElement target; 586 final FunctionElement target;
546 final Selector selector; 587 final Selector selector;
547 final List<Reference<Primitive>> arguments; 588 final List<Reference<Primitive>> arguments;
548 final Reference<Continuation> continuation;
549 final SourceInformation sourceInformation; 589 final SourceInformation sourceInformation;
550 590
591 CallingConvention callingConvention = CallingConvention.Normal;
592
593 Reference<Primitive> get dartReceiverReference {
594 return callingConvention == CallingConvention.Intercepted
595 ? arguments[0]
596 : receiver;
597 }
598
599 Primitive get dartReceiver => dartReceiverReference.definition;
600
601 Reference<Primitive> dartArgumentReference(int n) {
602 return callingConvention == CallingConvention.Normal
603 ? arguments[n]
604 : arguments[n + 1];
605 }
606
607 Primitive dartArgument(int n) => dartArgumentReference(n).definition;
608
551 InvokeMethodDirectly(Primitive receiver, 609 InvokeMethodDirectly(Primitive receiver,
552 this.target, 610 this.target,
553 this.selector, 611 this.selector,
554 List<Primitive> arguments, 612 List<Primitive> arguments,
555 Continuation continuation,
556 this.sourceInformation) 613 this.sourceInformation)
557 : this.receiver = new Reference<Primitive>(receiver), 614 : this.receiver = new Reference<Primitive>(receiver),
558 this.arguments = _referenceList(arguments), 615 this.arguments = _referenceList(arguments);
559 this.continuation = new Reference<Continuation>(continuation);
560 616
561 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); 617 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);
562 618
563 void setParentPointers() { 619 void setParentPointers() {
564 receiver.parent = this; 620 receiver.parent = this;
565 _setParentsOnList(arguments, this); 621 _setParentsOnList(arguments, this);
566 continuation.parent = this;
567 } 622 }
568 } 623 }
569 624
570 /// Non-const call to a constructor. 625 /// Non-const call to a constructor.
571 /// 626 ///
572 /// The [target] may be a generative constructor (forwarding or normal) 627 /// The [target] may be a generative constructor (forwarding or normal)
573 /// or a non-redirecting factory. 628 /// or a non-redirecting factory.
574 /// 629 ///
575 /// All optional arguments declared by [target] are passed in explicitly, and 630 /// All optional arguments declared by [target] are passed in explicitly, and
576 /// occur in the [arguments] list, in normalized order. 631 /// occur in the [arguments] list, in normalized order.
577 /// 632 ///
578 /// Last in the [arguments] list, after the mandatory and optional arguments, 633 /// Last in the [arguments] list, after the mandatory and optional arguments,
579 /// the internal representation of each type argument occurs, unless it could 634 /// 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 635 /// be determined at build-time that the constructed class has no need for its
581 /// runtime type information. 636 /// runtime type information.
582 /// 637 ///
583 /// Note that [InvokeConstructor] does it itself allocate an object. 638 /// Note that [InvokeConstructor] does it itself allocate an object.
584 /// The invoked constructor will do that using [CreateInstance]. 639 /// The invoked constructor will do that using [CreateInstance].
585 class InvokeConstructor extends CallExpression { 640 class InvokeConstructor extends UnsafePrimitive {
586 final DartType dartType; 641 final DartType dartType;
587 final ConstructorElement target; 642 final ConstructorElement target;
588 final List<Reference<Primitive>> arguments; 643 final List<Reference<Primitive>> arguments;
589 final Reference<Continuation> continuation;
590 final Selector selector; 644 final Selector selector;
591 final SourceInformation sourceInformation; 645 final SourceInformation sourceInformation;
592 646
593 /// If non-null, this is an allocation site-specific type that is potentially 647 /// If non-null, this is an allocation site-specific type that is potentially
594 /// better than the inferred return type of [target]. 648 /// better than the inferred return type of [target].
595 /// 649 ///
596 /// In particular, container type masks depend on the allocation site and 650 /// In particular, container type masks depend on the allocation site and
597 /// can therefore not be inferred solely based on the call target. 651 /// can therefore not be inferred solely based on the call target.
598 TypeMask allocationSiteType; 652 TypeMask allocationSiteType;
599 653
600 InvokeConstructor(this.dartType, 654 InvokeConstructor(this.dartType,
601 this.target, 655 this.target,
602 this.selector, 656 this.selector,
603 List<Primitive> args, 657 List<Primitive> args,
604 Continuation cont,
605 this.sourceInformation, 658 this.sourceInformation,
606 {this.allocationSiteType}) 659 {this.allocationSiteType})
607 : arguments = _referenceList(args), 660 : arguments = _referenceList(args);
608 continuation = new Reference<Continuation>(cont);
609 661
610 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); 662 accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
611 663
612 void setParentPointers() { 664 void setParentPointers() {
613 _setParentsOnList(arguments, this); 665 _setParentsOnList(arguments, this);
614 continuation.parent = this;
615 } 666 }
616 } 667 }
617 668
618 /// An alias for [value] in a context where the value is known to satisfy 669 /// An alias for [value] in a context where the value is known to satisfy
619 /// [type]. 670 /// [type].
620 /// 671 ///
621 /// Refinement nodes are inserted before the type propagator pass and removed 672 /// 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, 673 /// 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 674 /// but need to reason about value references being identical (i.e. referring
624 /// to the same primitive). 675 /// to the same primitive).
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 /// An "as" type cast. 763 /// An "as" type cast.
713 /// 764 ///
714 /// If [value] is `null` or is an instance of [type], [continuation] is invoked 765 /// If [value] is `null` or is an instance of [type], [continuation] is invoked
715 /// with [value] as argument. Otherwise, a [CastError] is thrown. 766 /// with [value] as argument. Otherwise, a [CastError] is thrown.
716 /// 767 ///
717 /// Discussion: 768 /// Discussion:
718 /// The parameter to [continuation] is redundant since it will always equal 769 /// The parameter to [continuation] is redundant since it will always equal
719 /// [value], which is typically in scope in the continuation. However, it might 770 /// [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 771 /// simplify type propagation, since a better type can be computed for the
721 /// continuation parameter without needing flow-sensitive analysis. 772 /// continuation parameter without needing flow-sensitive analysis.
722 class TypeCast extends CallExpression { 773 class TypeCast extends UnsafePrimitive {
723 Reference<Primitive> value; 774 Reference<Primitive> value;
724 final DartType dartType; 775 final DartType dartType;
725 776
726 /// See the corresponding field on [TypeTest]. 777 /// See the corresponding field on [TypeTest].
727 final List<Reference<Primitive>> typeArguments; 778 final List<Reference<Primitive>> typeArguments;
728 final Reference<Continuation> continuation;
729 779
730 TypeCast(Primitive value, 780 TypeCast(Primitive value,
731 this.dartType, 781 this.dartType,
732 List<Primitive> typeArguments, 782 List<Primitive> typeArguments)
733 Continuation cont)
734 : this.value = new Reference<Primitive>(value), 783 : this.value = new Reference<Primitive>(value),
735 this.typeArguments = _referenceList(typeArguments), 784 this.typeArguments = _referenceList(typeArguments);
736 this.continuation = new Reference<Continuation>(cont);
737 785
738 accept(Visitor visitor) => visitor.visitTypeCast(this); 786 accept(Visitor visitor) => visitor.visitTypeCast(this);
739 787
740 void setParentPointers() { 788 void setParentPointers() {
741 value.parent = this; 789 value.parent = this;
790 _setParentsOnList(typeArguments, this);
742 } 791 }
743 } 792 }
744 793
745 /// Apply a built-in operator. 794 /// Apply a built-in operator.
746 /// 795 ///
747 /// It must be known that the arguments have the proper types. 796 /// It must be known that the arguments have the proper types.
748 class ApplyBuiltinOperator extends Primitive { 797 class ApplyBuiltinOperator extends Primitive {
749 BuiltinOperator operator; 798 BuiltinOperator operator;
750 List<Reference<Primitive>> arguments; 799 List<Reference<Primitive>> arguments;
751 final SourceInformation sourceInformation; 800 final SourceInformation sourceInformation;
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 1168
1120 void setParentPointers() { 1169 void setParentPointers() {
1121 value.parent = this; 1170 value.parent = this;
1122 } 1171 }
1123 } 1172 }
1124 1173
1125 /// Reads the value of a lazily initialized static field. 1174 /// Reads the value of a lazily initialized static field.
1126 /// 1175 ///
1127 /// If the field has not yet been initialized, its initializer is evaluated 1176 /// If the field has not yet been initialized, its initializer is evaluated
1128 /// and assigned to the field. 1177 /// and assigned to the field.
1129 /// 1178 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; 1179 final FieldElement element;
1133 final Reference<Continuation> continuation;
1134 final SourceInformation sourceInformation; 1180 final SourceInformation sourceInformation;
1135 1181
1136 GetLazyStatic(this.element, 1182 GetLazyStatic(this.element, [this.sourceInformation]);
1137 Continuation continuation,
1138 [this.sourceInformation])
1139 : continuation = new Reference<Continuation>(continuation);
1140 1183
1141 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); 1184 accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
1142 1185
1143 void setParentPointers() { 1186 void setParentPointers() {
1144 continuation.parent = this;
1145 } 1187 }
1146 } 1188 }
1147 1189
1148 /// Creates an object for holding boxed variables captured by a closure. 1190 /// Creates an object for holding boxed variables captured by a closure.
1149 class CreateBox extends Primitive { 1191 class CreateBox extends Primitive {
1150 accept(Visitor visitor) => visitor.visitCreateBox(this); 1192 accept(Visitor visitor) => visitor.visitCreateBox(this);
1151 1193
1152 bool get isSafeForElimination => true; 1194 bool get isSafeForElimination => true;
1153 bool get isSafeForReordering => true; 1195 bool get isSafeForReordering => true;
1154 1196
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); 1338 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
1297 1339
1298 bool get isSafeForElimination => true; 1340 bool get isSafeForElimination => true;
1299 bool get isSafeForReordering => true; 1341 bool get isSafeForReordering => true;
1300 1342
1301 void setParentPointers() { 1343 void setParentPointers() {
1302 _setParentsOnList(arguments, this); 1344 _setParentsOnList(arguments, this);
1303 } 1345 }
1304 } 1346 }
1305 1347
1306 class ForeignCode extends CallExpression { 1348 class ForeignCode extends UnsafePrimitive {
1307 final js.Template codeTemplate; 1349 final js.Template codeTemplate;
1308 final TypeMask type; 1350 final TypeMask type;
1309 final List<Reference<Primitive>> arguments; 1351 final List<Reference<Primitive>> arguments;
1310 final native.NativeBehavior nativeBehavior; 1352 final native.NativeBehavior nativeBehavior;
1311 final FunctionElement dependency; 1353 final FunctionElement dependency;
1312 final Reference<Continuation> continuation;
1313 1354
1314 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, 1355 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
1315 this.nativeBehavior, Continuation continuation, {this.dependency}) 1356 this.nativeBehavior, {this.dependency})
1316 : this.arguments = _referenceList(arguments), 1357 : this.arguments = _referenceList(arguments);
1317 this.continuation = new Reference<Continuation>(continuation);
1318 1358
1319 accept(Visitor visitor) => visitor.visitForeignCode(this); 1359 accept(Visitor visitor) => visitor.visitForeignCode(this);
1320 1360
1321 void setParentPointers() { 1361 void setParentPointers() {
1322 _setParentsOnList(arguments, this); 1362 _setParentsOnList(arguments, this);
1323 continuation.parent = this;
1324 } 1363 }
1325 } 1364 }
1326 1365
1327 class Constant extends Primitive { 1366 class Constant extends Primitive {
1328 final values.ConstantValue value; 1367 final values.ConstantValue value;
1329 final SourceInformation sourceInformation; 1368 final SourceInformation sourceInformation;
1330 1369
1331 Constant(this.value, {this.sourceInformation}) { 1370 Constant(this.value, {this.sourceInformation}) {
1332 assert(value != null); 1371 assert(value != null);
1333 } 1372 }
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 } 1608 }
1570 1609
1571 bool get isSafeForElimination => true; 1610 bool get isSafeForElimination => true;
1572 bool get isSafeForReordering => true; 1611 bool get isSafeForReordering => true;
1573 1612
1574 void setParentPointers() { 1613 void setParentPointers() {
1575 _setParentsOnList(arguments, this); 1614 _setParentsOnList(arguments, this);
1576 } 1615 }
1577 } 1616 }
1578 1617
1579 class Await extends CallExpression { 1618 class Await extends UnsafePrimitive {
1580 final Reference<Primitive> input; 1619 final Reference<Primitive> input;
1581 final Reference<Continuation> continuation;
1582 1620
1583 Await(Primitive input, Continuation continuation) 1621 Await(Primitive input)
1584 : this.input = new Reference<Primitive>(input), 1622 : this.input = new Reference<Primitive>(input);
1585 this.continuation = new Reference<Continuation>(continuation);
1586 1623
1587 @override 1624 @override
1588 accept(Visitor visitor) { 1625 accept(Visitor visitor) {
1589 return visitor.visitAwait(this); 1626 return visitor.visitAwait(this);
1590 } 1627 }
1591 1628
1592 void setParentPointers() { 1629 void setParentPointers() {
1593 input.parent = this; 1630 input.parent = this;
1594 continuation.parent = this;
1595 } 1631 }
1596 } 1632 }
1597 1633
1598 class Yield extends CallExpression { 1634 class Yield extends UnsafePrimitive {
1599 final Reference<Primitive> input; 1635 final Reference<Primitive> input;
1600 final Reference<Continuation> continuation;
1601 final bool hasStar; 1636 final bool hasStar;
1602 1637
1603 Yield(Primitive input, this.hasStar, Continuation continuation) 1638 Yield(Primitive input, this.hasStar)
1604 : this.input = new Reference<Primitive>(input), 1639 : this.input = new Reference<Primitive>(input);
1605 this.continuation = new Reference<Continuation>(continuation);
1606 1640
1607 @override 1641 @override
1608 accept(Visitor visitor) { 1642 accept(Visitor visitor) {
1609 return visitor.visitYield(this); 1643 return visitor.visitYield(this);
1610 } 1644 }
1611 1645
1612 void setParentPointers() { 1646 void setParentPointers() {
1613 input.parent = this; 1647 input.parent = this;
1614 continuation.parent = this;
1615 } 1648 }
1616 } 1649 }
1617 1650
1618 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { 1651 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
1619 return definitions.map((e) => new Reference<Primitive>(e)).toList(); 1652 return definitions.map((e) => new Reference<Primitive>(e)).toList();
1620 } 1653 }
1621 1654
1622 void _setParentsOnNodes(List<Node> nodes, Node parent) { 1655 void _setParentsOnNodes(List<Node> nodes, Node parent) {
1623 for (Node node in nodes) { 1656 for (Node node in nodes) {
1624 node.parent = parent; 1657 node.parent = parent;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 visitLetMutable(LetMutable node) { 1786 visitLetMutable(LetMutable node) {
1754 processLetMutable(node); 1787 processLetMutable(node);
1755 visit(node.variable); 1788 visit(node.variable);
1756 processReference(node.value); 1789 processReference(node.value);
1757 visit(node.body); 1790 visit(node.body);
1758 } 1791 }
1759 1792
1760 processInvokeStatic(InvokeStatic node) {} 1793 processInvokeStatic(InvokeStatic node) {}
1761 visitInvokeStatic(InvokeStatic node) { 1794 visitInvokeStatic(InvokeStatic node) {
1762 processInvokeStatic(node); 1795 processInvokeStatic(node);
1763 processReference(node.continuation);
1764 node.arguments.forEach(processReference); 1796 node.arguments.forEach(processReference);
1765 } 1797 }
1766 1798
1767 processInvokeContinuation(InvokeContinuation node) {} 1799 processInvokeContinuation(InvokeContinuation node) {}
1768 visitInvokeContinuation(InvokeContinuation node) { 1800 visitInvokeContinuation(InvokeContinuation node) {
1769 processInvokeContinuation(node); 1801 processInvokeContinuation(node);
1770 processReference(node.continuation); 1802 processReference(node.continuation);
1771 node.arguments.forEach(processReference); 1803 node.arguments.forEach(processReference);
1772 } 1804 }
1773 1805
1774 processInvokeMethod(InvokeMethod node) {} 1806 processInvokeMethod(InvokeMethod node) {}
1775 visitInvokeMethod(InvokeMethod node) { 1807 visitInvokeMethod(InvokeMethod node) {
1776 processInvokeMethod(node); 1808 processInvokeMethod(node);
1777 processReference(node.receiver); 1809 processReference(node.receiver);
1778 processReference(node.continuation);
1779 node.arguments.forEach(processReference); 1810 node.arguments.forEach(processReference);
1780 } 1811 }
1781 1812
1782 processInvokeMethodDirectly(InvokeMethodDirectly node) {} 1813 processInvokeMethodDirectly(InvokeMethodDirectly node) {}
1783 visitInvokeMethodDirectly(InvokeMethodDirectly node) { 1814 visitInvokeMethodDirectly(InvokeMethodDirectly node) {
1784 processInvokeMethodDirectly(node); 1815 processInvokeMethodDirectly(node);
1785 processReference(node.receiver); 1816 processReference(node.receiver);
1786 processReference(node.continuation);
1787 node.arguments.forEach(processReference); 1817 node.arguments.forEach(processReference);
1788 } 1818 }
1789 1819
1790 processInvokeConstructor(InvokeConstructor node) {} 1820 processInvokeConstructor(InvokeConstructor node) {}
1791 visitInvokeConstructor(InvokeConstructor node) { 1821 visitInvokeConstructor(InvokeConstructor node) {
1792 processInvokeConstructor(node); 1822 processInvokeConstructor(node);
1793 processReference(node.continuation);
1794 node.arguments.forEach(processReference); 1823 node.arguments.forEach(processReference);
1795 } 1824 }
1796 1825
1797 processThrow(Throw node) {} 1826 processThrow(Throw node) {}
1798 visitThrow(Throw node) { 1827 visitThrow(Throw node) {
1799 processThrow(node); 1828 processThrow(node);
1800 processReference(node.value); 1829 processReference(node.value);
1801 } 1830 }
1802 1831
1803 processRethrow(Rethrow node) {} 1832 processRethrow(Rethrow node) {}
1804 visitRethrow(Rethrow node) { 1833 visitRethrow(Rethrow node) {
1805 processRethrow(node); 1834 processRethrow(node);
1806 } 1835 }
1807 1836
1808 processBranch(Branch node) {} 1837 processBranch(Branch node) {}
1809 visitBranch(Branch node) { 1838 visitBranch(Branch node) {
1810 processBranch(node); 1839 processBranch(node);
1811 processReference(node.trueContinuation); 1840 processReference(node.trueContinuation);
1812 processReference(node.falseContinuation); 1841 processReference(node.falseContinuation);
1813 processReference(node.condition); 1842 processReference(node.condition);
1814 } 1843 }
1815 1844
1816 processTypeCast(TypeCast node) {} 1845 processTypeCast(TypeCast node) {}
1817 visitTypeCast(TypeCast node) { 1846 visitTypeCast(TypeCast node) {
1818 processTypeCast(node); 1847 processTypeCast(node);
1819 processReference(node.continuation);
1820 processReference(node.value); 1848 processReference(node.value);
1821 node.typeArguments.forEach(processReference); 1849 node.typeArguments.forEach(processReference);
1822 } 1850 }
1823 1851
1824 processTypeTest(TypeTest node) {} 1852 processTypeTest(TypeTest node) {}
1825 visitTypeTest(TypeTest node) { 1853 visitTypeTest(TypeTest node) {
1826 processTypeTest(node); 1854 processTypeTest(node);
1827 processReference(node.value); 1855 processReference(node.value);
1828 if (node.interceptor != null) processReference(node.interceptor); 1856 if (node.interceptor != null) processReference(node.interceptor);
1829 node.typeArguments.forEach(processReference); 1857 node.typeArguments.forEach(processReference);
1830 } 1858 }
1831 1859
1832 processTypeTestViaFlag(TypeTestViaFlag node) {} 1860 processTypeTestViaFlag(TypeTestViaFlag node) {}
1833 visitTypeTestViaFlag(TypeTestViaFlag node) { 1861 visitTypeTestViaFlag(TypeTestViaFlag node) {
1834 processTypeTestViaFlag(node); 1862 processTypeTestViaFlag(node);
1835 processReference(node.interceptor); 1863 processReference(node.interceptor);
1836 } 1864 }
1837 1865
1838 processSetMutable(SetMutable node) {} 1866 processSetMutable(SetMutable node) {}
1839 visitSetMutable(SetMutable node) { 1867 visitSetMutable(SetMutable node) {
1840 processSetMutable(node); 1868 processSetMutable(node);
1841 processReference(node.variable); 1869 processReference(node.variable);
1842 processReference(node.value); 1870 processReference(node.value);
1843 } 1871 }
1844 1872
1845 processGetLazyStatic(GetLazyStatic node) {} 1873 processGetLazyStatic(GetLazyStatic node) {}
1846 visitGetLazyStatic(GetLazyStatic node) { 1874 visitGetLazyStatic(GetLazyStatic node) {
1847 processGetLazyStatic(node); 1875 processGetLazyStatic(node);
1848 processReference(node.continuation);
1849 } 1876 }
1850 1877
1851 processLiteralList(LiteralList node) {} 1878 processLiteralList(LiteralList node) {}
1852 visitLiteralList(LiteralList node) { 1879 visitLiteralList(LiteralList node) {
1853 processLiteralList(node); 1880 processLiteralList(node);
1854 node.values.forEach(processReference); 1881 node.values.forEach(processReference);
1855 } 1882 }
1856 1883
1857 processLiteralMap(LiteralMap node) {} 1884 processLiteralMap(LiteralMap node) {}
1858 visitLiteralMap(LiteralMap node) { 1885 visitLiteralMap(LiteralMap node) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 processApplyBuiltinMethod(ApplyBuiltinMethod node) {} 1992 processApplyBuiltinMethod(ApplyBuiltinMethod node) {}
1966 visitApplyBuiltinMethod(ApplyBuiltinMethod node) { 1993 visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
1967 processApplyBuiltinMethod(node); 1994 processApplyBuiltinMethod(node);
1968 processReference(node.receiver); 1995 processReference(node.receiver);
1969 node.arguments.forEach(processReference); 1996 node.arguments.forEach(processReference);
1970 } 1997 }
1971 1998
1972 processForeignCode(ForeignCode node) {} 1999 processForeignCode(ForeignCode node) {}
1973 visitForeignCode(ForeignCode node) { 2000 visitForeignCode(ForeignCode node) {
1974 processForeignCode(node); 2001 processForeignCode(node);
1975 if (node.continuation != null) {
1976 processReference(node.continuation);
1977 }
1978 node.arguments.forEach(processReference); 2002 node.arguments.forEach(processReference);
1979 } 2003 }
1980 2004
1981 processUnreachable(Unreachable node) {} 2005 processUnreachable(Unreachable node) {}
1982 visitUnreachable(Unreachable node) { 2006 visitUnreachable(Unreachable node) {
1983 processUnreachable(node); 2007 processUnreachable(node);
1984 } 2008 }
1985 2009
1986 processAwait(Await node) {} 2010 processAwait(Await node) {}
1987 visitAwait(Await node) { 2011 visitAwait(Await node) {
1988 processAwait(node); 2012 processAwait(node);
1989 processReference(node.input); 2013 processReference(node.input);
1990 processReference(node.continuation);
1991 } 2014 }
1992 2015
1993 processYield(Yield node) {} 2016 processYield(Yield node) {}
1994 visitYield(Yield node) { 2017 visitYield(Yield node) {
1995 processYield(node); 2018 processYield(node);
1996 processReference(node.input); 2019 processReference(node.input);
1997 processReference(node.continuation);
1998 } 2020 }
1999 2021
2000 processGetLength(GetLength node) {} 2022 processGetLength(GetLength node) {}
2001 visitGetLength(GetLength node) { 2023 visitGetLength(GetLength node) {
2002 processGetLength(node); 2024 processGetLength(node);
2003 processReference(node.object); 2025 processReference(node.object);
2004 } 2026 }
2005 2027
2006 processGetIndex(GetIndex node) {} 2028 processGetIndex(GetIndex node) {}
2007 visitGetIndex(GetIndex node) { 2029 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. 2171 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
2150 class RemovalVisitor extends TrampolineRecursiveVisitor { 2172 class RemovalVisitor extends TrampolineRecursiveVisitor {
2151 processReference(Reference reference) { 2173 processReference(Reference reference) {
2152 reference.unlink(); 2174 reference.unlink();
2153 } 2175 }
2154 2176
2155 static void remove(Node node) { 2177 static void remove(Node node) {
2156 (new RemovalVisitor()).visit(node); 2178 (new RemovalVisitor()).visit(node);
2157 } 2179 }
2158 } 2180 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698