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 '../constants/values.dart' as values show ConstantValue; | 6 import '../constants/values.dart' as values show ConstantValue; |
7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
9 import '../io/source_information.dart' show SourceInformation; | 9 import '../io/source_information.dart' show SourceInformation; |
10 import '../types/types.dart' show TypeMask; | 10 import '../types/types.dart' show TypeMask; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 if (this.hint == null) { | 88 if (this.hint == null) { |
89 this.hint = hint; | 89 this.hint = hint; |
90 } | 90 } |
91 } | 91 } |
92 | 92 |
93 /// True if the primitive can be removed, assuming it has no uses | 93 /// True if the primitive can be removed, assuming it has no uses |
94 /// (this getter does not check if there are any uses). | 94 /// (this getter does not check if there are any uses). |
95 /// | 95 /// |
96 /// False must be returned for primitives that may throw, diverge, or have | 96 /// False must be returned for primitives that may throw, diverge, or have |
97 /// observable side-effects. | 97 /// observable side-effects. |
98 bool get isSafeForElimination => true; | 98 bool get isSafeForElimination; |
| 99 |
| 100 /// True if time-of-evaluation is irrelevant for the given primitive, |
| 101 /// assuming its inputs are the same values. |
| 102 bool get isSafeForReordering; |
99 } | 103 } |
100 | 104 |
101 /// Operands to invocations and primitives are always variables. They point to | 105 /// Operands to invocations and primitives are always variables. They point to |
102 /// their definition and are doubly-linked into a list of occurrences. | 106 /// their definition and are doubly-linked into a list of occurrences. |
103 class Reference<T extends Definition<T>> { | 107 class Reference<T extends Definition<T>> { |
104 T definition; | 108 T definition; |
105 Reference<T> previous; | 109 Reference<T> previous; |
106 Reference<T> next; | 110 Reference<T> next; |
107 | 111 |
108 /// A pointer to the parent node. Is null until set by optimization passes. | 112 /// A pointer to the parent node. Is null until set by optimization passes. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 final SourceInformation sourceInformation; | 263 final SourceInformation sourceInformation; |
260 | 264 |
261 InvokeStatic(this.target, | 265 InvokeStatic(this.target, |
262 this.selector, | 266 this.selector, |
263 List<Primitive> args, | 267 List<Primitive> args, |
264 Continuation cont, | 268 Continuation cont, |
265 [this.sourceInformation]) | 269 [this.sourceInformation]) |
266 : arguments = _referenceList(args), | 270 : arguments = _referenceList(args), |
267 continuation = new Reference<Continuation>(cont); | 271 continuation = new Reference<Continuation>(cont); |
268 | 272 |
| 273 InvokeStatic.byReference(this.target, |
| 274 this.selector, |
| 275 this.arguments, |
| 276 this.continuation, |
| 277 [this.sourceInformation]); |
| 278 |
269 accept(Visitor visitor) => visitor.visitInvokeStatic(this); | 279 accept(Visitor visitor) => visitor.visitInvokeStatic(this); |
270 } | 280 } |
271 | 281 |
272 /// Invoke a method on an object. | 282 /// Invoke a method on an object. |
273 /// | 283 /// |
274 /// This includes getters, setters, operators, and index getter/setters. | 284 /// This includes getters, setters, operators, and index getter/setters. |
275 /// | 285 /// |
276 /// Tearing off a method is treated like a getter invocation (getters and | 286 /// Tearing off a method is treated like a getter invocation (getters and |
277 /// tear-offs cannot be distinguished at compile-time). | 287 /// tear-offs cannot be distinguished at compile-time). |
278 /// | 288 /// |
(...skipping 13 matching lines...) Expand all Loading... |
292 InvokeMethod(Primitive receiver, | 302 InvokeMethod(Primitive receiver, |
293 this.selector, | 303 this.selector, |
294 this.mask, | 304 this.mask, |
295 List<Primitive> arguments, | 305 List<Primitive> arguments, |
296 Continuation continuation, | 306 Continuation continuation, |
297 [this.sourceInformation]) | 307 [this.sourceInformation]) |
298 : this.receiver = new Reference<Primitive>(receiver), | 308 : this.receiver = new Reference<Primitive>(receiver), |
299 this.arguments = _referenceList(arguments), | 309 this.arguments = _referenceList(arguments), |
300 this.continuation = new Reference<Continuation>(continuation); | 310 this.continuation = new Reference<Continuation>(continuation); |
301 | 311 |
| 312 InvokeMethod.byReference(this.receiver, |
| 313 this.selector, |
| 314 this.mask, |
| 315 this.arguments, |
| 316 this.continuation, |
| 317 [this.sourceInformation]); |
| 318 |
302 accept(Visitor visitor) => visitor.visitInvokeMethod(this); | 319 accept(Visitor visitor) => visitor.visitInvokeMethod(this); |
303 } | 320 } |
304 | 321 |
305 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. | 322 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. |
306 /// | 323 /// |
307 /// That is, if [receiver] is an instance of a class that overrides [target] | 324 /// That is, if [receiver] is an instance of a class that overrides [target] |
308 /// with a different implementation, the overriding implementation is bypassed | 325 /// with a different implementation, the overriding implementation is bypassed |
309 /// and [target]'s implementation is invoked. | 326 /// and [target]'s implementation is invoked. |
310 /// | 327 /// |
311 /// As with [InvokeMethod], this can be used to invoke a method, operator, | 328 /// As with [InvokeMethod], this can be used to invoke a method, operator, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 /// Otherwise the list is empty. | 414 /// Otherwise the list is empty. |
398 final List<Reference<Primitive>> typeArguments; | 415 final List<Reference<Primitive>> typeArguments; |
399 | 416 |
400 TypeTest(Primitive value, | 417 TypeTest(Primitive value, |
401 this.type, | 418 this.type, |
402 List<Primitive> typeArguments) | 419 List<Primitive> typeArguments) |
403 : this.value = new Reference<Primitive>(value), | 420 : this.value = new Reference<Primitive>(value), |
404 this.typeArguments = _referenceList(typeArguments); | 421 this.typeArguments = _referenceList(typeArguments); |
405 | 422 |
406 accept(Visitor visitor) => visitor.visitTypeTest(this); | 423 accept(Visitor visitor) => visitor.visitTypeTest(this); |
| 424 |
| 425 bool get isSafeForElimination => true; |
| 426 bool get isSafeForReordering => true; |
407 } | 427 } |
408 | 428 |
409 /// An "as" type cast. | 429 /// An "as" type cast. |
410 /// | 430 /// |
411 /// If [value] is `null` or is an instance of [type], [continuation] is invoked | 431 /// If [value] is `null` or is an instance of [type], [continuation] is invoked |
412 /// with [value] as argument. Otherwise, a [CastError] is thrown. | 432 /// with [value] as argument. Otherwise, a [CastError] is thrown. |
413 /// | 433 /// |
414 /// Discussion: | 434 /// Discussion: |
415 /// The parameter to [continuation] is redundant since it will always equal | 435 /// The parameter to [continuation] is redundant since it will always equal |
416 /// [value], which is typically in scope in the continuation. However, it might | 436 /// [value], which is typically in scope in the continuation. However, it might |
(...skipping 22 matching lines...) Expand all Loading... |
439 /// | 459 /// |
440 /// It must be known that the arguments have the proper types. | 460 /// It must be known that the arguments have the proper types. |
441 class ApplyBuiltinOperator extends Primitive { | 461 class ApplyBuiltinOperator extends Primitive { |
442 BuiltinOperator operator; | 462 BuiltinOperator operator; |
443 List<Reference<Primitive>> arguments; | 463 List<Reference<Primitive>> arguments; |
444 | 464 |
445 ApplyBuiltinOperator(this.operator, List<Primitive> arguments) | 465 ApplyBuiltinOperator(this.operator, List<Primitive> arguments) |
446 : this.arguments = _referenceList(arguments); | 466 : this.arguments = _referenceList(arguments); |
447 | 467 |
448 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); | 468 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); |
| 469 |
| 470 bool get isSafeForElimination => true; |
| 471 bool get isSafeForReordering => true; |
449 } | 472 } |
450 | 473 |
451 /// Throw a value. | 474 /// Throw a value. |
452 /// | 475 /// |
453 /// Throw is an expression, i.e., it always occurs in tail position with | 476 /// Throw is an expression, i.e., it always occurs in tail position with |
454 /// respect to a body or expression. | 477 /// respect to a body or expression. |
455 class Throw extends Expression { | 478 class Throw extends Expression { |
456 Reference<Primitive> value; | 479 Reference<Primitive> value; |
457 | 480 |
458 Throw(Primitive value) : value = new Reference<Primitive>(value); | 481 Throw(Primitive value) : value = new Reference<Primitive>(value); |
(...skipping 15 matching lines...) Expand all Loading... |
474 /// The CPS translation of an expression produces a primitive as the value | 497 /// The CPS translation of an expression produces a primitive as the value |
475 /// of the expression. For convenience in the implementation of the | 498 /// of the expression. For convenience in the implementation of the |
476 /// translation, a [NonTailThrow] is used as that value. A cleanup pass | 499 /// translation, a [NonTailThrow] is used as that value. A cleanup pass |
477 /// removes these and replaces them with [Throw] expressions. | 500 /// removes these and replaces them with [Throw] expressions. |
478 class NonTailThrow extends Primitive { | 501 class NonTailThrow extends Primitive { |
479 final Reference<Primitive> value; | 502 final Reference<Primitive> value; |
480 | 503 |
481 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); | 504 NonTailThrow(Primitive value) : value = new Reference<Primitive>(value); |
482 | 505 |
483 accept(Visitor visitor) => visitor.visitNonTailThrow(this); | 506 accept(Visitor visitor) => visitor.visitNonTailThrow(this); |
| 507 |
| 508 bool get isSafeForElimination => false; |
| 509 bool get isSafeForReordering => false; |
484 } | 510 } |
485 | 511 |
486 /// An expression that is known to be unreachable. | 512 /// An expression that is known to be unreachable. |
487 /// | 513 /// |
488 /// This can be placed as the body of a call continuation, when the caller is | 514 /// This can be placed as the body of a call continuation, when the caller is |
489 /// known never to invoke it, e.g. because the calling expression always throws. | 515 /// known never to invoke it, e.g. because the calling expression always throws. |
490 class Unreachable extends Expression { | 516 class Unreachable extends Expression { |
491 accept(Visitor visitor) => visitor.visitUnreachable(this); | 517 accept(Visitor visitor) => visitor.visitUnreachable(this); |
492 } | 518 } |
493 | 519 |
494 /// Gets the value from a [MutableVariable]. | 520 /// Gets the value from a [MutableVariable]. |
495 /// | 521 /// |
496 /// [MutableVariable]s can be seen as ref cells that are not first-class | 522 /// [MutableVariable]s can be seen as ref cells that are not first-class |
497 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: | 523 /// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: |
498 /// | 524 /// |
499 /// let prim p = ![variable] in [body] | 525 /// let prim p = ![variable] in [body] |
500 /// | 526 /// |
501 class GetMutableVariable extends Primitive { | 527 class GetMutableVariable extends Primitive { |
502 final Reference<MutableVariable> variable; | 528 final Reference<MutableVariable> variable; |
503 | 529 |
504 GetMutableVariable(MutableVariable variable) | 530 GetMutableVariable(MutableVariable variable) |
505 : this.variable = new Reference<MutableVariable>(variable); | 531 : this.variable = new Reference<MutableVariable>(variable); |
506 | 532 |
507 accept(Visitor visitor) => visitor.visitGetMutableVariable(this); | 533 accept(Visitor visitor) => visitor.visitGetMutableVariable(this); |
| 534 |
| 535 bool get isSafeForElimination => true; |
| 536 bool get isSafeForReordering => false; |
508 } | 537 } |
509 | 538 |
510 /// Assign a [MutableVariable]. | 539 /// Assign a [MutableVariable]. |
511 /// | 540 /// |
512 /// [MutableVariable]s can be seen as ref cells that are not first-class | 541 /// [MutableVariable]s can be seen as ref cells that are not first-class |
513 /// values. This can be seen as a dereferencing assignment: | 542 /// values. This can be seen as a dereferencing assignment: |
514 /// | 543 /// |
515 /// { [variable] := [value]; [body] } | 544 /// { [variable] := [value]; [body] } |
516 class SetMutableVariable extends Expression implements InteriorNode { | 545 class SetMutableVariable extends Expression implements InteriorNode { |
517 final Reference<MutableVariable> variable; | 546 final Reference<MutableVariable> variable; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 /// True if the object is known not to be null. | 644 /// True if the object is known not to be null. |
616 // TODO(asgerf): This is a placeholder until we agree on how to track | 645 // TODO(asgerf): This is a placeholder until we agree on how to track |
617 // side effects. | 646 // side effects. |
618 bool objectIsNotNull = false; | 647 bool objectIsNotNull = false; |
619 | 648 |
620 GetField(Primitive object, this.field) | 649 GetField(Primitive object, this.field) |
621 : this.object = new Reference<Primitive>(object); | 650 : this.object = new Reference<Primitive>(object); |
622 | 651 |
623 accept(Visitor visitor) => visitor.visitGetField(this); | 652 accept(Visitor visitor) => visitor.visitGetField(this); |
624 | 653 |
625 @override | |
626 bool get isSafeForElimination => objectIsNotNull; | 654 bool get isSafeForElimination => objectIsNotNull; |
| 655 bool get isSafeForReordering => objectIsNotNull && field.isFinal; |
627 } | 656 } |
628 | 657 |
629 /// Reads the value of a static field or tears off a static method. | 658 /// Reads the value of a static field or tears off a static method. |
| 659 /// |
| 660 /// Note that lazily initialized fields should be read using GetLazyStatic. |
630 class GetStatic extends Primitive { | 661 class GetStatic extends Primitive { |
631 /// Can be [FieldElement] or [FunctionElement]. | 662 /// Can be [FieldElement] or [FunctionElement]. |
632 final Element element; | 663 final Element element; |
633 final SourceInformation sourceInformation; | 664 final SourceInformation sourceInformation; |
634 | 665 |
635 GetStatic(this.element, [this.sourceInformation]); | 666 GetStatic(this.element, [this.sourceInformation]); |
636 | 667 |
637 accept(Visitor visitor) => visitor.visitGetStatic(this); | 668 accept(Visitor visitor) => visitor.visitGetStatic(this); |
| 669 |
| 670 bool get isSafeForElimination { |
| 671 return true; |
| 672 } |
| 673 bool get isSafeForReordering { |
| 674 return element is FunctionElement || element.isFinal; |
| 675 } |
638 } | 676 } |
639 | 677 |
640 /// Sets the value of a static field. | 678 /// Sets the value of a static field. |
641 class SetStatic extends Expression implements InteriorNode { | 679 class SetStatic extends Expression implements InteriorNode { |
642 final FieldElement element; | 680 final FieldElement element; |
643 final Reference<Primitive> value; | 681 final Reference<Primitive> value; |
644 Expression body; | 682 Expression body; |
645 final SourceInformation sourceInformation; | 683 final SourceInformation sourceInformation; |
646 | 684 |
647 SetStatic(this.element, Primitive value, [this.sourceInformation]) | 685 SetStatic(this.element, Primitive value, [this.sourceInformation]) |
(...skipping 22 matching lines...) Expand all Loading... |
670 Continuation continuation, | 708 Continuation continuation, |
671 [this.sourceInformation]) | 709 [this.sourceInformation]) |
672 : continuation = new Reference<Continuation>(continuation); | 710 : continuation = new Reference<Continuation>(continuation); |
673 | 711 |
674 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); | 712 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); |
675 } | 713 } |
676 | 714 |
677 /// Creates an object for holding boxed variables captured by a closure. | 715 /// Creates an object for holding boxed variables captured by a closure. |
678 class CreateBox extends Primitive { | 716 class CreateBox extends Primitive { |
679 accept(Visitor visitor) => visitor.visitCreateBox(this); | 717 accept(Visitor visitor) => visitor.visitCreateBox(this); |
| 718 |
| 719 bool get isSafeForElimination => true; |
| 720 bool get isSafeForReordering => true; |
680 } | 721 } |
681 | 722 |
682 /// Creates an instance of a class and initializes its fields and runtime type | 723 /// Creates an instance of a class and initializes its fields and runtime type |
683 /// information. | 724 /// information. |
684 class CreateInstance extends Primitive { | 725 class CreateInstance extends Primitive { |
685 final ClassElement classElement; | 726 final ClassElement classElement; |
686 | 727 |
687 /// Initial values for the fields on the class. | 728 /// Initial values for the fields on the class. |
688 /// The order corresponds to the order of fields on the class. | 729 /// The order corresponds to the order of fields on the class. |
689 final List<Reference<Primitive>> arguments; | 730 final List<Reference<Primitive>> arguments; |
690 | 731 |
691 /// The runtime type information structure which contains the type arguments. | 732 /// The runtime type information structure which contains the type arguments. |
692 /// | 733 /// |
693 /// May be `null` to indicate that no type information is needed because the | 734 /// May be `null` to indicate that no type information is needed because the |
694 /// compiler determined that the type information for instances of this class | 735 /// compiler determined that the type information for instances of this class |
695 /// is not needed at runtime. | 736 /// is not needed at runtime. |
696 final List<Reference<Primitive>> typeInformation; | 737 final List<Reference<Primitive>> typeInformation; |
697 | 738 |
698 CreateInstance(this.classElement, List<Primitive> arguments, | 739 CreateInstance(this.classElement, List<Primitive> arguments, |
699 List<Primitive> typeInformation) | 740 List<Primitive> typeInformation) |
700 : this.arguments = _referenceList(arguments), | 741 : this.arguments = _referenceList(arguments), |
701 this.typeInformation = _referenceList(typeInformation); | 742 this.typeInformation = _referenceList(typeInformation); |
702 | 743 |
703 accept(Visitor visitor) => visitor.visitCreateInstance(this); | 744 accept(Visitor visitor) => visitor.visitCreateInstance(this); |
| 745 |
| 746 bool get isSafeForElimination => true; |
| 747 bool get isSafeForReordering => true; |
704 } | 748 } |
705 | 749 |
706 class Interceptor extends Primitive { | 750 class Interceptor extends Primitive { |
707 final Reference<Primitive> input; | 751 final Reference<Primitive> input; |
708 final Set<ClassElement> interceptedClasses; | 752 final Set<ClassElement> interceptedClasses; |
709 Interceptor(Primitive input, this.interceptedClasses) | 753 Interceptor(Primitive input, this.interceptedClasses) |
710 : this.input = new Reference<Primitive>(input); | 754 : this.input = new Reference<Primitive>(input); |
711 accept(Visitor visitor) => visitor.visitInterceptor(this); | 755 accept(Visitor visitor) => visitor.visitInterceptor(this); |
| 756 |
| 757 bool get isSafeForElimination => true; |
| 758 bool get isSafeForReordering => true; |
712 } | 759 } |
713 | 760 |
714 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. | 761 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. |
715 class CreateInvocationMirror extends Primitive { | 762 class CreateInvocationMirror extends Primitive { |
716 final Selector selector; | 763 final Selector selector; |
717 final List<Reference<Primitive>> arguments; | 764 final List<Reference<Primitive>> arguments; |
718 | 765 |
719 CreateInvocationMirror(this.selector, List<Primitive> arguments) | 766 CreateInvocationMirror(this.selector, List<Primitive> arguments) |
720 : this.arguments = _referenceList(arguments); | 767 : this.arguments = _referenceList(arguments); |
721 | 768 |
722 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); | 769 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); |
| 770 |
| 771 bool get isSafeForElimination => true; |
| 772 bool get isSafeForReordering => true; |
723 } | 773 } |
724 | 774 |
725 class ForeignCode extends Expression { | 775 class ForeignCode extends Expression { |
726 final js.Template codeTemplate; | 776 final js.Template codeTemplate; |
727 final TypeMask type; | 777 final TypeMask type; |
728 final List<Reference<Primitive>> arguments; | 778 final List<Reference<Primitive>> arguments; |
729 final native.NativeBehavior nativeBehavior; | 779 final native.NativeBehavior nativeBehavior; |
730 final FunctionElement dependency; | 780 final FunctionElement dependency; |
731 | 781 |
732 /// The continuation, if the foreign code is not a JavaScript 'throw', | 782 /// The continuation, if the foreign code is not a JavaScript 'throw', |
733 /// otherwise null. | 783 /// otherwise null. |
734 final Reference<Continuation> continuation; | 784 final Reference<Continuation> continuation; |
735 | 785 |
736 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, | 786 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, |
737 this.nativeBehavior, {Continuation continuation, this.dependency}) | 787 this.nativeBehavior, {Continuation continuation, this.dependency}) |
738 : arguments = _referenceList(arguments), | 788 : arguments = _referenceList(arguments), |
739 continuation = continuation == null ? null | 789 continuation = continuation == null ? null |
740 : new Reference<Continuation>(continuation); | 790 : new Reference<Continuation>(continuation); |
741 | 791 |
742 accept(Visitor visitor) => visitor.visitForeignCode(this); | 792 accept(Visitor visitor) => visitor.visitForeignCode(this); |
743 } | 793 } |
744 | 794 |
745 class Constant extends Primitive { | 795 class Constant extends Primitive { |
746 final values.ConstantValue value; | 796 final values.ConstantValue value; |
747 | 797 |
748 Constant(this.value); | 798 Constant(this.value); |
749 | 799 |
750 accept(Visitor visitor) => visitor.visitConstant(this); | 800 accept(Visitor visitor) => visitor.visitConstant(this); |
| 801 |
| 802 bool get isSafeForElimination => true; |
| 803 bool get isSafeForReordering => true; |
751 } | 804 } |
752 | 805 |
753 class LiteralList extends Primitive { | 806 class LiteralList extends Primitive { |
754 /// The List type being created; this is not the type argument. | 807 /// The List type being created; this is not the type argument. |
755 final InterfaceType type; | 808 final InterfaceType type; |
756 final List<Reference<Primitive>> values; | 809 final List<Reference<Primitive>> values; |
757 | 810 |
758 LiteralList(this.type, List<Primitive> values) | 811 LiteralList(this.type, List<Primitive> values) |
759 : this.values = _referenceList(values); | 812 : this.values = _referenceList(values); |
760 | 813 |
761 accept(Visitor visitor) => visitor.visitLiteralList(this); | 814 accept(Visitor visitor) => visitor.visitLiteralList(this); |
| 815 |
| 816 bool get isSafeForElimination => true; |
| 817 bool get isSafeForReordering => true; |
762 } | 818 } |
763 | 819 |
764 class LiteralMapEntry { | 820 class LiteralMapEntry { |
765 final Reference<Primitive> key; | 821 final Reference<Primitive> key; |
766 final Reference<Primitive> value; | 822 final Reference<Primitive> value; |
767 | 823 |
768 LiteralMapEntry(Primitive key, Primitive value) | 824 LiteralMapEntry(Primitive key, Primitive value) |
769 : this.key = new Reference<Primitive>(key), | 825 : this.key = new Reference<Primitive>(key), |
770 this.value = new Reference<Primitive>(value); | 826 this.value = new Reference<Primitive>(value); |
771 } | 827 } |
772 | 828 |
773 class LiteralMap extends Primitive { | 829 class LiteralMap extends Primitive { |
774 final InterfaceType type; | 830 final InterfaceType type; |
775 final List<LiteralMapEntry> entries; | 831 final List<LiteralMapEntry> entries; |
776 | 832 |
777 LiteralMap(this.type, this.entries); | 833 LiteralMap(this.type, this.entries); |
778 | 834 |
779 accept(Visitor visitor) => visitor.visitLiteralMap(this); | 835 accept(Visitor visitor) => visitor.visitLiteralMap(this); |
| 836 |
| 837 bool get isSafeForElimination => true; |
| 838 bool get isSafeForReordering => true; |
780 } | 839 } |
781 | 840 |
782 /// Currently unused. | 841 /// Currently unused. |
783 /// | 842 /// |
784 /// Nested functions (from Dart code) are translated to classes by closure | 843 /// Nested functions (from Dart code) are translated to classes by closure |
785 /// conversion, hence they are instantiated with [CreateInstance]. | 844 /// conversion, hence they are instantiated with [CreateInstance]. |
786 /// | 845 /// |
787 /// We keep this around for now because it might come in handy when we | 846 /// We keep this around for now because it might come in handy when we |
788 /// handle async/await in the CPS IR. | 847 /// handle async/await in the CPS IR. |
789 /// | 848 /// |
790 /// Instantiates a nested function. [MutableVariable]s are in scope in the | 849 /// Instantiates a nested function. [MutableVariable]s are in scope in the |
791 /// inner function, but primitives are not shared across function boundaries. | 850 /// inner function, but primitives are not shared across function boundaries. |
792 class CreateFunction extends Primitive { | 851 class CreateFunction extends Primitive { |
793 final FunctionDefinition definition; | 852 final FunctionDefinition definition; |
794 | 853 |
795 CreateFunction(this.definition); | 854 CreateFunction(this.definition); |
796 | 855 |
797 accept(Visitor visitor) => visitor.visitCreateFunction(this); | 856 accept(Visitor visitor) => visitor.visitCreateFunction(this); |
| 857 |
| 858 bool get isSafeForElimination => true; |
| 859 bool get isSafeForReordering => true; |
798 } | 860 } |
799 | 861 |
800 class Parameter extends Primitive { | 862 class Parameter extends Primitive { |
801 Parameter(Entity hint) { | 863 Parameter(Entity hint) { |
802 super.hint = hint; | 864 super.hint = hint; |
803 } | 865 } |
804 | 866 |
805 // In addition to a parent pointer to the containing Continuation or | 867 // In addition to a parent pointer to the containing Continuation or |
806 // FunctionDefinition, parameters have an index into the list of parameters | 868 // FunctionDefinition, parameters have an index into the list of parameters |
807 // bound by the parent. This gives constant-time access to the continuation | 869 // bound by the parent. This gives constant-time access to the continuation |
808 // from the parent. | 870 // from the parent. |
809 int parentIndex; | 871 int parentIndex; |
810 | 872 |
811 accept(Visitor visitor) => visitor.visitParameter(this); | 873 accept(Visitor visitor) => visitor.visitParameter(this); |
812 | 874 |
813 String toString() => 'Parameter(${hint == null ? null : hint.name})'; | 875 String toString() => 'Parameter(${hint == null ? null : hint.name})'; |
| 876 |
| 877 bool get isSafeForElimination => true; |
| 878 bool get isSafeForReordering => true; |
814 } | 879 } |
815 | 880 |
816 /// Continuations are normally bound by 'let cont'. A continuation with one | 881 /// Continuations are normally bound by 'let cont'. A continuation with one |
817 /// parameter and no body is used to represent a function's return continuation. | 882 /// parameter and no body is used to represent a function's return continuation. |
818 /// The return continuation is bound by the function, not by 'let cont'. | 883 /// The return continuation is bound by the function, not by 'let cont'. |
819 class Continuation extends Definition<Continuation> implements InteriorNode { | 884 class Continuation extends Definition<Continuation> implements InteriorNode { |
820 final List<Parameter> parameters; | 885 final List<Parameter> parameters; |
821 Expression body = null; | 886 Expression body = null; |
822 | 887 |
823 // In addition to a parent pointer to the containing LetCont, continuations | 888 // In addition to a parent pointer to the containing LetCont, continuations |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 /// [Type]. | 935 /// [Type]. |
871 class ReifyRuntimeType extends Primitive { | 936 class ReifyRuntimeType extends Primitive { |
872 /// Reference to the internal representation of a type (as produced, for | 937 /// Reference to the internal representation of a type (as produced, for |
873 /// example, by [ReadTypeVariable]). | 938 /// example, by [ReadTypeVariable]). |
874 final Reference<Primitive> value; | 939 final Reference<Primitive> value; |
875 ReifyRuntimeType(Primitive value) | 940 ReifyRuntimeType(Primitive value) |
876 : this.value = new Reference<Primitive>(value); | 941 : this.value = new Reference<Primitive>(value); |
877 | 942 |
878 @override | 943 @override |
879 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); | 944 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); |
| 945 |
| 946 bool get isSafeForElimination => true; |
| 947 bool get isSafeForReordering => true; |
880 } | 948 } |
881 | 949 |
882 /// Read the value the type variable [variable] from the target object. | 950 /// Read the value the type variable [variable] from the target object. |
883 /// | 951 /// |
884 /// The resulting value is an internal representation (and not neccessarily a | 952 /// The resulting value is an internal representation (and not neccessarily a |
885 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be | 953 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be |
886 /// used as a Dart value. | 954 /// used as a Dart value. |
887 class ReadTypeVariable extends Primitive { | 955 class ReadTypeVariable extends Primitive { |
888 final TypeVariableType variable; | 956 final TypeVariableType variable; |
889 final Reference<Primitive> target; | 957 final Reference<Primitive> target; |
890 | 958 |
891 ReadTypeVariable(this.variable, Primitive target) | 959 ReadTypeVariable(this.variable, Primitive target) |
892 : this.target = new Reference<Primitive>(target); | 960 : this.target = new Reference<Primitive>(target); |
893 | 961 |
894 @override | 962 @override |
895 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); | 963 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); |
| 964 |
| 965 bool get isSafeForElimination => true; |
| 966 bool get isSafeForReordering => true; |
896 } | 967 } |
897 | 968 |
898 /// Representation of a closed type (that is, a type without type variables). | 969 /// Representation of a closed type (that is, a type without type variables). |
899 /// | 970 /// |
900 /// The resulting value is constructed from [dartType] by replacing the type | 971 /// The resulting value is constructed from [dartType] by replacing the type |
901 /// variables with consecutive values from [arguments], in the order generated | 972 /// variables with consecutive values from [arguments], in the order generated |
902 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are | 973 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are |
903 /// treated as 'holes' in the term, which means that it must be ensured at | 974 /// treated as 'holes' in the term, which means that it must be ensured at |
904 /// construction, that duplicate occurences of a type variable in [dartType] | 975 /// construction, that duplicate occurences of a type variable in [dartType] |
905 /// are assigned the same value. | 976 /// are assigned the same value. |
906 class TypeExpression extends Primitive { | 977 class TypeExpression extends Primitive { |
907 final DartType dartType; | 978 final DartType dartType; |
908 final List<Reference<Primitive>> arguments; | 979 final List<Reference<Primitive>> arguments; |
909 | 980 |
910 TypeExpression(this.dartType, | 981 TypeExpression(this.dartType, |
911 [List<Primitive> arguments = const <Primitive>[]]) | 982 [List<Primitive> arguments = const <Primitive>[]]) |
912 : this.arguments = _referenceList(arguments); | 983 : this.arguments = _referenceList(arguments); |
913 | 984 |
914 @override | 985 @override |
915 accept(Visitor visitor) { | 986 accept(Visitor visitor) { |
916 return visitor.visitTypeExpression(this); | 987 return visitor.visitTypeExpression(this); |
917 } | 988 } |
| 989 |
| 990 bool get isSafeForElimination => true; |
| 991 bool get isSafeForReordering => true; |
918 } | 992 } |
919 | 993 |
920 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 994 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
921 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 995 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
922 } | 996 } |
923 | 997 |
924 abstract class Visitor<T> { | 998 abstract class Visitor<T> { |
925 const Visitor(); | 999 const Visitor(); |
926 | 1000 |
927 T visit(Node node); | 1001 T visit(Node node); |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 const RemovalVisitor(); | 1341 const RemovalVisitor(); |
1268 | 1342 |
1269 processReference(Reference reference) { | 1343 processReference(Reference reference) { |
1270 reference.unlink(); | 1344 reference.unlink(); |
1271 } | 1345 } |
1272 | 1346 |
1273 static void remove(Node node) { | 1347 static void remove(Node node) { |
1274 (const RemovalVisitor()).visit(node); | 1348 (const RemovalVisitor()).visit(node); |
1275 } | 1349 } |
1276 } | 1350 } |
OLD | NEW |