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