| 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 |