OLD | NEW |
---|---|
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 'cps_fragment.dart' show CpsFragment; | 7 import 'cps_fragment.dart' show CpsFragment; |
8 import 'cps_ir_nodes_sexpr.dart'; | 8 import 'cps_ir_nodes_sexpr.dart'; |
9 import '../constants/values.dart' as values; | 9 import '../constants/values.dart' as values; |
10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 10 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 bool get isSafeForElimination; | 260 bool get isSafeForElimination; |
261 | 261 |
262 /// True if time-of-evaluation is irrelevant for the given primitive, | 262 /// True if time-of-evaluation is irrelevant for the given primitive, |
263 /// assuming its inputs are the same values. | 263 /// assuming its inputs are the same values. |
264 bool get isSafeForReordering; | 264 bool get isSafeForReordering; |
265 | 265 |
266 /// The source information associated with this primitive. | 266 /// The source information associated with this primitive. |
267 // TODO(johnniwinther): Require source information for all primitives. | 267 // TODO(johnniwinther): Require source information for all primitives. |
268 SourceInformation get sourceInformation => null; | 268 SourceInformation get sourceInformation => null; |
269 | 269 |
270 /// If this is a [Refinement], [BoundsCheck] or [ReceiverCheck] node, returns the | 270 /// If this is a [Refinement], [BoundsCheck] or [ReceiverCheck] node, returns |
271 /// value being refined, the indexable object being checked, or the value | 271 /// the value being refined, the indexable object being checked, or the value |
272 /// that was checked to be non-null, respectively. | 272 /// that was checked to be non-null, respectively. |
273 /// | 273 /// |
274 /// Those instructions all return the corresponding operand directly, and | 274 /// Those instructions all return the corresponding operand directly, and |
275 /// this getter can be used to get (closer to) where the value came from. | 275 /// this getter can be used to get (closer to) where the value came from. |
276 // | 276 // |
277 // TODO(asgerf): Also do this for [TypeCast]? | 277 // TODO(asgerf): Also do this for [TypeCast]? |
278 Primitive get effectiveDefinition => this; | 278 Primitive get effectiveDefinition => this; |
279 | 279 |
280 /// Like [effectiveDefinition] but only unfolds [Refinement] nodes. | 280 /// Like [effectiveDefinition] but only unfolds [Refinement] nodes. |
281 Primitive get unrefined => this; | 281 Primitive get unrefined => this; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 /// | 489 /// |
490 /// let mutable v = P in E | 490 /// let mutable v = P in E |
491 /// | 491 /// |
492 /// [MutableVariable]s can be seen as ref cells that are not first-class | 492 /// [MutableVariable]s can be seen as ref cells that are not first-class |
493 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] | 493 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] |
494 /// to prevent unrestricted use of references to them. During one-pass | 494 /// to prevent unrestricted use of references to them. During one-pass |
495 /// construction, a [LetMutable] with an empty body is use to represent the | 495 /// construction, a [LetMutable] with an empty body is use to represent the |
496 /// one-hole context 'let mutable v = P in []'. | 496 /// one-hole context 'let mutable v = P in []'. |
497 class LetMutable extends InteriorExpression { | 497 class LetMutable extends InteriorExpression { |
498 final MutableVariable variable; | 498 final MutableVariable variable; |
499 final Reference<Primitive> value; | 499 final Reference<Primitive> valueRef; |
sra1
2016/03/01 17:59:53
valueReference
| |
500 Expression body; | 500 Expression body; |
501 | 501 |
502 Primitive get value => valueRef.definition; | |
503 | |
502 LetMutable(this.variable, Primitive value) | 504 LetMutable(this.variable, Primitive value) |
503 : this.value = new Reference<Primitive>(value); | 505 : this.valueRef = new Reference<Primitive>(value); |
504 | 506 |
505 Expression plug(Expression expr) { | 507 Expression plug(Expression expr) { |
506 return body = expr; | 508 return body = expr; |
507 } | 509 } |
508 | 510 |
509 accept(BlockVisitor visitor) => visitor.visitLetMutable(this); | 511 accept(BlockVisitor visitor) => visitor.visitLetMutable(this); |
510 | 512 |
511 void setParentPointers() { | 513 void setParentPointers() { |
512 variable.parent = this; | 514 variable.parent = this; |
513 value.parent = this; | 515 valueRef.parent = this; |
514 if (body != null) body.parent = this; | 516 if (body != null) body.parent = this; |
515 } | 517 } |
516 } | 518 } |
517 | 519 |
518 enum CallingConvention { | 520 enum CallingConvention { |
519 /// JS receiver is the Dart receiver, there are no extra arguments. | 521 /// JS receiver is the Dart receiver, there are no extra arguments. |
520 /// | 522 /// |
521 /// This includes cases (e.g., static functions, constructors) where there | 523 /// This includes cases (e.g., static functions, constructors) where there |
522 /// is no receiver. | 524 /// is no receiver. |
523 /// | 525 /// |
(...skipping 13 matching lines...) Expand all Loading... | |
537 /// JS receiver is the Dart receiver, there are no extra arguments. | 539 /// JS receiver is the Dart receiver, there are no extra arguments. |
538 /// | 540 /// |
539 /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)` | 541 /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)` |
540 OneShotIntercepted, | 542 OneShotIntercepted, |
541 } | 543 } |
542 | 544 |
543 /// Base class of function invocations. | 545 /// Base class of function invocations. |
544 /// | 546 /// |
545 /// This class defines the common interface of function invocations. | 547 /// This class defines the common interface of function invocations. |
546 abstract class InvocationPrimitive extends UnsafePrimitive { | 548 abstract class InvocationPrimitive extends UnsafePrimitive { |
547 Reference<Primitive> get receiver => null; | 549 Reference<Primitive> get receiverRef => null; |
sra1
2016/03/01 17:59:53
receiverReference
| |
548 List<Reference<Primitive>> get arguments; | 550 Primitive get receiver => receiverRef?.definition; |
549 SourceInformation get sourceInformation; | |
550 | 551 |
551 Reference<Primitive> get dartReceiverReference => null; | 552 List<Reference<Primitive>> get argumentRefs; |
sra1
2016/03/01 17:59:53
argumentReferences
| |
552 Primitive get dartReceiver => dartReceiverReference.definition; | 553 Primitive argument(int n) => argumentRefs[n].definition; |
554 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
sra1
2016/03/01 17:59:53
I find it a surprising API choice that `arguments`
| |
555 | |
556 Reference<Primitive> get dartReceiverRef => null; | |
557 Primitive get dartReceiver => dartReceiverRef?.definition; | |
553 | 558 |
554 CallingConvention get callingConvention => CallingConvention.Normal; | 559 CallingConvention get callingConvention => CallingConvention.Normal; |
555 | 560 |
556 Reference<Primitive> dartArgumentReference(int n) { | 561 Reference<Primitive> dartArgumentReference(int n) { |
557 switch (callingConvention) { | 562 switch (callingConvention) { |
558 case CallingConvention.Normal: | 563 case CallingConvention.Normal: |
559 case CallingConvention.OneShotIntercepted: | 564 case CallingConvention.OneShotIntercepted: |
560 return arguments[n]; | 565 return argumentRefs[n]; |
561 | 566 |
562 case CallingConvention.Intercepted: | 567 case CallingConvention.Intercepted: |
563 case CallingConvention.DummyIntercepted: | 568 case CallingConvention.DummyIntercepted: |
564 return arguments[n + 1]; | 569 return argumentRefs[n + 1]; |
565 } | 570 } |
566 } | 571 } |
567 | 572 |
568 Primitive dartArgument(int n) => dartArgumentReference(n).definition; | 573 Primitive dartArgument(int n) => dartArgumentReference(n).definition; |
569 | 574 |
570 int get dartArgumentsLength => | 575 int get dartArgumentsLength => |
571 arguments.length - | 576 argumentRefs.length - |
572 (callingConvention == CallingConvention.Intercepted || | 577 (callingConvention == CallingConvention.Intercepted || |
573 callingConvention == CallingConvention.DummyIntercepted ? 1 : 0); | 578 callingConvention == CallingConvention.DummyIntercepted ? 1 : 0); |
579 | |
580 SourceInformation get sourceInformation; | |
574 } | 581 } |
575 | 582 |
576 /// Invoke a static function. | 583 /// Invoke a static function. |
577 /// | 584 /// |
578 /// All optional arguments declared by [target] are passed in explicitly, and | 585 /// All optional arguments declared by [target] are passed in explicitly, and |
579 /// occur at the end of [arguments] list, in normalized order. | 586 /// occur at the end of [arguments] list, in normalized order. |
580 /// | 587 /// |
581 /// Discussion: | 588 /// Discussion: |
582 /// All information in the [selector] is technically redundant; it will likely | 589 /// All information in the [selector] is technically redundant; it will likely |
583 /// be removed. | 590 /// be removed. |
584 class InvokeStatic extends InvocationPrimitive { | 591 class InvokeStatic extends InvocationPrimitive { |
585 final FunctionElement target; | 592 final FunctionElement target; |
586 final Selector selector; | 593 final Selector selector; |
587 final List<Reference<Primitive>> arguments; | 594 final List<Reference<Primitive>> argumentRefs; |
588 final SourceInformation sourceInformation; | 595 final SourceInformation sourceInformation; |
589 | 596 |
590 InvokeStatic(this.target, | 597 InvokeStatic(this.target, |
591 this.selector, | 598 this.selector, |
592 List<Primitive> args, | 599 List<Primitive> args, |
593 [this.sourceInformation]) | 600 [this.sourceInformation]) |
594 : arguments = _referenceList(args); | 601 : argumentRefs = _referenceList(args); |
595 | 602 |
596 InvokeStatic.byReference(this.target, | 603 InvokeStatic.byReference(this.target, |
597 this.selector, | 604 this.selector, |
598 this.arguments, | 605 this.argumentRefs, |
599 [this.sourceInformation]); | 606 [this.sourceInformation]); |
600 | 607 |
601 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 608 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
602 | 609 |
603 bool get hasValue => true; | 610 bool get hasValue => true; |
604 | 611 |
605 void setParentPointers() { | 612 void setParentPointers() { |
606 _setParentsOnList(arguments, this); | 613 _setParentsOnList(argumentRefs, this); |
607 } | 614 } |
608 } | 615 } |
609 | 616 |
610 /// Invoke a method on an object. | 617 /// Invoke a method on an object. |
611 /// | 618 /// |
612 /// This includes getters, setters, operators, and index getter/setters. | 619 /// This includes getters, setters, operators, and index getter/setters. |
613 /// | 620 /// |
614 /// Tearing off a method is treated like a getter invocation (getters and | 621 /// Tearing off a method is treated like a getter invocation (getters and |
615 /// tear-offs cannot be distinguished at compile-time). | 622 /// tear-offs cannot be distinguished at compile-time). |
616 /// | 623 /// |
617 /// The [selector] records the names of named arguments. The value of named | 624 /// The [selector] records the names of named arguments. The value of named |
618 /// arguments occur at the end of the [arguments] list, in normalized order. | 625 /// arguments occur at the end of the [arguments] list, in normalized order. |
619 class InvokeMethod extends InvocationPrimitive { | 626 class InvokeMethod extends InvocationPrimitive { |
620 Reference<Primitive> receiver; | 627 Reference<Primitive> receiverRef; |
621 Selector selector; | 628 Selector selector; |
622 TypeMask mask; | 629 TypeMask mask; |
623 final List<Reference<Primitive>> arguments; | 630 final List<Reference<Primitive>> argumentRefs; |
624 final SourceInformation sourceInformation; | 631 final SourceInformation sourceInformation; |
625 | 632 |
626 CallingConvention callingConvention = CallingConvention.Normal; | 633 CallingConvention callingConvention = CallingConvention.Normal; |
627 | 634 |
628 Reference<Primitive> get dartReceiverReference { | 635 Reference<Primitive> get dartReceiverRef { |
629 return callingConvention == CallingConvention.Intercepted | 636 return callingConvention == CallingConvention.Intercepted |
630 ? arguments[0] | 637 ? argumentRefs[0] |
631 : receiver; | 638 : receiverRef; |
632 } | 639 } |
633 | 640 |
634 /// If true, it is known that the receiver cannot be `null`. | 641 /// If true, it is known that the receiver cannot be `null`. |
635 bool receiverIsNotNull = false; | 642 bool receiverIsNotNull = false; |
636 | 643 |
637 InvokeMethod(Primitive receiver, | 644 InvokeMethod(Primitive receiver, |
638 this.selector, | 645 this.selector, |
639 this.mask, | 646 this.mask, |
640 List<Primitive> arguments, | 647 List<Primitive> arguments, |
641 {this.sourceInformation, | 648 {this.sourceInformation, |
642 this.callingConvention: CallingConvention.Normal}) | 649 this.callingConvention: CallingConvention.Normal}) |
643 : this.receiver = new Reference<Primitive>(receiver), | 650 : this.receiverRef = new Reference<Primitive>(receiver), |
644 this.arguments = _referenceList(arguments); | 651 this.argumentRefs = _referenceList(arguments); |
645 | 652 |
646 accept(Visitor visitor) => visitor.visitInvokeMethod(this); | 653 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
647 | 654 |
648 bool get hasValue => true; | 655 bool get hasValue => true; |
649 | 656 |
650 void setParentPointers() { | 657 void setParentPointers() { |
651 receiver.parent = this; | 658 receiverRef.parent = this; |
652 _setParentsOnList(arguments, this); | 659 _setParentsOnList(argumentRefs, this); |
653 } | 660 } |
654 } | 661 } |
655 | 662 |
656 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. | 663 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
657 /// | 664 /// |
658 /// That is, if [receiver] is an instance of a class that overrides [target] | 665 /// That is, if [receiver] is an instance of a class that overrides [target] |
659 /// with a different implementation, the overriding implementation is bypassed | 666 /// with a different implementation, the overriding implementation is bypassed |
660 /// and [target]'s implementation is invoked. | 667 /// and [target]'s implementation is invoked. |
661 /// | 668 /// |
662 /// As with [InvokeMethod], this can be used to invoke a method, operator, | 669 /// As with [InvokeMethod], this can be used to invoke a method, operator, |
663 /// getter, setter, or index getter/setter. | 670 /// getter, setter, or index getter/setter. |
664 /// | 671 /// |
665 /// If it is known that [target] does not use its receiver argument, then | 672 /// If it is known that [target] does not use its receiver argument, then |
666 /// [receiver] may refer to a null constant primitive. This happens for direct | 673 /// [receiver] may refer to a null constant primitive. This happens for direct |
667 /// invocations to intercepted methods, where the effective receiver is instead | 674 /// invocations to intercepted methods, where the effective receiver is instead |
668 /// passed as a formal parameter. | 675 /// passed as a formal parameter. |
669 /// | 676 /// |
670 /// TODO(sra): Review. A direct call to a method that is mixed into a native | 677 /// TODO(sra): Review. A direct call to a method that is mixed into a native |
671 /// class will still require an explicit argument. | 678 /// class will still require an explicit argument. |
672 /// | 679 /// |
673 /// All optional arguments declared by [target] are passed in explicitly, and | 680 /// All optional arguments declared by [target] are passed in explicitly, and |
674 /// occur at the end of [arguments] list, in normalized order. | 681 /// occur at the end of [arguments] list, in normalized order. |
675 class InvokeMethodDirectly extends InvocationPrimitive { | 682 class InvokeMethodDirectly extends InvocationPrimitive { |
676 Reference<Primitive> receiver; | 683 Reference<Primitive> receiverRef; |
677 final FunctionElement target; | 684 final FunctionElement target; |
678 final Selector selector; | 685 final Selector selector; |
679 final List<Reference<Primitive>> arguments; | 686 final List<Reference<Primitive>> argumentRefs; |
680 final SourceInformation sourceInformation; | 687 final SourceInformation sourceInformation; |
681 | 688 |
682 CallingConvention callingConvention; | 689 CallingConvention callingConvention; |
683 | 690 |
684 Reference<Primitive> get dartReceiverReference { | 691 Reference<Primitive> get dartReceiverRef { |
685 return callingConvention == CallingConvention.Intercepted | 692 return callingConvention == CallingConvention.Intercepted |
686 ? arguments[0] | 693 ? argumentRefs[0] |
687 : receiver; | 694 : receiverRef; |
688 } | 695 } |
689 | 696 |
690 InvokeMethodDirectly(Primitive receiver, | 697 InvokeMethodDirectly(Primitive receiver, |
691 this.target, | 698 this.target, |
692 this.selector, | 699 this.selector, |
693 List<Primitive> arguments, | 700 List<Primitive> arguments, |
694 this.sourceInformation, | 701 this.sourceInformation, |
695 {this.callingConvention: CallingConvention.Normal}) | 702 {this.callingConvention: CallingConvention.Normal}) |
696 : this.receiver = new Reference<Primitive>(receiver), | 703 : this.receiverRef = new Reference<Primitive>(receiver), |
697 this.arguments = _referenceList(arguments); | 704 this.argumentRefs = _referenceList(arguments); |
698 | 705 |
699 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); | 706 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); |
700 | 707 |
701 bool get hasValue => true; | 708 bool get hasValue => true; |
702 | 709 |
703 void setParentPointers() { | 710 void setParentPointers() { |
704 receiver.parent = this; | 711 receiverRef.parent = this; |
705 _setParentsOnList(arguments, this); | 712 _setParentsOnList(argumentRefs, this); |
706 } | 713 } |
707 | 714 |
708 bool get isConstructorBodyCall => target is ConstructorBodyElement; | 715 bool get isConstructorBodyCall => target is ConstructorBodyElement; |
709 bool get isTearOff => selector.isGetter && !target.isGetter; | 716 bool get isTearOff => selector.isGetter && !target.isGetter; |
710 } | 717 } |
711 | 718 |
712 /// Non-const call to a constructor. | 719 /// Non-const call to a constructor. |
713 /// | 720 /// |
714 /// The [target] may be a generative constructor (forwarding or normal) | 721 /// The [target] may be a generative constructor (forwarding or normal) |
715 /// or a non-redirecting factory. | 722 /// or a non-redirecting factory. |
716 /// | 723 /// |
717 /// All optional arguments declared by [target] are passed in explicitly, and | 724 /// All optional arguments declared by [target] are passed in explicitly, and |
718 /// occur in the [arguments] list, in normalized order. | 725 /// occur in the [arguments] list, in normalized order. |
719 /// | 726 /// |
720 /// Last in the [arguments] list, after the mandatory and optional arguments, | 727 /// Last in the [arguments] list, after the mandatory and optional arguments, |
721 /// the internal representation of each type argument occurs, unless it could | 728 /// the internal representation of each type argument occurs, unless it could |
722 /// be determined at build-time that the constructed class has no need for its | 729 /// be determined at build-time that the constructed class has no need for its |
723 /// runtime type information. | 730 /// runtime type information. |
724 /// | 731 /// |
725 /// Note that [InvokeConstructor] does it itself allocate an object. | 732 /// Note that [InvokeConstructor] does it itself allocate an object. |
726 /// The invoked constructor will do that using [CreateInstance]. | 733 /// The invoked constructor will do that using [CreateInstance]. |
727 class InvokeConstructor extends InvocationPrimitive { | 734 class InvokeConstructor extends InvocationPrimitive { |
728 final DartType dartType; | 735 final DartType dartType; |
729 final ConstructorElement target; | 736 final ConstructorElement target; |
730 final List<Reference<Primitive>> arguments; | 737 final List<Reference<Primitive>> argumentRefs; |
731 final Selector selector; | 738 final Selector selector; |
732 final SourceInformation sourceInformation; | 739 final SourceInformation sourceInformation; |
733 | 740 |
734 /// If non-null, this is an allocation site-specific type that is potentially | 741 /// If non-null, this is an allocation site-specific type that is potentially |
735 /// better than the inferred return type of [target]. | 742 /// better than the inferred return type of [target]. |
736 /// | 743 /// |
737 /// In particular, container type masks depend on the allocation site and | 744 /// In particular, container type masks depend on the allocation site and |
738 /// can therefore not be inferred solely based on the call target. | 745 /// can therefore not be inferred solely based on the call target. |
739 TypeMask allocationSiteType; | 746 TypeMask allocationSiteType; |
740 | 747 |
741 InvokeConstructor(this.dartType, | 748 InvokeConstructor(this.dartType, |
742 this.target, | 749 this.target, |
743 this.selector, | 750 this.selector, |
744 List<Primitive> args, | 751 List<Primitive> args, |
745 this.sourceInformation, | 752 this.sourceInformation, |
746 {this.allocationSiteType}) | 753 {this.allocationSiteType}) |
747 : arguments = _referenceList(args); | 754 : argumentRefs = _referenceList(args); |
748 | 755 |
749 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); | 756 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); |
750 | 757 |
751 bool get hasValue => true; | 758 bool get hasValue => true; |
752 | 759 |
753 void setParentPointers() { | 760 void setParentPointers() { |
754 _setParentsOnList(arguments, this); | 761 _setParentsOnList(argumentRefs, this); |
755 } | 762 } |
756 } | 763 } |
757 | 764 |
758 /// An alias for [value] in a context where the value is known to satisfy | 765 /// An alias for [value] in a context where the value is known to satisfy |
759 /// [type]. | 766 /// [type]. |
760 /// | 767 /// |
761 /// Refinement nodes are inserted before the type propagator pass and removed | 768 /// Refinement nodes are inserted before the type propagator pass and removed |
762 /// afterwards, so as not to complicate passes that don't reason about types, | 769 /// afterwards, so as not to complicate passes that don't reason about types, |
763 /// but need to reason about value references being identical (i.e. referring | 770 /// but need to reason about value references being identical (i.e. referring |
764 /// to the same primitive). | 771 /// to the same primitive). |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
808 /// | 815 /// |
809 /// The [index] reference may be null if there are no checks to perform, | 816 /// The [index] reference may be null if there are no checks to perform, |
810 /// and the [length] reference may be null if there is no upper bound or | 817 /// and the [length] reference may be null if there is no upper bound or |
811 /// emptiness check. | 818 /// emptiness check. |
812 /// | 819 /// |
813 /// If a separate code motion guard for the index is required, e.g. because it | 820 /// If a separate code motion guard for the index is required, e.g. because it |
814 /// must be known to be non-negative in an operator that does not involve | 821 /// must be known to be non-negative in an operator that does not involve |
815 /// [object], a [Refinement] can be created for it with the non-negative integer | 822 /// [object], a [Refinement] can be created for it with the non-negative integer |
816 /// type. | 823 /// type. |
817 class BoundsCheck extends Primitive { | 824 class BoundsCheck extends Primitive { |
818 final Reference<Primitive> object; | 825 final Reference<Primitive> objectRef; |
819 Reference<Primitive> index; | 826 Reference<Primitive> indexRef; |
820 Reference<Primitive> length; | 827 Reference<Primitive> lengthRef; |
821 int checks; | 828 int checks; |
822 final SourceInformation sourceInformation; | 829 final SourceInformation sourceInformation; |
823 | 830 |
831 Primitive get object => objectRef.definition; | |
832 Primitive get index => indexRef?.definition; | |
833 Primitive get length => lengthRef?.definition; | |
834 | |
824 /// If true, check that `index >= 0`. | 835 /// If true, check that `index >= 0`. |
825 bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0; | 836 bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0; |
826 | 837 |
827 /// If true, check that `index < object.length`. | 838 /// If true, check that `index < object.length`. |
828 bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0; | 839 bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0; |
829 | 840 |
830 /// If true, check that `object.length !== 0`. | 841 /// If true, check that `object.length !== 0`. |
831 /// | 842 /// |
832 /// Equivalent to a lower bound check with `object.length - 1` as the index, | 843 /// Equivalent to a lower bound check with `object.length - 1` as the index, |
833 /// but this check is faster. | 844 /// but this check is faster. |
(...skipping 13 matching lines...) Expand all Loading... | |
847 | 858 |
848 static const int UPPER_BOUND = 1 << 0; | 859 static const int UPPER_BOUND = 1 << 0; |
849 static const int LOWER_BOUND = 1 << 1; | 860 static const int LOWER_BOUND = 1 << 1; |
850 static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck]. | 861 static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck]. |
851 static const int INTEGER = 1 << 3; // Check if index is an int. | 862 static const int INTEGER = 1 << 3; // Check if index is an int. |
852 static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND; | 863 static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND; |
853 static const int NONE = 0; | 864 static const int NONE = 0; |
854 | 865 |
855 BoundsCheck(Primitive object, Primitive index, Primitive length, | 866 BoundsCheck(Primitive object, Primitive index, Primitive length, |
856 [this.checks = BOTH_BOUNDS, this.sourceInformation]) | 867 [this.checks = BOTH_BOUNDS, this.sourceInformation]) |
857 : this.object = new Reference<Primitive>(object), | 868 : this.objectRef = new Reference<Primitive>(object), |
858 this.index = new Reference<Primitive>(index), | 869 this.indexRef = new Reference<Primitive>(index), |
859 this.length = length == null ? null : new Reference<Primitive>(length); | 870 this.lengthRef = _optionalReference(length); |
860 | 871 |
861 BoundsCheck.noCheck(Primitive object, [this.sourceInformation]) | 872 BoundsCheck.noCheck(Primitive object, [this.sourceInformation]) |
862 : this.object = new Reference<Primitive>(object), | 873 : this.objectRef = new Reference<Primitive>(object), |
863 this.checks = NONE; | 874 this.checks = NONE; |
864 | 875 |
865 accept(Visitor visitor) => visitor.visitBoundsCheck(this); | 876 accept(Visitor visitor) => visitor.visitBoundsCheck(this); |
866 | 877 |
867 void setParentPointers() { | 878 void setParentPointers() { |
868 object.parent = this; | 879 objectRef.parent = this; |
869 if (index != null) { | 880 if (indexRef != null) { |
870 index.parent = this; | 881 indexRef.parent = this; |
871 } | 882 } |
872 if (length != null) { | 883 if (lengthRef != null) { |
873 length.parent = this; | 884 lengthRef.parent = this; |
874 } | 885 } |
875 } | 886 } |
876 | 887 |
877 String get checkString { | 888 String get checkString { |
878 if (hasNoChecks) return 'no-check'; | 889 if (hasNoChecks) return 'no-check'; |
879 return [hasUpperBoundCheck ? 'upper' : null, | 890 return [hasUpperBoundCheck ? 'upper' : null, |
880 hasLowerBoundCheck ? 'lower' : null, | 891 hasLowerBoundCheck ? 'lower' : null, |
881 hasEmptinessCheck ? 'emptiness' : null, | 892 hasEmptinessCheck ? 'emptiness' : null, |
882 hasIntegerCheck ? 'integer' : null, | 893 hasIntegerCheck ? 'integer' : null, |
883 'check'] | 894 'check'] |
884 .where((x) => x != null).join('-'); | 895 .where((x) => x != null).join('-'); |
885 } | 896 } |
886 | 897 |
887 bool get isSafeForElimination => checks == NONE; | 898 bool get isSafeForElimination => checks == NONE; |
888 bool get isSafeForReordering => false; | 899 bool get isSafeForReordering => false; |
889 bool get hasValue => true; // Can be referenced to restrict code motion. | 900 bool get hasValue => true; // Can be referenced to restrict code motion. |
890 | 901 |
891 Primitive get effectiveDefinition => object.definition.effectiveDefinition; | 902 Primitive get effectiveDefinition => object.effectiveDefinition; |
892 } | 903 } |
893 | 904 |
894 /// Throw a [NoSuchMethodError] if [value] cannot respond to [selector]. | 905 /// Throw a [NoSuchMethodError] if [value] cannot respond to [selector]. |
895 /// | 906 /// |
896 /// Returns [value] so this can be used to restrict code motion. | 907 /// Returns [value] so this can be used to restrict code motion. |
897 /// | 908 /// |
898 /// The check can take one of three forms: | 909 /// The check can take one of three forms: |
899 /// | 910 /// |
900 /// value.toString; | 911 /// value.toString; |
901 /// value.selectorName; | 912 /// value.selectorName; |
902 /// value.selectorName(); (should only be used if check always fails) | 913 /// value.selectorName(); (should only be used if check always fails) |
903 /// | 914 /// |
904 /// The first two forms are used when it is known that only null fails the | 915 /// The first two forms are used when it is known that only null fails the |
905 /// check. Additionally, the check may be guarded by a [condition], allowing | 916 /// check. Additionally, the check may be guarded by a [condition], allowing |
906 /// for three more forms: | 917 /// for three more forms: |
907 /// | 918 /// |
908 /// if (condition) value.toString; (this form is valid but unused) | 919 /// if (condition) value.toString; (this form is valid but unused) |
909 /// if (condition) value.selectorName; | 920 /// if (condition) value.selectorName; |
910 /// if (condition) value.selectorName(); | 921 /// if (condition) value.selectorName(); |
911 /// | 922 /// |
912 /// The condition must be true if and only if the check should fail. It should | 923 /// The condition must be true if and only if the check should fail. It should |
913 /// ideally be of a form understood by JS engines, e.g. a `typeof` test. | 924 /// ideally be of a form understood by JS engines, e.g. a `typeof` test. |
914 /// | 925 /// |
915 /// If [useSelector] is false, the first form instead becomes `value.toString;`. | 926 /// If [useSelector] is false, the first form instead becomes `value.toString;`. |
916 /// This form is faster when the value is non-null and the accessed property has | 927 /// This form is faster when the value is non-null and the accessed property has |
917 /// been removed by tree shaking. | 928 /// been removed by tree shaking. |
918 /// | 929 /// |
919 /// [selector] may not be one of the selectors implemented by the null object. | 930 /// [selector] may not be one of the selectors implemented by the null object. |
920 class ReceiverCheck extends Primitive { | 931 class ReceiverCheck extends Primitive { |
921 final Reference<Primitive> value; | 932 final Reference<Primitive> valueRef; |
922 final Selector selector; | 933 final Selector selector; |
923 final SourceInformation sourceInformation; | 934 final SourceInformation sourceInformation; |
924 final Reference<Primitive> condition; | 935 final Reference<Primitive> conditionRef; |
925 final int _flags; | 936 final int _flags; |
926 | 937 |
938 Primitive get value => valueRef.definition; | |
939 Primitive get condition => conditionRef?.definition; | |
940 | |
927 static const int _USE_SELECTOR = 1 << 0; | 941 static const int _USE_SELECTOR = 1 << 0; |
928 static const int _NULL_CHECK = 1 << 1; | 942 static const int _NULL_CHECK = 1 << 1; |
929 | 943 |
930 /// True if the selector name should be used in the check; otherwise | 944 /// True if the selector name should be used in the check; otherwise |
931 /// `toString` will be used. | 945 /// `toString` will be used. |
932 bool get useSelector => _flags & _USE_SELECTOR != 0; | 946 bool get useSelector => _flags & _USE_SELECTOR != 0; |
933 | 947 |
934 /// True if null is the only possible input that cannot respond to [selector]. | 948 /// True if null is the only possible input that cannot respond to [selector]. |
935 bool get isNullCheck => _flags & _NULL_CHECK != 0; | 949 bool get isNullCheck => _flags & _NULL_CHECK != 0; |
936 | 950 |
937 | 951 |
938 /// Constructor for creating checks in arbitrary configurations. | 952 /// Constructor for creating checks in arbitrary configurations. |
939 /// | 953 /// |
940 /// Consider using one of the named constructors instead. | 954 /// Consider using one of the named constructors instead. |
941 /// | 955 /// |
942 /// [useSelector] and [isNullCheck] are mandatory named arguments. | 956 /// [useSelector] and [isNullCheck] are mandatory named arguments. |
943 ReceiverCheck(Primitive value, this.selector, this.sourceInformation, | 957 ReceiverCheck(Primitive value, this.selector, this.sourceInformation, |
944 {Primitive condition, bool useSelector, bool isNullCheck}) | 958 {Primitive condition, bool useSelector, bool isNullCheck}) |
945 : value = new Reference<Primitive>(value), | 959 : valueRef = new Reference<Primitive>(value), |
946 condition = _optionalReference(condition), | 960 conditionRef = _optionalReference(condition), |
947 _flags = (useSelector ? _USE_SELECTOR : 0) | | 961 _flags = (useSelector ? _USE_SELECTOR : 0) | |
948 (isNullCheck ? _NULL_CHECK : 0); | 962 (isNullCheck ? _NULL_CHECK : 0); |
949 | 963 |
950 /// Simplified constructor for building null checks. | 964 /// Simplified constructor for building null checks. |
951 /// | 965 /// |
952 /// Null must be the only possible input value that does not respond to | 966 /// Null must be the only possible input value that does not respond to |
953 /// [selector]. | 967 /// [selector]. |
954 ReceiverCheck.nullCheck( | 968 ReceiverCheck.nullCheck( |
955 Primitive value, | 969 Primitive value, |
956 Selector selector, | 970 Selector selector, |
(...skipping 22 matching lines...) Expand all Loading... | |
979 useSelector: true, | 993 useSelector: true, |
980 isNullCheck: false); | 994 isNullCheck: false); |
981 | 995 |
982 bool get isSafeForElimination => false; | 996 bool get isSafeForElimination => false; |
983 bool get isSafeForReordering => false; | 997 bool get isSafeForReordering => false; |
984 bool get hasValue => true; | 998 bool get hasValue => true; |
985 | 999 |
986 accept(Visitor visitor) => visitor.visitReceiverCheck(this); | 1000 accept(Visitor visitor) => visitor.visitReceiverCheck(this); |
987 | 1001 |
988 void setParentPointers() { | 1002 void setParentPointers() { |
989 value.parent = this; | 1003 valueRef.parent = this; |
990 if (condition != null) { | 1004 if (conditionRef != null) { |
991 condition.parent = this; | 1005 conditionRef.parent = this; |
992 } | 1006 } |
993 } | 1007 } |
994 | 1008 |
995 Primitive get effectiveDefinition => value.definition.effectiveDefinition; | 1009 Primitive get effectiveDefinition => value.effectiveDefinition; |
996 | 1010 |
997 String get nullCheckString => isNullCheck ? 'null-check' : 'general-check'; | 1011 String get nullCheckString => isNullCheck ? 'null-check' : 'general-check'; |
998 String get useSelectorString => useSelector ? 'use-selector' : 'no-selector'; | 1012 String get useSelectorString => useSelector ? 'use-selector' : 'no-selector'; |
999 String get flagString => '$nullCheckString $useSelectorString'; | 1013 String get flagString => '$nullCheckString $useSelectorString'; |
1000 } | 1014 } |
1001 | 1015 |
1002 /// An "is" type test. | 1016 /// An "is" type test. |
1003 /// | 1017 /// |
1004 /// Returns `true` if [value] is an instance of [dartType]. | 1018 /// Returns `true` if [value] is an instance of [dartType]. |
1005 /// | 1019 /// |
1006 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might | 1020 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might |
1007 /// be a type variable containing one of these types). This design is chosen | 1021 /// be a type variable containing one of these types). This design is chosen |
1008 /// to simplify code generation for type tests. | 1022 /// to simplify code generation for type tests. |
1009 class TypeTest extends Primitive { | 1023 class TypeTest extends Primitive { |
1010 Reference<Primitive> value; | 1024 Reference<Primitive> valueRef; |
1011 final DartType dartType; | 1025 final DartType dartType; |
1012 | 1026 |
1013 /// If [dartType] is an [InterfaceType], this holds the internal | 1027 /// If [dartType] is an [InterfaceType], this holds the internal |
1014 /// representation of the type arguments to [dartType]. Since these may | 1028 /// representation of the type arguments to [dartType]. Since these may |
1015 /// reference type variables from the enclosing class, they are not constant. | 1029 /// reference type variables from the enclosing class, they are not constant. |
1016 /// | 1030 /// |
1017 /// If [dartType] is a [TypeVariableType], this is a singleton list with the | 1031 /// If [dartType] is a [TypeVariableType], this is a singleton list with the |
1018 /// internal representation of the type held in that type variable. | 1032 /// internal representation of the type held in that type variable. |
1019 /// | 1033 /// |
1020 /// If [dartType] is a [FunctionType], this is a singleton list with the | 1034 /// If [dartType] is a [FunctionType], this is a singleton list with the |
1021 /// internal representation of that type, | 1035 /// internal representation of that type, |
1022 /// | 1036 /// |
1023 /// Otherwise the list is empty. | 1037 /// Otherwise the list is empty. |
1024 final List<Reference<Primitive>> typeArguments; | 1038 final List<Reference<Primitive>> typeArgumentRefs; |
1039 | |
1040 Primitive get value => valueRef.definition; | |
1041 Primitive typeArgument(int n) => typeArgumentRefs[n].definition; | |
1042 Iterable<Primitive> get typeArguments => _dereferenceList(typeArgumentRefs); | |
1025 | 1043 |
1026 TypeTest(Primitive value, | 1044 TypeTest(Primitive value, |
1027 this.dartType, | 1045 this.dartType, |
1028 List<Primitive> typeArguments) | 1046 List<Primitive> typeArguments) |
1029 : this.value = new Reference<Primitive>(value), | 1047 : this.valueRef = new Reference<Primitive>(value), |
1030 this.typeArguments = _referenceList(typeArguments); | 1048 this.typeArgumentRefs = _referenceList(typeArguments); |
1031 | 1049 |
1032 accept(Visitor visitor) => visitor.visitTypeTest(this); | 1050 accept(Visitor visitor) => visitor.visitTypeTest(this); |
1033 | 1051 |
1034 bool get hasValue => true; | 1052 bool get hasValue => true; |
1035 bool get isSafeForElimination => true; | 1053 bool get isSafeForElimination => true; |
1036 bool get isSafeForReordering => true; | 1054 bool get isSafeForReordering => true; |
1037 | 1055 |
1038 void setParentPointers() { | 1056 void setParentPointers() { |
1039 value.parent = this; | 1057 valueRef.parent = this; |
1040 _setParentsOnList(typeArguments, this); | 1058 _setParentsOnList(typeArgumentRefs, this); |
1041 } | 1059 } |
1042 } | 1060 } |
1043 | 1061 |
1044 /// An "is" type test for a raw type, performed by testing a flag property. | 1062 /// An "is" type test for a raw type, performed by testing a flag property. |
1045 /// | 1063 /// |
1046 /// Returns `true` if [interceptor] is for [dartType]. | 1064 /// Returns `true` if [interceptor] is for [dartType]. |
1047 class TypeTestViaFlag extends Primitive { | 1065 class TypeTestViaFlag extends Primitive { |
1048 Reference<Primitive> interceptor; | 1066 Reference<Primitive> interceptorRef; |
1049 final DartType dartType; | 1067 final DartType dartType; |
1050 | 1068 |
1069 Primitive get interceptor => interceptorRef.definition; | |
1070 | |
1051 TypeTestViaFlag(Primitive interceptor, this.dartType) | 1071 TypeTestViaFlag(Primitive interceptor, this.dartType) |
1052 : this.interceptor = new Reference<Primitive>(interceptor); | 1072 : this.interceptorRef = new Reference<Primitive>(interceptor); |
1053 | 1073 |
1054 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this); | 1074 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this); |
1055 | 1075 |
1056 bool get hasValue => true; | 1076 bool get hasValue => true; |
1057 bool get isSafeForElimination => true; | 1077 bool get isSafeForElimination => true; |
1058 bool get isSafeForReordering => true; | 1078 bool get isSafeForReordering => true; |
1059 | 1079 |
1060 void setParentPointers() { | 1080 void setParentPointers() { |
1061 interceptor.parent = this; | 1081 interceptorRef.parent = this; |
1062 } | 1082 } |
1063 } | 1083 } |
1064 | 1084 |
1065 /// An "as" type cast. | 1085 /// An "as" type cast. |
1066 /// | 1086 /// |
1067 /// If [value] is `null` or is an instance of [type], [continuation] is invoked | 1087 /// If [value] is `null` or is an instance of [type], [continuation] is invoked |
1068 /// with [value] as argument. Otherwise, a [CastError] is thrown. | 1088 /// with [value] as argument. Otherwise, a [CastError] is thrown. |
1069 /// | 1089 /// |
1070 /// Discussion: | 1090 /// Discussion: |
1071 /// The parameter to [continuation] is redundant since it will always equal | 1091 /// The parameter to [continuation] is redundant since it will always equal |
1072 /// [value], which is typically in scope in the continuation. However, it might | 1092 /// [value], which is typically in scope in the continuation. However, it might |
1073 /// simplify type propagation, since a better type can be computed for the | 1093 /// simplify type propagation, since a better type can be computed for the |
1074 /// continuation parameter without needing flow-sensitive analysis. | 1094 /// continuation parameter without needing flow-sensitive analysis. |
1075 class TypeCast extends UnsafePrimitive { | 1095 class TypeCast extends UnsafePrimitive { |
1076 Reference<Primitive> value; | 1096 Reference<Primitive> valueRef; |
1077 final DartType dartType; | 1097 final DartType dartType; |
1078 | 1098 |
1079 /// See the corresponding field on [TypeTest]. | 1099 /// See the corresponding field on [TypeTest]. |
1080 final List<Reference<Primitive>> typeArguments; | 1100 final List<Reference<Primitive>> typeArgumentRefs; |
1101 | |
1102 Primitive get value => valueRef.definition; | |
1103 Primitive typeArgument(int n) => typeArgumentRefs[n].definition; | |
1104 Iterable<Primitive> get typeArguments => _dereferenceList(typeArgumentRefs); | |
1081 | 1105 |
1082 TypeCast(Primitive value, | 1106 TypeCast(Primitive value, |
1083 this.dartType, | 1107 this.dartType, |
1084 List<Primitive> typeArguments) | 1108 List<Primitive> typeArguments) |
1085 : this.value = new Reference<Primitive>(value), | 1109 : this.valueRef = new Reference<Primitive>(value), |
1086 this.typeArguments = _referenceList(typeArguments); | 1110 this.typeArgumentRefs = _referenceList(typeArguments); |
1087 | 1111 |
1088 accept(Visitor visitor) => visitor.visitTypeCast(this); | 1112 accept(Visitor visitor) => visitor.visitTypeCast(this); |
1089 | 1113 |
1090 bool get hasValue => true; | 1114 bool get hasValue => true; |
1091 | 1115 |
1092 void setParentPointers() { | 1116 void setParentPointers() { |
1093 value.parent = this; | 1117 valueRef.parent = this; |
1094 _setParentsOnList(typeArguments, this); | 1118 _setParentsOnList(typeArgumentRefs, this); |
1095 } | 1119 } |
1096 } | 1120 } |
1097 | 1121 |
1098 /// Apply a built-in operator. | 1122 /// Apply a built-in operator. |
1099 /// | 1123 /// |
1100 /// It must be known that the arguments have the proper types. | 1124 /// It must be known that the arguments have the proper types. |
1101 class ApplyBuiltinOperator extends Primitive { | 1125 class ApplyBuiltinOperator extends Primitive { |
1102 BuiltinOperator operator; | 1126 BuiltinOperator operator; |
1103 List<Reference<Primitive>> arguments; | 1127 List<Reference<Primitive>> argumentRefs; |
1104 final SourceInformation sourceInformation; | 1128 final SourceInformation sourceInformation; |
1105 | 1129 |
1130 Primitive argument(int n) => argumentRefs[n].definition; | |
1131 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1132 | |
1106 ApplyBuiltinOperator(this.operator, | 1133 ApplyBuiltinOperator(this.operator, |
1107 List<Primitive> arguments, | 1134 List<Primitive> arguments, |
1108 this.sourceInformation) | 1135 this.sourceInformation) |
1109 : this.arguments = _referenceList(arguments); | 1136 : this.argumentRefs = _referenceList(arguments); |
1110 | 1137 |
1111 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); | 1138 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); |
1112 | 1139 |
1113 bool get hasValue => true; | 1140 bool get hasValue => true; |
1114 bool get isSafeForElimination => true; | 1141 bool get isSafeForElimination => true; |
1115 bool get isSafeForReordering => true; | 1142 bool get isSafeForReordering => true; |
1116 | 1143 |
1117 void setParentPointers() { | 1144 void setParentPointers() { |
1118 _setParentsOnList(arguments, this); | 1145 _setParentsOnList(argumentRefs, this); |
1119 } | 1146 } |
1120 } | 1147 } |
1121 | 1148 |
1122 /// Apply a built-in method. | 1149 /// Apply a built-in method. |
1123 /// | 1150 /// |
1124 /// It must be known that the arguments have the proper types. | 1151 /// It must be known that the arguments have the proper types. |
1125 class ApplyBuiltinMethod extends Primitive { | 1152 class ApplyBuiltinMethod extends Primitive { |
1126 BuiltinMethod method; | 1153 BuiltinMethod method; |
1127 Reference<Primitive> receiver; | 1154 Reference<Primitive> receiverRef; |
1128 List<Reference<Primitive>> arguments; | 1155 List<Reference<Primitive>> argumentRefs; |
1129 final SourceInformation sourceInformation; | 1156 final SourceInformation sourceInformation; |
1130 | 1157 |
1158 Primitive get receiver => receiverRef.definition; | |
1159 Primitive argument(int n) => argumentRefs[n].definition; | |
1160 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1161 | |
1131 bool receiverIsNotNull; | 1162 bool receiverIsNotNull; |
1132 | 1163 |
1133 ApplyBuiltinMethod(this.method, | 1164 ApplyBuiltinMethod(this.method, |
1134 Primitive receiver, | 1165 Primitive receiver, |
1135 List<Primitive> arguments, | 1166 List<Primitive> arguments, |
1136 this.sourceInformation, | 1167 this.sourceInformation, |
1137 {this.receiverIsNotNull: false}) | 1168 {this.receiverIsNotNull: false}) |
1138 : this.receiver = new Reference<Primitive>(receiver), | 1169 : this.receiverRef = new Reference<Primitive>(receiver), |
1139 this.arguments = _referenceList(arguments); | 1170 this.argumentRefs = _referenceList(arguments); |
1140 | 1171 |
1141 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); | 1172 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); |
1142 | 1173 |
1143 bool get hasValue => true; | 1174 bool get hasValue => true; |
1144 bool get isSafeForElimination => false; | 1175 bool get isSafeForElimination => false; |
1145 bool get isSafeForReordering => false; | 1176 bool get isSafeForReordering => false; |
1146 | 1177 |
1147 void setParentPointers() { | 1178 void setParentPointers() { |
1148 receiver.parent = this; | 1179 receiverRef.parent = this; |
1149 _setParentsOnList(arguments, this); | 1180 _setParentsOnList(argumentRefs, this); |
1150 } | 1181 } |
1151 | 1182 |
1152 int get effects => getEffectsOfBuiltinMethod(method); | 1183 int get effects => getEffectsOfBuiltinMethod(method); |
1153 } | 1184 } |
1154 | 1185 |
1155 /// Throw a value. | 1186 /// Throw a value. |
1156 /// | 1187 /// |
1157 /// Throw is an expression, i.e., it always occurs in tail position with | 1188 /// Throw is an expression, i.e., it always occurs in tail position with |
1158 /// respect to a body or expression. | 1189 /// respect to a body or expression. |
1159 class Throw extends TailExpression { | 1190 class Throw extends TailExpression { |
1160 Reference<Primitive> value; | 1191 Reference<Primitive> valueRef; |
1161 | 1192 |
1162 Throw(Primitive value) : value = new Reference<Primitive>(value); | 1193 Primitive get value => valueRef.definition; |
1194 | |
1195 Throw(Primitive value) : valueRef = new Reference<Primitive>(value); | |
1163 | 1196 |
1164 accept(BlockVisitor visitor) => visitor.visitThrow(this); | 1197 accept(BlockVisitor visitor) => visitor.visitThrow(this); |
1165 | 1198 |
1166 void setParentPointers() { | 1199 void setParentPointers() { |
1167 value.parent = this; | 1200 valueRef.parent = this; |
1168 } | 1201 } |
1169 } | 1202 } |
1170 | 1203 |
1171 /// Rethrow | 1204 /// Rethrow |
1172 /// | 1205 /// |
1173 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It | 1206 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It |
1174 /// implicitly throws the exception parameter of the enclosing handler with | 1207 /// implicitly throws the exception parameter of the enclosing handler with |
1175 /// the same stack trace as the enclosing handler. | 1208 /// the same stack trace as the enclosing handler. |
1176 class Rethrow extends TailExpression { | 1209 class Rethrow extends TailExpression { |
1177 accept(BlockVisitor visitor) => visitor.visitRethrow(this); | 1210 accept(BlockVisitor visitor) => visitor.visitRethrow(this); |
(...skipping 10 matching lines...) Expand all Loading... | |
1188 } | 1221 } |
1189 | 1222 |
1190 /// Gets the value from a [MutableVariable]. | 1223 /// Gets the value from a [MutableVariable]. |
1191 /// | 1224 /// |
1192 /// [MutableVariable]s can be seen as ref cells that are not first-class | 1225 /// [MutableVariable]s can be seen as ref cells that are not first-class |
1193 /// values. A [LetPrim] with a [GetMutable] can then be seen as: | 1226 /// values. A [LetPrim] with a [GetMutable] can then be seen as: |
1194 /// | 1227 /// |
1195 /// let prim p = ![variable] in [body] | 1228 /// let prim p = ![variable] in [body] |
1196 /// | 1229 /// |
1197 class GetMutable extends Primitive { | 1230 class GetMutable extends Primitive { |
1198 final Reference<MutableVariable> variable; | 1231 final Reference<MutableVariable> variableRef; |
1232 | |
1233 MutableVariable get variable => variableRef.definition; | |
1199 | 1234 |
1200 GetMutable(MutableVariable variable) | 1235 GetMutable(MutableVariable variable) |
1201 : this.variable = new Reference<MutableVariable>(variable); | 1236 : this.variableRef = new Reference<MutableVariable>(variable); |
1202 | 1237 |
1203 accept(Visitor visitor) => visitor.visitGetMutable(this); | 1238 accept(Visitor visitor) => visitor.visitGetMutable(this); |
1204 | 1239 |
1205 bool get hasValue => true; | 1240 bool get hasValue => true; |
1206 bool get isSafeForElimination => true; | 1241 bool get isSafeForElimination => true; |
1207 bool get isSafeForReordering => false; | 1242 bool get isSafeForReordering => false; |
1208 | 1243 |
1209 void setParentPointers() { | 1244 void setParentPointers() { |
1210 variable.parent = this; | 1245 variableRef.parent = this; |
1211 } | 1246 } |
1212 } | 1247 } |
1213 | 1248 |
1214 /// Assign a [MutableVariable]. | 1249 /// Assign a [MutableVariable]. |
1215 /// | 1250 /// |
1216 /// [MutableVariable]s can be seen as ref cells that are not first-class | 1251 /// [MutableVariable]s can be seen as ref cells that are not first-class |
1217 /// values. This can be seen as a dereferencing assignment: | 1252 /// values. This can be seen as a dereferencing assignment: |
1218 /// | 1253 /// |
1219 /// { [variable] := [value]; [body] } | 1254 /// { [variable] := [value]; [body] } |
1220 class SetMutable extends Primitive { | 1255 class SetMutable extends Primitive { |
1221 final Reference<MutableVariable> variable; | 1256 final Reference<MutableVariable> variableRef; |
1222 final Reference<Primitive> value; | 1257 final Reference<Primitive> valueRef; |
1258 | |
1259 MutableVariable get variable => variableRef.definition; | |
1260 Primitive get value => valueRef.definition; | |
1223 | 1261 |
1224 SetMutable(MutableVariable variable, Primitive value) | 1262 SetMutable(MutableVariable variable, Primitive value) |
1225 : this.variable = new Reference<MutableVariable>(variable), | 1263 : this.variableRef = new Reference<MutableVariable>(variable), |
1226 this.value = new Reference<Primitive>(value); | 1264 this.valueRef = new Reference<Primitive>(value); |
1227 | 1265 |
1228 accept(Visitor visitor) => visitor.visitSetMutable(this); | 1266 accept(Visitor visitor) => visitor.visitSetMutable(this); |
1229 | 1267 |
1230 bool get hasValue => false; | 1268 bool get hasValue => false; |
1231 bool get isSafeForElimination => false; | 1269 bool get isSafeForElimination => false; |
1232 bool get isSafeForReordering => false; | 1270 bool get isSafeForReordering => false; |
1233 | 1271 |
1234 void setParentPointers() { | 1272 void setParentPointers() { |
1235 variable.parent = this; | 1273 variableRef.parent = this; |
1236 value.parent = this; | 1274 valueRef.parent = this; |
1237 } | 1275 } |
1238 } | 1276 } |
1239 | 1277 |
1240 /// Invoke a continuation in tail position. | 1278 /// Invoke a continuation in tail position. |
1241 class InvokeContinuation extends TailExpression { | 1279 class InvokeContinuation extends TailExpression { |
1242 Reference<Continuation> continuation; | 1280 Reference<Continuation> continuationRef; |
1243 List<Reference<Primitive>> arguments; | 1281 List<Reference<Primitive>> argumentRefs; |
1244 SourceInformation sourceInformation; | 1282 SourceInformation sourceInformation; |
1245 | 1283 |
1284 Continuation get continuation => continuationRef.definition; | |
1285 Primitive argument(int n) => argumentRefs[n].definition; | |
1286 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1287 | |
1246 // An invocation of a continuation is recursive if it occurs in the body of | 1288 // An invocation of a continuation is recursive if it occurs in the body of |
1247 // the continuation itself. | 1289 // the continuation itself. |
1248 bool isRecursive; | 1290 bool isRecursive; |
1249 | 1291 |
1250 /// True if this invocation escapes from the body of a [LetHandler] | 1292 /// True if this invocation escapes from the body of a [LetHandler] |
1251 /// (i.e. a try block). Notably, such an invocation cannot be inlined. | 1293 /// (i.e. a try block). Notably, such an invocation cannot be inlined. |
1252 bool isEscapingTry; | 1294 bool isEscapingTry; |
1253 | 1295 |
1254 InvokeContinuation(Continuation cont, List<Primitive> args, | 1296 InvokeContinuation(Continuation cont, List<Primitive> args, |
1255 {this.isRecursive: false, | 1297 {this.isRecursive: false, |
1256 this.isEscapingTry: false, | 1298 this.isEscapingTry: false, |
1257 this.sourceInformation}) | 1299 this.sourceInformation}) |
1258 : continuation = new Reference<Continuation>(cont), | 1300 : continuationRef = new Reference<Continuation>(cont), |
1259 arguments = _referenceList(args) { | 1301 argumentRefs = _referenceList(args) { |
1260 assert(cont.parameters == null || cont.parameters.length == args.length); | 1302 assert(cont.parameters == null || cont.parameters.length == args.length); |
1261 if (isRecursive) cont.isRecursive = true; | 1303 if (isRecursive) cont.isRecursive = true; |
1262 } | 1304 } |
1263 | 1305 |
1264 /// A continuation invocation whose target and arguments will be filled | 1306 /// A continuation invocation whose target and arguments will be filled |
1265 /// in later. | 1307 /// in later. |
1266 /// | 1308 /// |
1267 /// Used as a placeholder for a jump whose target is not yet created | 1309 /// Used as a placeholder for a jump whose target is not yet created |
1268 /// (e.g., in the translation of break and continue). | 1310 /// (e.g., in the translation of break and continue). |
1269 InvokeContinuation.uninitialized({this.isRecursive: false, | 1311 InvokeContinuation.uninitialized({this.isRecursive: false, |
1270 this.isEscapingTry: false}) | 1312 this.isEscapingTry: false}) |
1271 : continuation = null, | 1313 : continuationRef = null, |
1272 arguments = null, | 1314 argumentRefs = null, |
1273 sourceInformation = null; | 1315 sourceInformation = null; |
1274 | 1316 |
1275 accept(BlockVisitor visitor) => visitor.visitInvokeContinuation(this); | 1317 accept(BlockVisitor visitor) => visitor.visitInvokeContinuation(this); |
1276 | 1318 |
1277 void setParentPointers() { | 1319 void setParentPointers() { |
1278 if (continuation != null) continuation.parent = this; | 1320 if (continuationRef != null) continuationRef.parent = this; |
1279 if (arguments != null) _setParentsOnList(arguments, this); | 1321 if (argumentRefs != null) _setParentsOnList(argumentRefs, this); |
1280 } | 1322 } |
1281 } | 1323 } |
1282 | 1324 |
1283 /// Choose between a pair of continuations based on a condition value. | 1325 /// Choose between a pair of continuations based on a condition value. |
1284 /// | 1326 /// |
1285 /// The two continuations must not declare any parameters. | 1327 /// The two continuations must not declare any parameters. |
1286 class Branch extends TailExpression { | 1328 class Branch extends TailExpression { |
1287 final Reference<Primitive> condition; | 1329 final Reference<Primitive> conditionRef; |
1288 final Reference<Continuation> trueContinuation; | 1330 final Reference<Continuation> trueContinuationRef; |
1289 final Reference<Continuation> falseContinuation; | 1331 final Reference<Continuation> falseContinuationRef; |
1332 | |
1333 Primitive get condition => conditionRef.definition; | |
1334 Continuation get trueContinuation => trueContinuationRef.definition; | |
1335 Continuation get falseContinuation => falseContinuationRef.definition; | |
1290 | 1336 |
1291 /// If true, only the value `true` satisfies the condition. Otherwise, any | 1337 /// If true, only the value `true` satisfies the condition. Otherwise, any |
1292 /// truthy value satisfies the check. | 1338 /// truthy value satisfies the check. |
1293 /// | 1339 /// |
1294 /// Non-strict checks are preferable when the condition is known to be a | 1340 /// Non-strict checks are preferable when the condition is known to be a |
1295 /// boolean. | 1341 /// boolean. |
1296 bool isStrictCheck; | 1342 bool isStrictCheck; |
1297 | 1343 |
1298 Branch(Primitive condition, | 1344 Branch(Primitive condition, |
1299 Continuation trueCont, | 1345 Continuation trueCont, |
1300 Continuation falseCont, | 1346 Continuation falseCont, |
1301 {bool strict}) | 1347 {bool strict}) |
1302 : this.condition = new Reference<Primitive>(condition), | 1348 : this.conditionRef = new Reference<Primitive>(condition), |
1303 trueContinuation = new Reference<Continuation>(trueCont), | 1349 trueContinuationRef = new Reference<Continuation>(trueCont), |
1304 falseContinuation = new Reference<Continuation>(falseCont), | 1350 falseContinuationRef = new Reference<Continuation>(falseCont), |
1305 isStrictCheck = strict { | 1351 isStrictCheck = strict { |
1306 assert(strict != null); | 1352 assert(strict != null); |
1307 } | 1353 } |
1308 | 1354 |
1309 Branch.strict(Primitive condition, | 1355 Branch.strict(Primitive condition, |
1310 Continuation trueCont, | 1356 Continuation trueCont, |
1311 Continuation falseCont) | 1357 Continuation falseCont) |
1312 : this(condition, trueCont, falseCont, strict: true); | 1358 : this(condition, trueCont, falseCont, strict: true); |
1313 | 1359 |
1314 Branch.loose(Primitive condition, | 1360 Branch.loose(Primitive condition, |
1315 Continuation trueCont, | 1361 Continuation trueCont, |
1316 Continuation falseCont) | 1362 Continuation falseCont) |
1317 : this(condition, trueCont, falseCont, strict: false); | 1363 : this(condition, trueCont, falseCont, strict: false); |
1318 | 1364 |
1319 accept(BlockVisitor visitor) => visitor.visitBranch(this); | 1365 accept(BlockVisitor visitor) => visitor.visitBranch(this); |
1320 | 1366 |
1321 void setParentPointers() { | 1367 void setParentPointers() { |
1322 condition.parent = this; | 1368 conditionRef.parent = this; |
1323 trueContinuation.parent = this; | 1369 trueContinuationRef.parent = this; |
1324 falseContinuation.parent = this; | 1370 falseContinuationRef.parent = this; |
1325 } | 1371 } |
1326 } | 1372 } |
1327 | 1373 |
1328 /// Directly assigns to a field on a given object. | 1374 /// Directly assigns to a field on a given object. |
1329 class SetField extends Primitive { | 1375 class SetField extends Primitive { |
1330 final Reference<Primitive> object; | 1376 final Reference<Primitive> objectRef; |
1331 FieldElement field; | 1377 FieldElement field; |
1332 final Reference<Primitive> value; | 1378 final Reference<Primitive> valueRef; |
1379 | |
1380 Primitive get object => objectRef.definition; | |
1381 Primitive get value => valueRef.definition; | |
1333 | 1382 |
1334 SetField(Primitive object, this.field, Primitive value) | 1383 SetField(Primitive object, this.field, Primitive value) |
1335 : this.object = new Reference<Primitive>(object), | 1384 : this.objectRef = new Reference<Primitive>(object), |
1336 this.value = new Reference<Primitive>(value); | 1385 this.valueRef = new Reference<Primitive>(value); |
1337 | 1386 |
1338 accept(Visitor visitor) => visitor.visitSetField(this); | 1387 accept(Visitor visitor) => visitor.visitSetField(this); |
1339 | 1388 |
1340 bool get hasValue => false; | 1389 bool get hasValue => false; |
1341 bool get isSafeForElimination => false; | 1390 bool get isSafeForElimination => false; |
1342 bool get isSafeForReordering => false; | 1391 bool get isSafeForReordering => false; |
1343 | 1392 |
1344 void setParentPointers() { | 1393 void setParentPointers() { |
1345 object.parent = this; | 1394 objectRef.parent = this; |
1346 value.parent = this; | 1395 valueRef.parent = this; |
1347 } | 1396 } |
1348 | 1397 |
1349 int get effects => Effects.changesInstanceField; | 1398 int get effects => Effects.changesInstanceField; |
1350 } | 1399 } |
1351 | 1400 |
1352 /// Directly reads from a field on a given object. | 1401 /// Directly reads from a field on a given object. |
1353 /// | 1402 /// |
1354 /// The [object] must either be `null` or an object that has [field]. | 1403 /// The [object] must either be `null` or an object that has [field]. |
1355 class GetField extends Primitive { | 1404 class GetField extends Primitive { |
1356 final Reference<Primitive> object; | 1405 final Reference<Primitive> objectRef; |
1357 FieldElement field; | 1406 FieldElement field; |
1358 | 1407 |
1359 /// True if the field never changes value. | 1408 /// True if the field never changes value. |
1360 final bool isFinal; | 1409 final bool isFinal; |
1361 | 1410 |
1362 /// True if the object is known not to be null. | 1411 /// True if the object is known not to be null. |
1363 // TODO(asgerf): This is a placeholder until we agree on how to track | 1412 // TODO(asgerf): This is a placeholder until we agree on how to track |
1364 // side effects. | 1413 // side effects. |
1365 bool objectIsNotNull = false; | 1414 bool objectIsNotNull = false; |
1366 | 1415 |
1416 Primitive get object => objectRef.definition; | |
1417 | |
1367 GetField(Primitive object, this.field, {this.isFinal: false}) | 1418 GetField(Primitive object, this.field, {this.isFinal: false}) |
1368 : this.object = new Reference<Primitive>(object); | 1419 : this.objectRef = new Reference<Primitive>(object); |
1369 | 1420 |
1370 accept(Visitor visitor) => visitor.visitGetField(this); | 1421 accept(Visitor visitor) => visitor.visitGetField(this); |
1371 | 1422 |
1372 bool get hasValue => true; | 1423 bool get hasValue => true; |
1373 bool get isSafeForElimination => objectIsNotNull; | 1424 bool get isSafeForElimination => objectIsNotNull; |
1374 bool get isSafeForReordering => false; | 1425 bool get isSafeForReordering => false; |
1375 | 1426 |
1376 toString() => 'GetField($field)'; | 1427 toString() => 'GetField($field)'; |
1377 | 1428 |
1378 void setParentPointers() { | 1429 void setParentPointers() { |
1379 object.parent = this; | 1430 objectRef.parent = this; |
1380 } | 1431 } |
1381 | 1432 |
1382 int get effects => isFinal ? 0 : Effects.dependsOnInstanceField; | 1433 int get effects => isFinal ? 0 : Effects.dependsOnInstanceField; |
1383 } | 1434 } |
1384 | 1435 |
1385 /// Get the length of a string or native list. | 1436 /// Get the length of a string or native list. |
1386 class GetLength extends Primitive { | 1437 class GetLength extends Primitive { |
1387 final Reference<Primitive> object; | 1438 final Reference<Primitive> objectRef; |
1388 | 1439 |
1389 /// True if the length of the given object can never change. | 1440 /// True if the length of the given object can never change. |
1390 bool isFinal; | 1441 bool isFinal; |
1391 | 1442 |
1392 /// True if the object is known not to be null. | 1443 /// True if the object is known not to be null. |
1393 bool objectIsNotNull = false; | 1444 bool objectIsNotNull = false; |
1394 | 1445 |
1446 Primitive get object => objectRef.definition; | |
1447 | |
1395 GetLength(Primitive object, {this.isFinal: false}) | 1448 GetLength(Primitive object, {this.isFinal: false}) |
1396 : this.object = new Reference<Primitive>(object); | 1449 : this.objectRef = new Reference<Primitive>(object); |
1397 | 1450 |
1398 bool get hasValue => true; | 1451 bool get hasValue => true; |
1399 bool get isSafeForElimination => objectIsNotNull; | 1452 bool get isSafeForElimination => objectIsNotNull; |
1400 bool get isSafeForReordering => false; | 1453 bool get isSafeForReordering => false; |
1401 | 1454 |
1402 accept(Visitor v) => v.visitGetLength(this); | 1455 accept(Visitor v) => v.visitGetLength(this); |
1403 | 1456 |
1404 void setParentPointers() { | 1457 void setParentPointers() { |
1405 object.parent = this; | 1458 objectRef.parent = this; |
1406 } | 1459 } |
1407 | 1460 |
1408 int get effects => isFinal ? 0 : Effects.dependsOnIndexableLength; | 1461 int get effects => isFinal ? 0 : Effects.dependsOnIndexableLength; |
1409 } | 1462 } |
1410 | 1463 |
1411 /// Read an entry from an indexable object. | 1464 /// Read an entry from an indexable object. |
1412 /// | 1465 /// |
1413 /// [object] must be null or an indexable object, and [index] must be | 1466 /// [object] must be null or an indexable object, and [index] must be |
1414 /// an integer where `0 <= index < object.length`. | 1467 /// an integer where `0 <= index < object.length`. |
1415 class GetIndex extends Primitive { | 1468 class GetIndex extends Primitive { |
1416 final Reference<Primitive> object; | 1469 final Reference<Primitive> objectRef; |
1417 final Reference<Primitive> index; | 1470 final Reference<Primitive> indexRef; |
1418 | 1471 |
1419 /// True if the object is known not to be null. | 1472 /// True if the object is known not to be null. |
1420 bool objectIsNotNull = false; | 1473 bool objectIsNotNull = false; |
1421 | 1474 |
1475 Primitive get object => objectRef.definition; | |
1476 Primitive get index => indexRef.definition; | |
1477 | |
1422 GetIndex(Primitive object, Primitive index) | 1478 GetIndex(Primitive object, Primitive index) |
1423 : this.object = new Reference<Primitive>(object), | 1479 : this.objectRef = new Reference<Primitive>(object), |
1424 this.index = new Reference<Primitive>(index); | 1480 this.indexRef = new Reference<Primitive>(index); |
1425 | 1481 |
1426 bool get hasValue => true; | 1482 bool get hasValue => true; |
1427 bool get isSafeForElimination => objectIsNotNull; | 1483 bool get isSafeForElimination => objectIsNotNull; |
1428 bool get isSafeForReordering => false; | 1484 bool get isSafeForReordering => false; |
1429 | 1485 |
1430 accept(Visitor v) => v.visitGetIndex(this); | 1486 accept(Visitor v) => v.visitGetIndex(this); |
1431 | 1487 |
1432 void setParentPointers() { | 1488 void setParentPointers() { |
1433 object.parent = this; | 1489 objectRef.parent = this; |
1434 index.parent = this; | 1490 indexRef.parent = this; |
1435 } | 1491 } |
1436 | 1492 |
1437 int get effects => Effects.dependsOnIndexableContent; | 1493 int get effects => Effects.dependsOnIndexableContent; |
1438 } | 1494 } |
1439 | 1495 |
1440 /// Set an entry on a native list. | 1496 /// Set an entry on a native list. |
1441 /// | 1497 /// |
1442 /// [object] must be null or a native list, and [index] must be an integer | 1498 /// [object] must be null or a native list, and [index] must be an integer |
1443 /// within the bounds of the indexable object. | 1499 /// within the bounds of the indexable object. |
1444 /// | 1500 /// |
1445 /// [SetIndex] may not be used to alter the length of a JS array. | 1501 /// [SetIndex] may not be used to alter the length of a JS array. |
1446 /// | 1502 /// |
1447 /// The primitive itself has no value and may not be referenced. | 1503 /// The primitive itself has no value and may not be referenced. |
1448 class SetIndex extends Primitive { | 1504 class SetIndex extends Primitive { |
1449 final Reference<Primitive> object; | 1505 final Reference<Primitive> objectRef; |
1450 final Reference<Primitive> index; | 1506 final Reference<Primitive> indexRef; |
1451 final Reference<Primitive> value; | 1507 final Reference<Primitive> valueRef; |
1508 | |
1509 Primitive get object => objectRef.definition; | |
1510 Primitive get index => indexRef.definition; | |
1511 Primitive get value => valueRef.definition; | |
1452 | 1512 |
1453 SetIndex(Primitive object, Primitive index, Primitive value) | 1513 SetIndex(Primitive object, Primitive index, Primitive value) |
1454 : this.object = new Reference<Primitive>(object), | 1514 : this.objectRef = new Reference<Primitive>(object), |
1455 this.index = new Reference<Primitive>(index), | 1515 this.indexRef = new Reference<Primitive>(index), |
1456 this.value = new Reference<Primitive>(value); | 1516 this.valueRef = new Reference<Primitive>(value); |
1457 | 1517 |
1458 bool get hasValue => false; | 1518 bool get hasValue => false; |
1459 bool get isSafeForElimination => false; | 1519 bool get isSafeForElimination => false; |
1460 bool get isSafeForReordering => false; | 1520 bool get isSafeForReordering => false; |
1461 | 1521 |
1462 accept(Visitor v) => v.visitSetIndex(this); | 1522 accept(Visitor v) => v.visitSetIndex(this); |
1463 | 1523 |
1464 void setParentPointers() { | 1524 void setParentPointers() { |
1465 object.parent = this; | 1525 objectRef.parent = this; |
1466 index.parent = this; | 1526 indexRef.parent = this; |
1467 value.parent = this; | 1527 valueRef.parent = this; |
1468 } | 1528 } |
1469 | 1529 |
1470 int get effects => Effects.changesIndexableContent; | 1530 int get effects => Effects.changesIndexableContent; |
1471 } | 1531 } |
1472 | 1532 |
1473 /// Reads the value of a static field or tears off a static method. | 1533 /// Reads the value of a static field or tears off a static method. |
1474 /// | 1534 /// |
1475 /// If [GetStatic] is used to load a lazily initialized static field, it must | 1535 /// If [GetStatic] is used to load a lazily initialized static field, it must |
1476 /// have been initialized beforehand, and a [witness] must be set to restrict | 1536 /// have been initialized beforehand, and a [witness] must be set to restrict |
1477 /// code motion. | 1537 /// code motion. |
1478 class GetStatic extends Primitive { | 1538 class GetStatic extends Primitive { |
1479 /// Can be [FieldElement] or [FunctionElement]. | 1539 /// Can be [FieldElement] or [FunctionElement]. |
1480 final Element element; | 1540 final Element element; |
1481 final SourceInformation sourceInformation; | 1541 final SourceInformation sourceInformation; |
1482 | 1542 |
1483 /// True if the field never changes value. | 1543 /// True if the field never changes value. |
1484 final bool isFinal; | 1544 final bool isFinal; |
1485 | 1545 |
1486 /// If reading a lazily initialized field, [witness] must refer to a node | 1546 /// If reading a lazily initialized field, [witness] must refer to a node |
1487 /// that initializes the field or always occurs after the field initializer. | 1547 /// that initializes the field or always occurs after the field initializer. |
1488 /// | 1548 /// |
1489 /// The value of the witness is not used. | 1549 /// The value of the witness is not used. |
1490 Reference<Primitive> witness; | 1550 Reference<Primitive> witnessRef; |
1551 | |
1552 Primitive get witness => witnessRef.definition; | |
1491 | 1553 |
1492 GetStatic(this.element, {this.isFinal: false, this.sourceInformation}); | 1554 GetStatic(this.element, {this.isFinal: false, this.sourceInformation}); |
1493 | 1555 |
1494 /// Read a lazily initialized static field that is known to have been | 1556 /// Read a lazily initialized static field that is known to have been |
1495 /// initialized by [witness] or earlier. | 1557 /// initialized by [witness] or earlier. |
1496 GetStatic.witnessed(this.element, Primitive witness, {this.sourceInformation}) | 1558 GetStatic.witnessed(this.element, Primitive witness, {this.sourceInformation}) |
1497 : witness = witness == null ? null : new Reference<Primitive>(witness), | 1559 : witnessRef = _optionalReference(witness), |
1498 isFinal = false; | 1560 isFinal = false; |
1499 | 1561 |
1500 accept(Visitor visitor) => visitor.visitGetStatic(this); | 1562 accept(Visitor visitor) => visitor.visitGetStatic(this); |
1501 | 1563 |
1502 bool get hasValue => true; | 1564 bool get hasValue => true; |
1503 bool get isSafeForElimination => true; | 1565 bool get isSafeForElimination => true; |
1504 bool get isSafeForReordering => isFinal; | 1566 bool get isSafeForReordering => isFinal; |
1505 | 1567 |
1506 void setParentPointers() { | 1568 void setParentPointers() { |
1507 if (witness != null) { | 1569 if (witnessRef != null) { |
1508 witness.parent = this; | 1570 witnessRef.parent = this; |
1509 } | 1571 } |
1510 } | 1572 } |
1511 | 1573 |
1512 int get effects => isFinal ? 0 : Effects.dependsOnStaticField; | 1574 int get effects => isFinal ? 0 : Effects.dependsOnStaticField; |
1513 } | 1575 } |
1514 | 1576 |
1515 /// Sets the value of a static field. | 1577 /// Sets the value of a static field. |
1516 class SetStatic extends Primitive { | 1578 class SetStatic extends Primitive { |
1517 final FieldElement element; | 1579 final FieldElement element; |
1518 final Reference<Primitive> value; | 1580 final Reference<Primitive> valueRef; |
1519 final SourceInformation sourceInformation; | 1581 final SourceInformation sourceInformation; |
1520 | 1582 |
1583 Primitive get value => valueRef.definition; | |
1584 | |
1521 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 1585 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
1522 : this.value = new Reference<Primitive>(value); | 1586 : this.valueRef = new Reference<Primitive>(value); |
1523 | 1587 |
1524 accept(Visitor visitor) => visitor.visitSetStatic(this); | 1588 accept(Visitor visitor) => visitor.visitSetStatic(this); |
1525 | 1589 |
1526 bool get hasValue => false; | 1590 bool get hasValue => false; |
1527 bool get isSafeForElimination => false; | 1591 bool get isSafeForElimination => false; |
1528 bool get isSafeForReordering => false; | 1592 bool get isSafeForReordering => false; |
1529 | 1593 |
1530 void setParentPointers() { | 1594 void setParentPointers() { |
1531 value.parent = this; | 1595 valueRef.parent = this; |
1532 } | 1596 } |
1533 | 1597 |
1534 int get effects => Effects.changesStaticField; | 1598 int get effects => Effects.changesStaticField; |
1535 } | 1599 } |
1536 | 1600 |
1537 /// Reads the value of a lazily initialized static field. | 1601 /// Reads the value of a lazily initialized static field. |
1538 /// | 1602 /// |
1539 /// If the field has not yet been initialized, its initializer is evaluated | 1603 /// If the field has not yet been initialized, its initializer is evaluated |
1540 /// and assigned to the field. | 1604 /// and assigned to the field. |
1541 class GetLazyStatic extends UnsafePrimitive { | 1605 class GetLazyStatic extends UnsafePrimitive { |
(...skipping 26 matching lines...) Expand all Loading... | |
1568 void setParentPointers() {} | 1632 void setParentPointers() {} |
1569 } | 1633 } |
1570 | 1634 |
1571 /// Creates an instance of a class and initializes its fields and runtime type | 1635 /// Creates an instance of a class and initializes its fields and runtime type |
1572 /// information. | 1636 /// information. |
1573 class CreateInstance extends Primitive { | 1637 class CreateInstance extends Primitive { |
1574 final ClassElement classElement; | 1638 final ClassElement classElement; |
1575 | 1639 |
1576 /// Initial values for the fields on the class. | 1640 /// Initial values for the fields on the class. |
1577 /// The order corresponds to the order of fields on the class. | 1641 /// The order corresponds to the order of fields on the class. |
1578 final List<Reference<Primitive>> arguments; | 1642 final List<Reference<Primitive>> argumentRefs; |
1579 | 1643 |
1580 /// The runtime type information structure which contains the type arguments. | 1644 /// The runtime type information structure which contains the type arguments. |
1581 /// | 1645 /// |
1582 /// May be `null` to indicate that no type information is needed because the | 1646 /// May be `null` to indicate that no type information is needed because the |
1583 /// compiler determined that the type information for instances of this class | 1647 /// compiler determined that the type information for instances of this class |
1584 /// is not needed at runtime. | 1648 /// is not needed at runtime. |
1585 final Reference<Primitive> typeInformation; | 1649 final Reference<Primitive> typeInformationRef; |
1586 | 1650 |
1587 final SourceInformation sourceInformation; | 1651 final SourceInformation sourceInformation; |
1588 | 1652 |
1653 Primitive argument(int n) => argumentRefs[n].definition; | |
1654 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1655 Primitive get typeInformation => typeInformationRef?.definition; | |
1656 | |
1589 CreateInstance(this.classElement, List<Primitive> arguments, | 1657 CreateInstance(this.classElement, List<Primitive> arguments, |
1590 Primitive typeInformation, | 1658 Primitive typeInformation, |
1591 this.sourceInformation) | 1659 this.sourceInformation) |
1592 : this.arguments = _referenceList(arguments), | 1660 : this.argumentRefs = _referenceList(arguments), |
1593 this.typeInformation = typeInformation == null | 1661 this.typeInformationRef = _optionalReference(typeInformation); |
1594 ? null | |
1595 : new Reference<Primitive>(typeInformation); | |
1596 | 1662 |
1597 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 1663 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
1598 | 1664 |
1599 bool get hasValue => true; | 1665 bool get hasValue => true; |
1600 bool get isSafeForElimination => true; | 1666 bool get isSafeForElimination => true; |
1601 bool get isSafeForReordering => true; | 1667 bool get isSafeForReordering => true; |
1602 | 1668 |
1603 toString() => 'CreateInstance($classElement)'; | 1669 toString() => 'CreateInstance($classElement)'; |
1604 | 1670 |
1605 void setParentPointers() { | 1671 void setParentPointers() { |
1606 _setParentsOnList(arguments, this); | 1672 _setParentsOnList(argumentRefs, this); |
1607 if (typeInformation != null) typeInformation.parent = this; | 1673 if (typeInformationRef != null) typeInformationRef.parent = this; |
1608 } | 1674 } |
1609 } | 1675 } |
1610 | 1676 |
1611 /// Obtains the interceptor for the given value. This is a method table | 1677 /// Obtains the interceptor for the given value. This is a method table |
1612 /// corresponding to the Dart class of the value. | 1678 /// corresponding to the Dart class of the value. |
1613 /// | 1679 /// |
1614 /// All values are either intercepted or self-intercepted. The interceptor for | 1680 /// All values are either intercepted or self-intercepted. The interceptor for |
1615 /// an "intercepted value" is one of the subclasses of Interceptor. | 1681 /// an "intercepted value" is one of the subclasses of Interceptor. |
1616 /// The interceptor for a "self-intercepted value" is the value itself. | 1682 /// The interceptor for a "self-intercepted value" is the value itself. |
1617 /// | 1683 /// |
1618 /// If the input is an intercepted value, and any of its superclasses is in | 1684 /// If the input is an intercepted value, and any of its superclasses is in |
1619 /// [interceptedClasses], the method table for the input is returned. | 1685 /// [interceptedClasses], the method table for the input is returned. |
1620 /// Otherwise, the input itself is returned. | 1686 /// Otherwise, the input itself is returned. |
1621 /// | 1687 /// |
1622 /// There are thus three significant cases: | 1688 /// There are thus three significant cases: |
1623 /// - the input is a self-interceptor | 1689 /// - the input is a self-interceptor |
1624 /// - the input is an intercepted value and is caught by [interceptedClasses] | 1690 /// - the input is an intercepted value and is caught by [interceptedClasses] |
1625 /// - the input is an intercepted value but is bypassed by [interceptedClasses] | 1691 /// - the input is an intercepted value but is bypassed by [interceptedClasses] |
1626 /// | 1692 /// |
1627 /// The [flags] field indicates which of the above cases may happen, with | 1693 /// The [flags] field indicates which of the above cases may happen, with |
1628 /// additional special cases for null (which can either by intercepted or | 1694 /// additional special cases for null (which can either by intercepted or |
1629 /// bypassed). | 1695 /// bypassed). |
1630 class Interceptor extends Primitive { | 1696 class Interceptor extends Primitive { |
1631 final Reference<Primitive> input; | 1697 final Reference<Primitive> inputRef; |
1632 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); | 1698 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); |
1633 final SourceInformation sourceInformation; | 1699 final SourceInformation sourceInformation; |
1634 | 1700 |
1701 Primitive get input => inputRef.definition; | |
1702 | |
1635 Interceptor(Primitive input, this.sourceInformation) | 1703 Interceptor(Primitive input, this.sourceInformation) |
1636 : this.input = new Reference<Primitive>(input); | 1704 : this.inputRef = new Reference<Primitive>(input); |
1637 | 1705 |
1638 accept(Visitor visitor) => visitor.visitInterceptor(this); | 1706 accept(Visitor visitor) => visitor.visitInterceptor(this); |
1639 | 1707 |
1640 bool get hasValue => true; | 1708 bool get hasValue => true; |
1641 bool get isSafeForElimination => true; | 1709 bool get isSafeForElimination => true; |
1642 bool get isSafeForReordering => true; | 1710 bool get isSafeForReordering => true; |
1643 | 1711 |
1644 void setParentPointers() { | 1712 void setParentPointers() { |
1645 input.parent = this; | 1713 inputRef.parent = this; |
1646 } | 1714 } |
1647 } | 1715 } |
1648 | 1716 |
1649 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. | 1717 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
1650 class CreateInvocationMirror extends Primitive { | 1718 class CreateInvocationMirror extends Primitive { |
1651 final Selector selector; | 1719 final Selector selector; |
1652 final List<Reference<Primitive>> arguments; | 1720 final List<Reference<Primitive>> argumentRefs; |
1721 | |
1722 Primitive argument(int n) => argumentRefs[n].definition; | |
1723 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1653 | 1724 |
1654 CreateInvocationMirror(this.selector, List<Primitive> arguments) | 1725 CreateInvocationMirror(this.selector, List<Primitive> arguments) |
1655 : this.arguments = _referenceList(arguments); | 1726 : this.argumentRefs = _referenceList(arguments); |
1656 | 1727 |
1657 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); | 1728 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
1658 | 1729 |
1659 bool get hasValue => true; | 1730 bool get hasValue => true; |
1660 bool get isSafeForElimination => true; | 1731 bool get isSafeForElimination => true; |
1661 bool get isSafeForReordering => true; | 1732 bool get isSafeForReordering => true; |
1662 | 1733 |
1663 void setParentPointers() { | 1734 void setParentPointers() { |
1664 _setParentsOnList(arguments, this); | 1735 _setParentsOnList(argumentRefs, this); |
1665 } | 1736 } |
1666 } | 1737 } |
1667 | 1738 |
1668 class ForeignCode extends UnsafePrimitive { | 1739 class ForeignCode extends UnsafePrimitive { |
1669 final js.Template codeTemplate; | 1740 final js.Template codeTemplate; |
1670 final TypeMask storedType; | 1741 final TypeMask storedType; |
1671 final List<Reference<Primitive>> arguments; | 1742 final List<Reference<Primitive>> argumentRefs; |
1672 final native.NativeBehavior nativeBehavior; | 1743 final native.NativeBehavior nativeBehavior; |
1673 final FunctionElement dependency; | 1744 final FunctionElement dependency; |
1674 | 1745 |
1746 Primitive argument(int n) => argumentRefs[n].definition; | |
1747 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1748 | |
1675 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, | 1749 ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments, |
1676 this.nativeBehavior, {this.dependency}) | 1750 this.nativeBehavior, {this.dependency}) |
1677 : this.arguments = _referenceList(arguments) { | 1751 : this.argumentRefs = _referenceList(arguments) { |
1678 effects = Effects.from(nativeBehavior.sideEffects); | 1752 effects = Effects.from(nativeBehavior.sideEffects); |
1679 } | 1753 } |
1680 | 1754 |
1681 accept(Visitor visitor) => visitor.visitForeignCode(this); | 1755 accept(Visitor visitor) => visitor.visitForeignCode(this); |
1682 | 1756 |
1683 bool get hasValue => true; | 1757 bool get hasValue => true; |
1684 | 1758 |
1685 void setParentPointers() { | 1759 void setParentPointers() { |
1686 _setParentsOnList(arguments, this); | 1760 _setParentsOnList(argumentRefs, this); |
1687 } | 1761 } |
1688 | 1762 |
1689 bool isNullGuardOnNullFirstArgument() { | 1763 bool isNullGuardOnNullFirstArgument() { |
1690 if (arguments.length < 1) return false; | 1764 if (argumentRefs.length < 1) return false; |
1691 // TODO(sra): Fix NativeThrowBehavior to distinguish MAY from | 1765 // TODO(sra): Fix NativeThrowBehavior to distinguish MAY from |
1692 // throws-nsm-on-null-followed-by-MAY and remove | 1766 // throws-nsm-on-null-followed-by-MAY and remove |
1693 // [isNullGuardForFirstArgument]. | 1767 // [isNullGuardForFirstArgument]. |
1694 if (nativeBehavior.throwBehavior.isNullNSMGuard) return true; | 1768 if (nativeBehavior.throwBehavior.isNullNSMGuard) return true; |
1695 return js.isNullGuardOnFirstArgument(codeTemplate); | 1769 return js.isNullGuardOnFirstArgument(codeTemplate); |
1696 } | 1770 } |
1697 } | 1771 } |
1698 | 1772 |
1699 class Constant extends Primitive { | 1773 class Constant extends Primitive { |
1700 final values.ConstantValue value; | 1774 final values.ConstantValue value; |
1701 final SourceInformation sourceInformation; | 1775 final SourceInformation sourceInformation; |
1702 | 1776 |
1703 Constant(this.value, {this.sourceInformation}) { | 1777 Constant(this.value, {this.sourceInformation}) { |
1704 assert(value != null); | 1778 assert(value != null); |
1705 } | 1779 } |
1706 | 1780 |
1707 accept(Visitor visitor) => visitor.visitConstant(this); | 1781 accept(Visitor visitor) => visitor.visitConstant(this); |
1708 | 1782 |
1709 bool get hasValue => true; | 1783 bool get hasValue => true; |
1710 bool get isSafeForElimination => true; | 1784 bool get isSafeForElimination => true; |
1711 bool get isSafeForReordering => true; | 1785 bool get isSafeForReordering => true; |
1712 | 1786 |
1713 void setParentPointers() {} | 1787 void setParentPointers() {} |
1714 } | 1788 } |
1715 | 1789 |
1716 class LiteralList extends Primitive { | 1790 class LiteralList extends Primitive { |
1717 /// The List type being created; this is not the type argument. | 1791 /// The List type being created; this is not the type argument. |
1718 final InterfaceType dartType; | 1792 final InterfaceType dartType; |
1719 final List<Reference<Primitive>> values; | 1793 final List<Reference<Primitive>> valueRefs; |
1720 | 1794 |
1721 /// If non-null, this is an allocation site-specific type for the list | 1795 /// If non-null, this is an allocation site-specific type for the list |
1722 /// created here. | 1796 /// created here. |
1723 TypeMask allocationSiteType; | 1797 TypeMask allocationSiteType; |
1724 | 1798 |
1799 Primitive value(int n) => valueRefs[n].definition; | |
1800 Iterable<Primitive> get values => _dereferenceList(valueRefs); | |
1801 | |
1725 LiteralList(this.dartType, List<Primitive> values, {this.allocationSiteType}) | 1802 LiteralList(this.dartType, List<Primitive> values, {this.allocationSiteType}) |
1726 : this.values = _referenceList(values); | 1803 : this.valueRefs = _referenceList(values); |
1727 | 1804 |
1728 accept(Visitor visitor) => visitor.visitLiteralList(this); | 1805 accept(Visitor visitor) => visitor.visitLiteralList(this); |
1729 | 1806 |
1730 bool get hasValue => true; | 1807 bool get hasValue => true; |
1731 bool get isSafeForElimination => true; | 1808 bool get isSafeForElimination => true; |
1732 bool get isSafeForReordering => true; | 1809 bool get isSafeForReordering => true; |
1733 | 1810 |
1734 void setParentPointers() { | 1811 void setParentPointers() { |
1735 _setParentsOnList(values, this); | 1812 _setParentsOnList(valueRefs, this); |
1736 } | 1813 } |
1737 } | 1814 } |
1738 | 1815 |
1739 class Parameter extends Primitive { | 1816 class Parameter extends Primitive { |
1740 Parameter(Entity hint) { | 1817 Parameter(Entity hint) { |
1741 super.hint = hint; | 1818 super.hint = hint; |
1742 } | 1819 } |
1743 | 1820 |
1744 accept(Visitor visitor) => visitor.visitParameter(this); | 1821 accept(Visitor visitor) => visitor.visitParameter(this); |
1745 | 1822 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1850 returnContinuation.parent = this; | 1927 returnContinuation.parent = this; |
1851 if (body != null) body.parent = this; | 1928 if (body != null) body.parent = this; |
1852 } | 1929 } |
1853 } | 1930 } |
1854 | 1931 |
1855 /// Converts the internal representation of a type to a Dart object of type | 1932 /// Converts the internal representation of a type to a Dart object of type |
1856 /// [Type]. | 1933 /// [Type]. |
1857 class ReifyRuntimeType extends Primitive { | 1934 class ReifyRuntimeType extends Primitive { |
1858 /// Reference to the internal representation of a type (as produced, for | 1935 /// Reference to the internal representation of a type (as produced, for |
1859 /// example, by [ReadTypeVariable]). | 1936 /// example, by [ReadTypeVariable]). |
1860 final Reference<Primitive> value; | 1937 final Reference<Primitive> valueRef; |
1861 | 1938 |
1862 final SourceInformation sourceInformation; | 1939 final SourceInformation sourceInformation; |
1863 | 1940 |
1941 Primitive get value => valueRef.definition; | |
1942 | |
1864 ReifyRuntimeType(Primitive value, this.sourceInformation) | 1943 ReifyRuntimeType(Primitive value, this.sourceInformation) |
1865 : this.value = new Reference<Primitive>(value); | 1944 : this.valueRef = new Reference<Primitive>(value); |
1866 | 1945 |
1867 @override | 1946 @override |
1868 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); | 1947 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
1869 | 1948 |
1870 bool get hasValue => true; | 1949 bool get hasValue => true; |
1871 bool get isSafeForElimination => true; | 1950 bool get isSafeForElimination => true; |
1872 bool get isSafeForReordering => true; | 1951 bool get isSafeForReordering => true; |
1873 | 1952 |
1874 void setParentPointers() { | 1953 void setParentPointers() { |
1875 value.parent = this; | 1954 valueRef.parent = this; |
1876 } | 1955 } |
1877 } | 1956 } |
1878 | 1957 |
1879 /// Read the value the type variable [variable] from the target object. | 1958 /// Read the value the type variable [variable] from the target object. |
1880 /// | 1959 /// |
1881 /// The resulting value is an internal representation (and not neccessarily a | 1960 /// The resulting value is an internal representation (and not neccessarily a |
1882 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be | 1961 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be |
1883 /// used as a Dart value. | 1962 /// used as a Dart value. |
1884 class ReadTypeVariable extends Primitive { | 1963 class ReadTypeVariable extends Primitive { |
1885 final TypeVariableType variable; | 1964 final TypeVariableType variable; |
1886 final Reference<Primitive> target; | 1965 final Reference<Primitive> targetRef; |
1887 final SourceInformation sourceInformation; | 1966 final SourceInformation sourceInformation; |
1888 | 1967 |
1968 Primitive get target => targetRef.definition; | |
1969 | |
1889 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) | 1970 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) |
1890 : this.target = new Reference<Primitive>(target); | 1971 : this.targetRef = new Reference<Primitive>(target); |
1891 | 1972 |
1892 @override | 1973 @override |
1893 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 1974 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
1894 | 1975 |
1895 bool get hasValue => true; | 1976 bool get hasValue => true; |
1896 bool get isSafeForElimination => true; | 1977 bool get isSafeForElimination => true; |
1897 bool get isSafeForReordering => true; | 1978 bool get isSafeForReordering => true; |
1898 | 1979 |
1899 void setParentPointers() { | 1980 void setParentPointers() { |
1900 target.parent = this; | 1981 targetRef.parent = this; |
1901 } | 1982 } |
1902 } | 1983 } |
1903 | 1984 |
1904 enum TypeExpressionKind { | 1985 enum TypeExpressionKind { |
1905 COMPLETE, | 1986 COMPLETE, |
1906 INSTANCE | 1987 INSTANCE |
1907 } | 1988 } |
1908 | 1989 |
1909 /// Constructs a representation of a closed or ground-term type (that is, a type | 1990 /// Constructs a representation of a closed or ground-term type (that is, a type |
1910 /// without type variables). | 1991 /// without type variables). |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1952 /// TypeExpression(COMPLETE, // E3 = List<T> | 2033 /// TypeExpression(COMPLETE, // E3 = List<T> |
1953 /// dartType: List<E2>, | 2034 /// dartType: List<E2>, |
1954 /// ReadTypeVariable(this, T)))) // E2 = T | 2035 /// ReadTypeVariable(this, T)))) // E2 = T |
1955 // | 2036 // |
1956 // TODO(sra): The INSTANCE form requires the actual instance for full | 2037 // TODO(sra): The INSTANCE form requires the actual instance for full |
1957 // interpretation. I want to move to a representation where the INSTANCE form is | 2038 // interpretation. I want to move to a representation where the INSTANCE form is |
1958 // also a complete form (possibly the same). | 2039 // also a complete form (possibly the same). |
1959 class TypeExpression extends Primitive { | 2040 class TypeExpression extends Primitive { |
1960 final TypeExpressionKind kind; | 2041 final TypeExpressionKind kind; |
1961 final DartType dartType; | 2042 final DartType dartType; |
1962 final List<Reference<Primitive>> arguments; | 2043 final List<Reference<Primitive>> argumentRefs; |
2044 | |
2045 Primitive argument(int n) => argumentRefs[n].definition; | |
2046 Iterable<Primitive> get arguments => _dereferenceList(argumentRefs); | |
1963 | 2047 |
1964 TypeExpression(this.kind, | 2048 TypeExpression(this.kind, |
1965 this.dartType, | 2049 this.dartType, |
1966 List<Primitive> arguments) | 2050 List<Primitive> arguments) |
1967 : this.arguments = _referenceList(arguments) { | 2051 : this.argumentRefs = _referenceList(arguments) { |
1968 assert(kind == TypeExpressionKind.INSTANCE | 2052 assert(kind == TypeExpressionKind.INSTANCE |
1969 ? dartType == (dartType.element as ClassElement).thisType | 2053 ? dartType == (dartType.element as ClassElement).thisType |
1970 : true); | 2054 : true); |
1971 } | 2055 } |
1972 | 2056 |
1973 @override | 2057 @override |
1974 accept(Visitor visitor) { | 2058 accept(Visitor visitor) { |
1975 return visitor.visitTypeExpression(this); | 2059 return visitor.visitTypeExpression(this); |
1976 } | 2060 } |
1977 | 2061 |
1978 bool get hasValue => true; | 2062 bool get hasValue => true; |
1979 bool get isSafeForElimination => true; | 2063 bool get isSafeForElimination => true; |
1980 bool get isSafeForReordering => true; | 2064 bool get isSafeForReordering => true; |
1981 | 2065 |
1982 void setParentPointers() { | 2066 void setParentPointers() { |
1983 _setParentsOnList(arguments, this); | 2067 _setParentsOnList(argumentRefs, this); |
1984 } | 2068 } |
1985 | 2069 |
1986 String get kindAsString { | 2070 String get kindAsString { |
1987 switch (kind) { | 2071 switch (kind) { |
1988 case TypeExpressionKind.COMPLETE: return 'COMPLETE'; | 2072 case TypeExpressionKind.COMPLETE: return 'COMPLETE'; |
1989 case TypeExpressionKind.INSTANCE: return 'INSTANCE'; | 2073 case TypeExpressionKind.INSTANCE: return 'INSTANCE'; |
1990 } | 2074 } |
1991 } | 2075 } |
1992 } | 2076 } |
1993 | 2077 |
1994 class Await extends UnsafePrimitive { | 2078 class Await extends UnsafePrimitive { |
1995 final Reference<Primitive> input; | 2079 final Reference<Primitive> inputRef; |
2080 | |
2081 Primitive get input => inputRef.definition; | |
1996 | 2082 |
1997 Await(Primitive input) | 2083 Await(Primitive input) |
1998 : this.input = new Reference<Primitive>(input); | 2084 : this.inputRef = new Reference<Primitive>(input); |
1999 | 2085 |
2000 @override | 2086 @override |
2001 accept(Visitor visitor) { | 2087 accept(Visitor visitor) { |
2002 return visitor.visitAwait(this); | 2088 return visitor.visitAwait(this); |
2003 } | 2089 } |
2004 | 2090 |
2005 bool get hasValue => true; | 2091 bool get hasValue => true; |
2006 | 2092 |
2007 void setParentPointers() { | 2093 void setParentPointers() { |
2008 input.parent = this; | 2094 inputRef.parent = this; |
2009 } | 2095 } |
2010 } | 2096 } |
2011 | 2097 |
2012 class Yield extends UnsafePrimitive { | 2098 class Yield extends UnsafePrimitive { |
2013 final Reference<Primitive> input; | 2099 final Reference<Primitive> inputRef; |
2014 final bool hasStar; | 2100 final bool hasStar; |
2015 | 2101 |
2102 Primitive get input => inputRef.definition; | |
2103 | |
2016 Yield(Primitive input, this.hasStar) | 2104 Yield(Primitive input, this.hasStar) |
2017 : this.input = new Reference<Primitive>(input); | 2105 : this.inputRef = new Reference<Primitive>(input); |
2018 | 2106 |
2019 @override | 2107 @override |
2020 accept(Visitor visitor) { | 2108 accept(Visitor visitor) { |
2021 return visitor.visitYield(this); | 2109 return visitor.visitYield(this); |
2022 } | 2110 } |
2023 | 2111 |
2024 bool get hasValue => true; | 2112 bool get hasValue => true; |
2025 | 2113 |
2026 void setParentPointers() { | 2114 void setParentPointers() { |
2027 input.parent = this; | 2115 inputRef.parent = this; |
2028 } | 2116 } |
2029 } | 2117 } |
2030 | 2118 |
2031 Reference<Primitive> _reference(Primitive definition) { | 2119 Reference<Primitive> _reference(Primitive definition) { |
2032 return new Reference<Primitive>(definition); | 2120 return new Reference<Primitive>(definition); |
2033 } | 2121 } |
2034 | 2122 |
2035 Reference<Primitive> _optionalReference(Primitive definition) { | 2123 Reference<Primitive> _optionalReference(Primitive definition) { |
2036 return definition == null | 2124 return definition == null |
2037 ? null | 2125 ? null |
2038 : new Reference<Primitive>(definition); | 2126 : new Reference<Primitive>(definition); |
2039 } | 2127 } |
2040 | 2128 |
2041 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 2129 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
2042 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 2130 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
2043 } | 2131 } |
2044 | 2132 |
2133 Iterable<Primitive> _dereferenceList(List<Reference<Primitive>> references) { | |
2134 return references.map((ref) => ref.definition); | |
2135 } | |
2136 | |
2045 void _setParentsOnNodes(List<Node> nodes, Node parent) { | 2137 void _setParentsOnNodes(List<Node> nodes, Node parent) { |
2046 for (Node node in nodes) { | 2138 for (Node node in nodes) { |
2047 node.parent = parent; | 2139 node.parent = parent; |
2048 } | 2140 } |
2049 } | 2141 } |
2050 | 2142 |
2051 void _setParentsOnList(List<Reference> nodes, Node parent) { | 2143 void _setParentsOnList(List<Reference> nodes, Node parent) { |
2052 for (Reference node in nodes) { | 2144 for (Reference node in nodes) { |
2053 node.parent = parent; | 2145 node.parent = parent; |
2054 } | 2146 } |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2244 visitLetHandler(LetHandler node) { | 2336 visitLetHandler(LetHandler node) { |
2245 processLetHandler(node); | 2337 processLetHandler(node); |
2246 visit(node.handler); | 2338 visit(node.handler); |
2247 visit(node.body); | 2339 visit(node.body); |
2248 } | 2340 } |
2249 | 2341 |
2250 processLetMutable(LetMutable node) {} | 2342 processLetMutable(LetMutable node) {} |
2251 visitLetMutable(LetMutable node) { | 2343 visitLetMutable(LetMutable node) { |
2252 processLetMutable(node); | 2344 processLetMutable(node); |
2253 visit(node.variable); | 2345 visit(node.variable); |
2254 processReference(node.value); | 2346 processReference(node.valueRef); |
2255 visit(node.body); | 2347 visit(node.body); |
2256 } | 2348 } |
2257 | 2349 |
2258 processInvokeStatic(InvokeStatic node) {} | 2350 processInvokeStatic(InvokeStatic node) {} |
2259 visitInvokeStatic(InvokeStatic node) { | 2351 visitInvokeStatic(InvokeStatic node) { |
2260 processInvokeStatic(node); | 2352 processInvokeStatic(node); |
2261 node.arguments.forEach(processReference); | 2353 node.argumentRefs.forEach(processReference); |
2262 } | 2354 } |
2263 | 2355 |
2264 processInvokeContinuation(InvokeContinuation node) {} | 2356 processInvokeContinuation(InvokeContinuation node) {} |
2265 visitInvokeContinuation(InvokeContinuation node) { | 2357 visitInvokeContinuation(InvokeContinuation node) { |
2266 processInvokeContinuation(node); | 2358 processInvokeContinuation(node); |
2267 processReference(node.continuation); | 2359 processReference(node.continuationRef); |
2268 node.arguments.forEach(processReference); | 2360 node.argumentRefs.forEach(processReference); |
2269 } | 2361 } |
2270 | 2362 |
2271 processInvokeMethod(InvokeMethod node) {} | 2363 processInvokeMethod(InvokeMethod node) {} |
2272 visitInvokeMethod(InvokeMethod node) { | 2364 visitInvokeMethod(InvokeMethod node) { |
2273 processInvokeMethod(node); | 2365 processInvokeMethod(node); |
2274 processReference(node.receiver); | 2366 processReference(node.receiverRef); |
2275 node.arguments.forEach(processReference); | 2367 node.argumentRefs.forEach(processReference); |
2276 } | 2368 } |
2277 | 2369 |
2278 processInvokeMethodDirectly(InvokeMethodDirectly node) {} | 2370 processInvokeMethodDirectly(InvokeMethodDirectly node) {} |
2279 visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 2371 visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
2280 processInvokeMethodDirectly(node); | 2372 processInvokeMethodDirectly(node); |
2281 processReference(node.receiver); | 2373 processReference(node.receiverRef); |
2282 node.arguments.forEach(processReference); | 2374 node.argumentRefs.forEach(processReference); |
2283 } | 2375 } |
2284 | 2376 |
2285 processInvokeConstructor(InvokeConstructor node) {} | 2377 processInvokeConstructor(InvokeConstructor node) {} |
2286 visitInvokeConstructor(InvokeConstructor node) { | 2378 visitInvokeConstructor(InvokeConstructor node) { |
2287 processInvokeConstructor(node); | 2379 processInvokeConstructor(node); |
2288 node.arguments.forEach(processReference); | 2380 node.argumentRefs.forEach(processReference); |
2289 } | 2381 } |
2290 | 2382 |
2291 processThrow(Throw node) {} | 2383 processThrow(Throw node) {} |
2292 visitThrow(Throw node) { | 2384 visitThrow(Throw node) { |
2293 processThrow(node); | 2385 processThrow(node); |
2294 processReference(node.value); | 2386 processReference(node.valueRef); |
2295 } | 2387 } |
2296 | 2388 |
2297 processRethrow(Rethrow node) {} | 2389 processRethrow(Rethrow node) {} |
2298 visitRethrow(Rethrow node) { | 2390 visitRethrow(Rethrow node) { |
2299 processRethrow(node); | 2391 processRethrow(node); |
2300 } | 2392 } |
2301 | 2393 |
2302 processBranch(Branch node) {} | 2394 processBranch(Branch node) {} |
2303 visitBranch(Branch node) { | 2395 visitBranch(Branch node) { |
2304 processBranch(node); | 2396 processBranch(node); |
2305 processReference(node.trueContinuation); | 2397 processReference(node.trueContinuationRef); |
2306 processReference(node.falseContinuation); | 2398 processReference(node.falseContinuationRef); |
2307 processReference(node.condition); | 2399 processReference(node.conditionRef); |
2308 } | 2400 } |
2309 | 2401 |
2310 processTypeCast(TypeCast node) {} | 2402 processTypeCast(TypeCast node) {} |
2311 visitTypeCast(TypeCast node) { | 2403 visitTypeCast(TypeCast node) { |
2312 processTypeCast(node); | 2404 processTypeCast(node); |
2313 processReference(node.value); | 2405 processReference(node.valueRef); |
2314 node.typeArguments.forEach(processReference); | 2406 node.typeArgumentRefs.forEach(processReference); |
2315 } | 2407 } |
2316 | 2408 |
2317 processTypeTest(TypeTest node) {} | 2409 processTypeTest(TypeTest node) {} |
2318 visitTypeTest(TypeTest node) { | 2410 visitTypeTest(TypeTest node) { |
2319 processTypeTest(node); | 2411 processTypeTest(node); |
2320 processReference(node.value); | 2412 processReference(node.valueRef); |
2321 node.typeArguments.forEach(processReference); | 2413 node.typeArgumentRefs.forEach(processReference); |
2322 } | 2414 } |
2323 | 2415 |
2324 processTypeTestViaFlag(TypeTestViaFlag node) {} | 2416 processTypeTestViaFlag(TypeTestViaFlag node) {} |
2325 visitTypeTestViaFlag(TypeTestViaFlag node) { | 2417 visitTypeTestViaFlag(TypeTestViaFlag node) { |
2326 processTypeTestViaFlag(node); | 2418 processTypeTestViaFlag(node); |
2327 processReference(node.interceptor); | 2419 processReference(node.interceptorRef); |
2328 } | 2420 } |
2329 | 2421 |
2330 processSetMutable(SetMutable node) {} | 2422 processSetMutable(SetMutable node) {} |
2331 visitSetMutable(SetMutable node) { | 2423 visitSetMutable(SetMutable node) { |
2332 processSetMutable(node); | 2424 processSetMutable(node); |
2333 processReference(node.variable); | 2425 processReference(node.variableRef); |
2334 processReference(node.value); | 2426 processReference(node.valueRef); |
2335 } | 2427 } |
2336 | 2428 |
2337 processGetLazyStatic(GetLazyStatic node) {} | 2429 processGetLazyStatic(GetLazyStatic node) {} |
2338 visitGetLazyStatic(GetLazyStatic node) { | 2430 visitGetLazyStatic(GetLazyStatic node) { |
2339 processGetLazyStatic(node); | 2431 processGetLazyStatic(node); |
2340 } | 2432 } |
2341 | 2433 |
2342 processLiteralList(LiteralList node) {} | 2434 processLiteralList(LiteralList node) {} |
2343 visitLiteralList(LiteralList node) { | 2435 visitLiteralList(LiteralList node) { |
2344 processLiteralList(node); | 2436 processLiteralList(node); |
2345 node.values.forEach(processReference); | 2437 node.valueRefs.forEach(processReference); |
2346 } | 2438 } |
2347 | 2439 |
2348 processConstant(Constant node) {} | 2440 processConstant(Constant node) {} |
2349 visitConstant(Constant node) { | 2441 visitConstant(Constant node) { |
2350 processConstant(node); | 2442 processConstant(node); |
2351 } | 2443 } |
2352 | 2444 |
2353 processMutableVariable(node) {} | 2445 processMutableVariable(node) {} |
2354 visitMutableVariable(MutableVariable node) { | 2446 visitMutableVariable(MutableVariable node) { |
2355 processMutableVariable(node); | 2447 processMutableVariable(node); |
2356 } | 2448 } |
2357 | 2449 |
2358 processGetMutable(GetMutable node) {} | 2450 processGetMutable(GetMutable node) {} |
2359 visitGetMutable(GetMutable node) { | 2451 visitGetMutable(GetMutable node) { |
2360 processGetMutable(node); | 2452 processGetMutable(node); |
2361 processReference(node.variable); | 2453 processReference(node.variableRef); |
2362 } | 2454 } |
2363 | 2455 |
2364 processParameter(Parameter node) {} | 2456 processParameter(Parameter node) {} |
2365 visitParameter(Parameter node) { | 2457 visitParameter(Parameter node) { |
2366 processParameter(node); | 2458 processParameter(node); |
2367 } | 2459 } |
2368 | 2460 |
2369 processInterceptor(Interceptor node) {} | 2461 processInterceptor(Interceptor node) {} |
2370 visitInterceptor(Interceptor node) { | 2462 visitInterceptor(Interceptor node) { |
2371 processInterceptor(node); | 2463 processInterceptor(node); |
2372 processReference(node.input); | 2464 processReference(node.inputRef); |
2373 } | 2465 } |
2374 | 2466 |
2375 processCreateInstance(CreateInstance node) {} | 2467 processCreateInstance(CreateInstance node) {} |
2376 visitCreateInstance(CreateInstance node) { | 2468 visitCreateInstance(CreateInstance node) { |
2377 processCreateInstance(node); | 2469 processCreateInstance(node); |
2378 node.arguments.forEach(processReference); | 2470 node.argumentRefs.forEach(processReference); |
2379 if (node.typeInformation != null) processReference(node.typeInformation); | 2471 if (node.typeInformationRef != null) { |
2472 processReference(node.typeInformationRef); | |
2473 } | |
2380 } | 2474 } |
2381 | 2475 |
2382 processSetField(SetField node) {} | 2476 processSetField(SetField node) {} |
2383 visitSetField(SetField node) { | 2477 visitSetField(SetField node) { |
2384 processSetField(node); | 2478 processSetField(node); |
2385 processReference(node.object); | 2479 processReference(node.objectRef); |
2386 processReference(node.value); | 2480 processReference(node.valueRef); |
2387 } | 2481 } |
2388 | 2482 |
2389 processGetField(GetField node) {} | 2483 processGetField(GetField node) {} |
2390 visitGetField(GetField node) { | 2484 visitGetField(GetField node) { |
2391 processGetField(node); | 2485 processGetField(node); |
2392 processReference(node.object); | 2486 processReference(node.objectRef); |
2393 } | 2487 } |
2394 | 2488 |
2395 processGetStatic(GetStatic node) {} | 2489 processGetStatic(GetStatic node) {} |
2396 visitGetStatic(GetStatic node) { | 2490 visitGetStatic(GetStatic node) { |
2397 processGetStatic(node); | 2491 processGetStatic(node); |
2398 if (node.witness != null) { | 2492 if (node.witnessRef != null) { |
2399 processReference(node.witness); | 2493 processReference(node.witnessRef); |
2400 } | 2494 } |
2401 } | 2495 } |
2402 | 2496 |
2403 processSetStatic(SetStatic node) {} | 2497 processSetStatic(SetStatic node) {} |
2404 visitSetStatic(SetStatic node) { | 2498 visitSetStatic(SetStatic node) { |
2405 processSetStatic(node); | 2499 processSetStatic(node); |
2406 processReference(node.value); | 2500 processReference(node.valueRef); |
2407 } | 2501 } |
2408 | 2502 |
2409 processCreateBox(CreateBox node) {} | 2503 processCreateBox(CreateBox node) {} |
2410 visitCreateBox(CreateBox node) { | 2504 visitCreateBox(CreateBox node) { |
2411 processCreateBox(node); | 2505 processCreateBox(node); |
2412 } | 2506 } |
2413 | 2507 |
2414 processReifyRuntimeType(ReifyRuntimeType node) {} | 2508 processReifyRuntimeType(ReifyRuntimeType node) {} |
2415 visitReifyRuntimeType(ReifyRuntimeType node) { | 2509 visitReifyRuntimeType(ReifyRuntimeType node) { |
2416 processReifyRuntimeType(node); | 2510 processReifyRuntimeType(node); |
2417 processReference(node.value); | 2511 processReference(node.valueRef); |
2418 } | 2512 } |
2419 | 2513 |
2420 processReadTypeVariable(ReadTypeVariable node) {} | 2514 processReadTypeVariable(ReadTypeVariable node) {} |
2421 visitReadTypeVariable(ReadTypeVariable node) { | 2515 visitReadTypeVariable(ReadTypeVariable node) { |
2422 processReadTypeVariable(node); | 2516 processReadTypeVariable(node); |
2423 processReference(node.target); | 2517 processReference(node.targetRef); |
2424 } | 2518 } |
2425 | 2519 |
2426 processTypeExpression(TypeExpression node) {} | 2520 processTypeExpression(TypeExpression node) {} |
2427 visitTypeExpression(TypeExpression node) { | 2521 visitTypeExpression(TypeExpression node) { |
2428 processTypeExpression(node); | 2522 processTypeExpression(node); |
2429 node.arguments.forEach(processReference); | 2523 node.argumentRefs.forEach(processReference); |
2430 } | 2524 } |
2431 | 2525 |
2432 processCreateInvocationMirror(CreateInvocationMirror node) {} | 2526 processCreateInvocationMirror(CreateInvocationMirror node) {} |
2433 visitCreateInvocationMirror(CreateInvocationMirror node) { | 2527 visitCreateInvocationMirror(CreateInvocationMirror node) { |
2434 processCreateInvocationMirror(node); | 2528 processCreateInvocationMirror(node); |
2435 node.arguments.forEach(processReference); | 2529 node.argumentRefs.forEach(processReference); |
2436 } | 2530 } |
2437 | 2531 |
2438 processApplyBuiltinOperator(ApplyBuiltinOperator node) {} | 2532 processApplyBuiltinOperator(ApplyBuiltinOperator node) {} |
2439 visitApplyBuiltinOperator(ApplyBuiltinOperator node) { | 2533 visitApplyBuiltinOperator(ApplyBuiltinOperator node) { |
2440 processApplyBuiltinOperator(node); | 2534 processApplyBuiltinOperator(node); |
2441 node.arguments.forEach(processReference); | 2535 node.argumentRefs.forEach(processReference); |
2442 } | 2536 } |
2443 | 2537 |
2444 processApplyBuiltinMethod(ApplyBuiltinMethod node) {} | 2538 processApplyBuiltinMethod(ApplyBuiltinMethod node) {} |
2445 visitApplyBuiltinMethod(ApplyBuiltinMethod node) { | 2539 visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
2446 processApplyBuiltinMethod(node); | 2540 processApplyBuiltinMethod(node); |
2447 processReference(node.receiver); | 2541 processReference(node.receiverRef); |
2448 node.arguments.forEach(processReference); | 2542 node.argumentRefs.forEach(processReference); |
2449 } | 2543 } |
2450 | 2544 |
2451 processForeignCode(ForeignCode node) {} | 2545 processForeignCode(ForeignCode node) {} |
2452 visitForeignCode(ForeignCode node) { | 2546 visitForeignCode(ForeignCode node) { |
2453 processForeignCode(node); | 2547 processForeignCode(node); |
2454 node.arguments.forEach(processReference); | 2548 node.argumentRefs.forEach(processReference); |
2455 } | 2549 } |
2456 | 2550 |
2457 processUnreachable(Unreachable node) {} | 2551 processUnreachable(Unreachable node) {} |
2458 visitUnreachable(Unreachable node) { | 2552 visitUnreachable(Unreachable node) { |
2459 processUnreachable(node); | 2553 processUnreachable(node); |
2460 } | 2554 } |
2461 | 2555 |
2462 processAwait(Await node) {} | 2556 processAwait(Await node) {} |
2463 visitAwait(Await node) { | 2557 visitAwait(Await node) { |
2464 processAwait(node); | 2558 processAwait(node); |
2465 processReference(node.input); | 2559 processReference(node.inputRef); |
2466 } | 2560 } |
2467 | 2561 |
2468 processYield(Yield node) {} | 2562 processYield(Yield node) {} |
2469 visitYield(Yield node) { | 2563 visitYield(Yield node) { |
2470 processYield(node); | 2564 processYield(node); |
2471 processReference(node.input); | 2565 processReference(node.inputRef); |
2472 } | 2566 } |
2473 | 2567 |
2474 processGetLength(GetLength node) {} | 2568 processGetLength(GetLength node) {} |
2475 visitGetLength(GetLength node) { | 2569 visitGetLength(GetLength node) { |
2476 processGetLength(node); | 2570 processGetLength(node); |
2477 processReference(node.object); | 2571 processReference(node.objectRef); |
2478 } | 2572 } |
2479 | 2573 |
2480 processGetIndex(GetIndex node) {} | 2574 processGetIndex(GetIndex node) {} |
2481 visitGetIndex(GetIndex node) { | 2575 visitGetIndex(GetIndex node) { |
2482 processGetIndex(node); | 2576 processGetIndex(node); |
2483 processReference(node.object); | 2577 processReference(node.objectRef); |
2484 processReference(node.index); | 2578 processReference(node.indexRef); |
2485 } | 2579 } |
2486 | 2580 |
2487 processSetIndex(SetIndex node) {} | 2581 processSetIndex(SetIndex node) {} |
2488 visitSetIndex(SetIndex node) { | 2582 visitSetIndex(SetIndex node) { |
2489 processSetIndex(node); | 2583 processSetIndex(node); |
2490 processReference(node.object); | 2584 processReference(node.objectRef); |
2491 processReference(node.index); | 2585 processReference(node.indexRef); |
2492 processReference(node.value); | 2586 processReference(node.valueRef); |
2493 } | 2587 } |
2494 | 2588 |
2495 processRefinement(Refinement node) {} | 2589 processRefinement(Refinement node) {} |
2496 visitRefinement(Refinement node) { | 2590 visitRefinement(Refinement node) { |
2497 processRefinement(node); | 2591 processRefinement(node); |
2498 processReference(node.value); | 2592 processReference(node.value); |
2499 } | 2593 } |
2500 | 2594 |
2501 processBoundsCheck(BoundsCheck node) {} | 2595 processBoundsCheck(BoundsCheck node) {} |
2502 visitBoundsCheck(BoundsCheck node) { | 2596 visitBoundsCheck(BoundsCheck node) { |
2503 processBoundsCheck(node); | 2597 processBoundsCheck(node); |
2504 processReference(node.object); | 2598 processReference(node.objectRef); |
2505 if (node.index != null) { | 2599 if (node.indexRef != null) { |
2506 processReference(node.index); | 2600 processReference(node.indexRef); |
2507 } | 2601 } |
2508 if (node.length != null) { | 2602 if (node.lengthRef != null) { |
2509 processReference(node.length); | 2603 processReference(node.lengthRef); |
2510 } | 2604 } |
2511 } | 2605 } |
2512 | 2606 |
2513 processNullCheck(ReceiverCheck node) {} | 2607 processNullCheck(ReceiverCheck node) {} |
2514 visitReceiverCheck(ReceiverCheck node) { | 2608 visitReceiverCheck(ReceiverCheck node) { |
2515 processNullCheck(node); | 2609 processNullCheck(node); |
2516 processReference(node.value); | 2610 processReference(node.valueRef); |
2517 if (node.condition != null) { | 2611 if (node.conditionRef != null) { |
2518 processReference(node.condition); | 2612 processReference(node.conditionRef); |
2519 } | 2613 } |
2520 } | 2614 } |
2521 } | 2615 } |
2522 | 2616 |
2523 typedef void StackAction(); | 2617 typedef void StackAction(); |
2524 | 2618 |
2525 /// Calls `process*` for all nodes in a tree. | 2619 /// Calls `process*` for all nodes in a tree. |
2526 /// For simple usage, only override the `process*` methods. | 2620 /// For simple usage, only override the `process*` methods. |
2527 /// | 2621 /// |
2528 /// To avoid deep recursion, this class uses an "action stack" containing | 2622 /// To avoid deep recursion, this class uses an "action stack" containing |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2604 | 2698 |
2605 Expression traverseLetPrim(LetPrim node) { | 2699 Expression traverseLetPrim(LetPrim node) { |
2606 processLetPrim(node); | 2700 processLetPrim(node); |
2607 visit(node.primitive); | 2701 visit(node.primitive); |
2608 return node.body; | 2702 return node.body; |
2609 } | 2703 } |
2610 | 2704 |
2611 Expression traverseLetMutable(LetMutable node) { | 2705 Expression traverseLetMutable(LetMutable node) { |
2612 processLetMutable(node); | 2706 processLetMutable(node); |
2613 visit(node.variable); | 2707 visit(node.variable); |
2614 processReference(node.value); | 2708 processReference(node.valueRef); |
2615 return node.body; | 2709 return node.body; |
2616 } | 2710 } |
2617 | 2711 |
2618 void _trampoline(Expression node, {int initialHeight}) { | 2712 void _trampoline(Expression node, {int initialHeight}) { |
2619 initialHeight = initialHeight ?? _stack.length; | 2713 initialHeight = initialHeight ?? _stack.length; |
2620 _processBlock(node); | 2714 _processBlock(node); |
2621 while (_stack.length > initialHeight) { | 2715 while (_stack.length > initialHeight) { |
2622 StackAction callback = _stack.removeLast(); | 2716 StackAction callback = _stack.removeLast(); |
2623 callback(); | 2717 callback(); |
2624 } | 2718 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2699 visitLetHandler(LetHandler node) {} | 2793 visitLetHandler(LetHandler node) {} |
2700 visitLetMutable(LetMutable node) {} | 2794 visitLetMutable(LetMutable node) {} |
2701 visitInvokeContinuation(InvokeContinuation node) {} | 2795 visitInvokeContinuation(InvokeContinuation node) {} |
2702 visitThrow(Throw node) {} | 2796 visitThrow(Throw node) {} |
2703 visitRethrow(Rethrow node) {} | 2797 visitRethrow(Rethrow node) {} |
2704 visitBranch(Branch node) {} | 2798 visitBranch(Branch node) {} |
2705 visitUnreachable(Unreachable node) {} | 2799 visitUnreachable(Unreachable node) {} |
2706 visitContinuation(Continuation node) {} | 2800 visitContinuation(Continuation node) {} |
2707 | 2801 |
2708 Definition visitInvokeStatic(InvokeStatic node) { | 2802 Definition visitInvokeStatic(InvokeStatic node) { |
2709 return new InvokeStatic(node.target, node.selector, getList(node.arguments), | 2803 return new InvokeStatic(node.target, node.selector, |
2710 node.sourceInformation); | 2804 getList(node.argumentRefs), node.sourceInformation); |
2711 } | 2805 } |
2712 | 2806 |
2713 Definition visitInvokeMethod(InvokeMethod node) { | 2807 Definition visitInvokeMethod(InvokeMethod node) { |
2714 return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask, | 2808 return new InvokeMethod(getCopy(node.receiverRef), node.selector, node.mask, |
2715 getList(node.arguments), | 2809 getList(node.argumentRefs), |
2716 sourceInformation: node.sourceInformation, | 2810 sourceInformation: node.sourceInformation, |
2717 callingConvention: node.callingConvention); | 2811 callingConvention: node.callingConvention); |
2718 } | 2812 } |
2719 | 2813 |
2720 Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 2814 Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
2721 return new InvokeMethodDirectly(getCopy(node.receiver), node.target, | 2815 return new InvokeMethodDirectly(getCopy(node.receiverRef), node.target, |
2722 node.selector, | 2816 node.selector, |
2723 getList(node.arguments), | 2817 getList(node.argumentRefs), |
2724 node.sourceInformation, | 2818 node.sourceInformation, |
2725 callingConvention: node.callingConvention); | 2819 callingConvention: node.callingConvention); |
2726 } | 2820 } |
2727 | 2821 |
2728 Definition visitInvokeConstructor(InvokeConstructor node) { | 2822 Definition visitInvokeConstructor(InvokeConstructor node) { |
2729 return new InvokeConstructor(node.dartType, node.target, node.selector, | 2823 return new InvokeConstructor(node.dartType, node.target, node.selector, |
2730 getList(node.arguments), | 2824 getList(node.argumentRefs), |
2731 node.sourceInformation) | 2825 node.sourceInformation) |
2732 ..allocationSiteType = node.allocationSiteType; | 2826 ..allocationSiteType = node.allocationSiteType; |
2733 } | 2827 } |
2734 | 2828 |
2735 Definition visitTypeCast(TypeCast node) { | 2829 Definition visitTypeCast(TypeCast node) { |
2736 return new TypeCast(getCopy(node.value), node.dartType, | 2830 return new TypeCast(getCopy(node.valueRef), node.dartType, |
2737 getList(node.typeArguments)); | 2831 getList(node.typeArgumentRefs)); |
2738 } | 2832 } |
2739 | 2833 |
2740 Definition visitSetMutable(SetMutable node) { | 2834 Definition visitSetMutable(SetMutable node) { |
2741 return new SetMutable(getCopy(node.variable), getCopy(node.value)); | 2835 return new SetMutable(getCopy(node.variableRef), getCopy(node.valueRef)); |
2742 } | 2836 } |
2743 | 2837 |
2744 Definition visitSetStatic(SetStatic node) { | 2838 Definition visitSetStatic(SetStatic node) { |
2745 return new SetStatic(node.element, getCopy(node.value), | 2839 return new SetStatic(node.element, getCopy(node.valueRef), |
2746 node.sourceInformation); | 2840 node.sourceInformation); |
2747 } | 2841 } |
2748 | 2842 |
2749 Definition visitSetField(SetField node) { | 2843 Definition visitSetField(SetField node) { |
2750 return new SetField(getCopy(node.object), node.field, getCopy(node.value)); | 2844 return new SetField(getCopy(node.objectRef), node.field, |
2845 getCopy(node.valueRef)); | |
2751 } | 2846 } |
2752 | 2847 |
2753 Definition visitGetLazyStatic(GetLazyStatic node) { | 2848 Definition visitGetLazyStatic(GetLazyStatic node) { |
2754 return new GetLazyStatic(node.element, | 2849 return new GetLazyStatic(node.element, |
2755 isFinal: node.isFinal, | 2850 isFinal: node.isFinal, |
2756 sourceInformation: node.sourceInformation); | 2851 sourceInformation: node.sourceInformation); |
2757 } | 2852 } |
2758 | 2853 |
2759 Definition visitAwait(Await node) { | 2854 Definition visitAwait(Await node) { |
2760 return new Await(getCopy(node.input)); | 2855 return new Await(getCopy(node.inputRef)); |
2761 } | 2856 } |
2762 | 2857 |
2763 Definition visitYield(Yield node) { | 2858 Definition visitYield(Yield node) { |
2764 return new Yield(getCopy(node.input), node.hasStar); | 2859 return new Yield(getCopy(node.inputRef), node.hasStar); |
2765 } | 2860 } |
2766 | 2861 |
2767 Definition visitLiteralList(LiteralList node) { | 2862 Definition visitLiteralList(LiteralList node) { |
2768 return new LiteralList(node.dartType, getList(node.values)) | 2863 return new LiteralList(node.dartType, getList(node.valueRefs)) |
2769 ..allocationSiteType = node.allocationSiteType; | 2864 ..allocationSiteType = node.allocationSiteType; |
2770 } | 2865 } |
2771 | 2866 |
2772 Definition visitConstant(Constant node) { | 2867 Definition visitConstant(Constant node) { |
2773 return new Constant(node.value, sourceInformation: node.sourceInformation); | 2868 return new Constant(node.value, sourceInformation: node.sourceInformation); |
2774 } | 2869 } |
2775 | 2870 |
2776 Definition visitGetMutable(GetMutable node) { | 2871 Definition visitGetMutable(GetMutable node) { |
2777 return new GetMutable(getCopy(node.variable)); | 2872 return new GetMutable(getCopy(node.variableRef)); |
2778 } | 2873 } |
2779 | 2874 |
2780 Definition visitParameter(Parameter node) { | 2875 Definition visitParameter(Parameter node) { |
2781 return new Parameter(node.hint); | 2876 return new Parameter(node.hint); |
2782 } | 2877 } |
2783 | 2878 |
2784 Definition visitMutableVariable(MutableVariable node) { | 2879 Definition visitMutableVariable(MutableVariable node) { |
2785 return new MutableVariable(node.hint); | 2880 return new MutableVariable(node.hint); |
2786 } | 2881 } |
2787 | 2882 |
2788 Definition visitGetStatic(GetStatic node) { | 2883 Definition visitGetStatic(GetStatic node) { |
2789 if (node.witness != null) { | 2884 if (node.witnessRef != null) { |
2790 return new GetStatic.witnessed(node.element, | 2885 return new GetStatic.witnessed(node.element, |
2791 getCopy(node.witness), | 2886 getCopy(node.witnessRef), |
2792 sourceInformation: node.sourceInformation); | 2887 sourceInformation: node.sourceInformation); |
2793 } else { | 2888 } else { |
2794 return new GetStatic(node.element, | 2889 return new GetStatic(node.element, |
2795 isFinal: node.isFinal, | 2890 isFinal: node.isFinal, |
2796 sourceInformation: node.sourceInformation); | 2891 sourceInformation: node.sourceInformation); |
2797 } | 2892 } |
2798 } | 2893 } |
2799 | 2894 |
2800 Definition visitInterceptor(Interceptor node) { | 2895 Definition visitInterceptor(Interceptor node) { |
2801 return new Interceptor(getCopy(node.input), node.sourceInformation) | 2896 return new Interceptor(getCopy(node.inputRef), node.sourceInformation) |
2802 ..interceptedClasses.addAll(node.interceptedClasses); | 2897 ..interceptedClasses.addAll(node.interceptedClasses); |
2803 } | 2898 } |
2804 | 2899 |
2805 Definition visitCreateInstance(CreateInstance node) { | 2900 Definition visitCreateInstance(CreateInstance node) { |
2806 return new CreateInstance( | 2901 return new CreateInstance( |
2807 node.classElement, | 2902 node.classElement, |
2808 getList(node.arguments), | 2903 getList(node.argumentRefs), |
2809 node.typeInformation == null ? null : getCopy(node.typeInformation), | 2904 getCopyOrNull(node.typeInformationRef), |
2810 node.sourceInformation); | 2905 node.sourceInformation); |
2811 } | 2906 } |
2812 | 2907 |
2813 Definition visitGetField(GetField node) { | 2908 Definition visitGetField(GetField node) { |
2814 return new GetField(getCopy(node.object), node.field, | 2909 return new GetField(getCopy(node.objectRef), node.field, |
2815 isFinal: node.isFinal); | 2910 isFinal: node.isFinal); |
2816 } | 2911 } |
2817 | 2912 |
2818 Definition visitCreateBox(CreateBox node) { | 2913 Definition visitCreateBox(CreateBox node) { |
2819 return new CreateBox(); | 2914 return new CreateBox(); |
2820 } | 2915 } |
2821 | 2916 |
2822 Definition visitReifyRuntimeType(ReifyRuntimeType node) { | 2917 Definition visitReifyRuntimeType(ReifyRuntimeType node) { |
2823 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); | 2918 return new ReifyRuntimeType(getCopy(node.valueRef), node.sourceInformation); |
2824 } | 2919 } |
2825 | 2920 |
2826 Definition visitReadTypeVariable(ReadTypeVariable node) { | 2921 Definition visitReadTypeVariable(ReadTypeVariable node) { |
2827 return new ReadTypeVariable(node.variable, getCopy(node.target), | 2922 return new ReadTypeVariable(node.variable, getCopy(node.targetRef), |
2828 node.sourceInformation); | 2923 node.sourceInformation); |
2829 } | 2924 } |
2830 | 2925 |
2831 Definition visitTypeExpression(TypeExpression node) { | 2926 Definition visitTypeExpression(TypeExpression node) { |
2832 return new TypeExpression( | 2927 return new TypeExpression( |
2833 node.kind, node.dartType, getList(node.arguments)); | 2928 node.kind, node.dartType, getList(node.argumentRefs)); |
2834 } | 2929 } |
2835 | 2930 |
2836 Definition visitCreateInvocationMirror(CreateInvocationMirror node) { | 2931 Definition visitCreateInvocationMirror(CreateInvocationMirror node) { |
2837 return new CreateInvocationMirror(node.selector, getList(node.arguments)); | 2932 return new CreateInvocationMirror(node.selector, |
2933 getList(node.argumentRefs)); | |
2838 } | 2934 } |
2839 | 2935 |
2840 Definition visitTypeTest(TypeTest node) { | 2936 Definition visitTypeTest(TypeTest node) { |
2841 return new TypeTest(getCopy(node.value), node.dartType, | 2937 return new TypeTest(getCopy(node.valueRef), node.dartType, |
2842 getList(node.typeArguments)); | 2938 getList(node.typeArgumentRefs)); |
2843 } | 2939 } |
2844 | 2940 |
2845 Definition visitTypeTestViaFlag(TypeTestViaFlag node) { | 2941 Definition visitTypeTestViaFlag(TypeTestViaFlag node) { |
2846 return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType); | 2942 return new TypeTestViaFlag(getCopy(node.interceptorRef), node.dartType); |
2847 } | 2943 } |
2848 | 2944 |
2849 Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) { | 2945 Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) { |
2850 return new ApplyBuiltinOperator(node.operator, getList(node.arguments), | 2946 return new ApplyBuiltinOperator(node.operator, getList(node.argumentRefs), |
2851 node.sourceInformation); | 2947 node.sourceInformation); |
2852 } | 2948 } |
2853 | 2949 |
2854 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) { | 2950 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
2855 return new ApplyBuiltinMethod(node.method, getCopy(node.receiver), | 2951 return new ApplyBuiltinMethod(node.method, getCopy(node.receiverRef), |
2856 getList(node.arguments), | 2952 getList(node.argumentRefs), |
2857 node.sourceInformation, | 2953 node.sourceInformation, |
2858 receiverIsNotNull: node.receiverIsNotNull); | 2954 receiverIsNotNull: node.receiverIsNotNull); |
2859 } | 2955 } |
2860 | 2956 |
2861 Definition visitGetLength(GetLength node) { | 2957 Definition visitGetLength(GetLength node) { |
2862 return new GetLength(getCopy(node.object), isFinal: node.isFinal); | 2958 return new GetLength(getCopy(node.objectRef), isFinal: node.isFinal); |
2863 } | 2959 } |
2864 | 2960 |
2865 Definition visitGetIndex(GetIndex node) { | 2961 Definition visitGetIndex(GetIndex node) { |
2866 return new GetIndex(getCopy(node.object), getCopy(node.index)); | 2962 return new GetIndex(getCopy(node.objectRef), getCopy(node.indexRef)); |
2867 } | 2963 } |
2868 | 2964 |
2869 Definition visitSetIndex(SetIndex node) { | 2965 Definition visitSetIndex(SetIndex node) { |
2870 return new SetIndex(getCopy(node.object), getCopy(node.index), | 2966 return new SetIndex(getCopy(node.objectRef), getCopy(node.indexRef), |
2871 getCopy(node.value)); | 2967 getCopy(node.valueRef)); |
2872 } | 2968 } |
2873 | 2969 |
2874 Definition visitRefinement(Refinement node) { | 2970 Definition visitRefinement(Refinement node) { |
2875 return new Refinement(getCopy(node.value), node.refineType); | 2971 return new Refinement(getCopy(node.value), node.refineType); |
2876 } | 2972 } |
2877 | 2973 |
2878 Definition visitBoundsCheck(BoundsCheck node) { | 2974 Definition visitBoundsCheck(BoundsCheck node) { |
2879 if (node.hasNoChecks) { | 2975 if (node.hasNoChecks) { |
2880 return new BoundsCheck.noCheck(getCopy(node.object), | 2976 return new BoundsCheck.noCheck(getCopy(node.objectRef), |
2881 node.sourceInformation); | 2977 node.sourceInformation); |
2882 } else { | 2978 } else { |
2883 return new BoundsCheck(getCopy(node.object), getCopy(node.index), | 2979 return new BoundsCheck(getCopy(node.objectRef), getCopy(node.indexRef), |
2884 getCopyOrNull(node.length), | 2980 getCopyOrNull(node.lengthRef), |
2885 node.checks, | 2981 node.checks, |
2886 node.sourceInformation); | 2982 node.sourceInformation); |
2887 } | 2983 } |
2888 } | 2984 } |
2889 | 2985 |
2890 Definition visitReceiverCheck(ReceiverCheck node) { | 2986 Definition visitReceiverCheck(ReceiverCheck node) { |
2891 return new ReceiverCheck(getCopy(node.value), | 2987 return new ReceiverCheck(getCopy(node.valueRef), |
2892 node.selector, | 2988 node.selector, |
2893 node.sourceInformation, | 2989 node.sourceInformation, |
2894 condition: getCopyOrNull(node.condition), | 2990 condition: getCopyOrNull(node.conditionRef), |
2895 useSelector: node.useSelector, | 2991 useSelector: node.useSelector, |
2896 isNullCheck: node.isNullCheck); | 2992 isNullCheck: node.isNullCheck); |
2897 } | 2993 } |
2898 | 2994 |
2899 Definition visitForeignCode(ForeignCode node) { | 2995 Definition visitForeignCode(ForeignCode node) { |
2900 return new ForeignCode(node.codeTemplate, node.storedType, | 2996 return new ForeignCode(node.codeTemplate, node.storedType, |
2901 getList(node.arguments), | 2997 getList(node.argumentRefs), |
2902 node.nativeBehavior, | 2998 node.nativeBehavior, |
2903 dependency: node.dependency); | 2999 dependency: node.dependency); |
2904 } | 3000 } |
2905 } | 3001 } |
2906 | 3002 |
2907 /// A trampolining visitor to copy [FunctionDefinition]s. | 3003 /// A trampolining visitor to copy [FunctionDefinition]s. |
2908 class CopyingVisitor extends TrampolineRecursiveVisitor { | 3004 class CopyingVisitor extends TrampolineRecursiveVisitor { |
2909 // The visitor maintains a map from original continuations to their copies. | 3005 // The visitor maintains a map from original continuations to their copies. |
2910 Map<Continuation, Continuation> _copies = <Continuation, Continuation>{}; | 3006 Map<Continuation, Continuation> _copies = <Continuation, Continuation>{}; |
2911 | 3007 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3004 return node.body; | 3100 return node.body; |
3005 } | 3101 } |
3006 | 3102 |
3007 Expression traverseLetPrim(LetPrim node) { | 3103 Expression traverseLetPrim(LetPrim node) { |
3008 plug(new LetPrim(_definitions.copy(node.primitive))); | 3104 plug(new LetPrim(_definitions.copy(node.primitive))); |
3009 return node.body; | 3105 return node.body; |
3010 } | 3106 } |
3011 | 3107 |
3012 Expression traverseLetMutable(LetMutable node) { | 3108 Expression traverseLetMutable(LetMutable node) { |
3013 plug(new LetMutable(_definitions.copy(node.variable), | 3109 plug(new LetMutable(_definitions.copy(node.variable), |
3014 _definitions.getCopy(node.value))); | 3110 _definitions.getCopy(node.valueRef))); |
3015 return node.body; | 3111 return node.body; |
3016 } | 3112 } |
3017 | 3113 |
3018 // Tail expressions do not have references, so we do not need to map them | 3114 // Tail expressions do not have references, so we do not need to map them |
3019 // to their copies. | 3115 // to their copies. |
3020 visitInvokeContinuation(InvokeContinuation node) { | 3116 visitInvokeContinuation(InvokeContinuation node) { |
3021 plug(new InvokeContinuation(_copies[node.continuation.definition], | 3117 plug(new InvokeContinuation(_copies[node.continuation], |
3022 _definitions.getList(node.arguments), | 3118 _definitions.getList(node.argumentRefs), |
3023 isRecursive: node.isRecursive, | 3119 isRecursive: node.isRecursive, |
3024 isEscapingTry: node.isEscapingTry, | 3120 isEscapingTry: node.isEscapingTry, |
3025 sourceInformation: node.sourceInformation)); | 3121 sourceInformation: node.sourceInformation)); |
3026 } | 3122 } |
3027 | 3123 |
3028 visitThrow(Throw node) { | 3124 visitThrow(Throw node) { |
3029 plug(new Throw(_definitions.getCopy(node.value))); | 3125 plug(new Throw(_definitions.getCopy(node.valueRef))); |
3030 } | 3126 } |
3031 | 3127 |
3032 visitRethrow(Rethrow node) { | 3128 visitRethrow(Rethrow node) { |
3033 plug(new Rethrow()); | 3129 plug(new Rethrow()); |
3034 } | 3130 } |
3035 | 3131 |
3036 visitBranch(Branch node) { | 3132 visitBranch(Branch node) { |
3037 plug(new Branch.loose(_definitions.getCopy(node.condition), | 3133 plug(new Branch.loose(_definitions.getCopy(node.conditionRef), |
3038 _copies[node.trueContinuation.definition], | 3134 _copies[node.trueContinuation], |
3039 _copies[node.falseContinuation.definition]) | 3135 _copies[node.falseContinuation]) |
3040 ..isStrictCheck = node.isStrictCheck); | 3136 ..isStrictCheck = node.isStrictCheck); |
3041 } | 3137 } |
3042 | 3138 |
3043 visitUnreachable(Unreachable node) { | 3139 visitUnreachable(Unreachable node) { |
3044 plug(new Unreachable()); | 3140 plug(new Unreachable()); |
3045 } | 3141 } |
3046 } | 3142 } |
OLD | NEW |