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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1537663002: dart2js: Initial implementation of inlining. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebaseline test expectations and fix a bug (typo). Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 library dart2js.ir_nodes; 4 library dart2js.ir_nodes;
5 5
6 import 'dart:collection'; 6 import 'dart:collection';
7 import 'cps_fragment.dart' show CpsFragment;
7 import '../constants/values.dart' as values; 8 import '../constants/values.dart' as values;
8 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; 9 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
9 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
10 import '../io/source_information.dart' show SourceInformation; 11 import '../io/source_information.dart' show SourceInformation;
11 import '../types/types.dart' show TypeMask; 12 import '../types/types.dart' show TypeMask;
12 import '../universe/selector.dart' show Selector; 13 import '../universe/selector.dart' show Selector;
13 14
14 import 'builtin_operator.dart'; 15 import 'builtin_operator.dart';
15 export 'builtin_operator.dart'; 16 export 'builtin_operator.dart';
16 17
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive); 197 EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive);
197 } 198 }
198 199
199 /// A named value. 200 /// A named value.
200 /// 201 ///
201 /// The identity of the [Primitive] object is the name of the value. 202 /// The identity of the [Primitive] object is the name of the value.
202 /// The subclass describes how to compute the value. 203 /// The subclass describes how to compute the value.
203 /// 204 ///
204 /// All primitives except [Parameter] must be bound by a [LetPrim]. 205 /// All primitives except [Parameter] must be bound by a [LetPrim].
205 abstract class Primitive extends Variable<Primitive> { 206 abstract class Primitive extends Variable<Primitive> {
206 /// The [VariableElement] or [ParameterElement] from which the primitive 207 Primitive() : super(null);
207 /// binding originated.
208 Entity hint;
209
210 /// Use the given element as a hint for naming this primitive.
211 ///
212 /// Has no effect if this primitive already has a non-null [element].
213 void useElementAsHint(Entity hint) {
214 if (this.hint == null) {
215 this.hint = hint;
216 }
217 }
218 208
219 /// True if this primitive has a value that can be used by other expressions. 209 /// True if this primitive has a value that can be used by other expressions.
220 bool get hasValue; 210 bool get hasValue;
221 211
222 /// True if the primitive can be removed, assuming it has no uses 212 /// True if the primitive can be removed, assuming it has no uses
223 /// (this getter does not check if there are any uses). 213 /// (this getter does not check if there are any uses).
224 /// 214 ///
225 /// False must be returned for primitives that may throw, diverge, or have 215 /// False must be returned for primitives that may throw, diverge, or have
226 /// observable side-effects. 216 /// observable side-effects.
227 bool get isSafeForElimination; 217 bool get isSafeForElimination;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 assert(this is! Parameter); 278 assert(this is! Parameter);
289 assert(newDefinition is! Parameter); 279 assert(newDefinition is! Parameter);
290 assert(newDefinition.parent == null); 280 assert(newDefinition.parent == null);
291 replaceUsesWith(newDefinition); 281 replaceUsesWith(newDefinition);
292 destroy(); 282 destroy();
293 LetPrim let = parent; 283 LetPrim let = parent;
294 let.primitive = newDefinition; 284 let.primitive = newDefinition;
295 newDefinition.parent = let; 285 newDefinition.parent = let;
296 newDefinition.useElementAsHint(hint); 286 newDefinition.useElementAsHint(hint);
297 } 287 }
288
289 /// Replaces this definition with a CPS fragment (a term with a hole in it),
290 /// given the value to replace the uses of the definition with.
291 ///
292 /// This can be thought of as substituting:
293 ///
294 /// let x = OLD in BODY
295 /// ==>
296 /// FRAGMENT[BODY{newPrimitive/x}]
297 void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) {
298 assert(this is! Parameter);
299 replaceUsesWith(newPrimitive);
300 destroy();
301 LetPrim let = parent;
302 fragment.insertBelow(let);
303 let.remove();
304 }
298 } 305 }
299 306
300 /// A primitive that is generally not safe for elimination, but may be marked 307 /// A primitive that is generally not safe for elimination, but may be marked
301 /// as safe by type propagation 308 /// as safe by type propagation
302 // 309 //
303 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this 310 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this
304 // class. 311 // class.
305 abstract class UnsafePrimitive extends Primitive { 312 abstract class UnsafePrimitive extends Primitive {
306 bool isSafeForElimination = false; 313 bool isSafeForElimination = false;
307 bool isSafeForReordering = false; 314 bool isSafeForReordering = false;
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 464
458 accept(Visitor visitor) => visitor.visitLetMutable(this); 465 accept(Visitor visitor) => visitor.visitLetMutable(this);
459 466
460 void setParentPointers() { 467 void setParentPointers() {
461 variable.parent = this; 468 variable.parent = this;
462 value.parent = this; 469 value.parent = this;
463 if (body != null) body.parent = this; 470 if (body != null) body.parent = this;
464 } 471 }
465 } 472 }
466 473
474 enum CallingConvention {
475 /// JS receiver is the Dart receiver, there are no extra arguments.
476 ///
477 /// This includes cases (e.g., static functions, constructors) where there
478 /// is no receiver.
479 ///
480 /// For example: `foo.bar$1(x)`
481 Normal,
482
483 /// JS receiver is an interceptor, the first argument is the Dart receiver.
484 ///
485 /// For example: `getInterceptor(foo).bar$1(foo, x)`
486 Intercepted,
487
488 /// JS receiver is the Dart receiver, the first argument is a dummy value.
489 ///
490 /// For example: `foo.bar$1(0, x)`
491 DummyIntercepted,
492
493 /// JS receiver is the Dart receiver, there are no extra arguments.
494 ///
495 /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
496 OneShotIntercepted,
497 }
498
499 /// Base class of function invocations.
500 ///
501 /// This class defines the common interface of function invocations.
502 abstract class InvocationPrimitive extends UnsafePrimitive {
503 Reference<Primitive> get receiver => null;
504 List<Reference<Primitive>> get arguments;
505 SourceInformation get sourceInformation;
506
507 Reference<Primitive> get dartReceiverReference => null;
508 CallingConvention get callingConvention => CallingConvention.Normal;
509 }
510
467 /// Invoke a static function. 511 /// Invoke a static function.
468 /// 512 ///
469 /// All optional arguments declared by [target] are passed in explicitly, and 513 /// All optional arguments declared by [target] are passed in explicitly, and
470 /// occur at the end of [arguments] list, in normalized order. 514 /// occur at the end of [arguments] list, in normalized order.
471 /// 515 ///
472 /// Discussion: 516 /// Discussion:
473 /// All information in the [selector] is technically redundant; it will likely 517 /// All information in the [selector] is technically redundant; it will likely
474 /// be removed. 518 /// be removed.
475 class InvokeStatic extends UnsafePrimitive { 519 class InvokeStatic extends InvocationPrimitive {
476 final FunctionElement target; 520 final FunctionElement target;
477 final Selector selector; 521 final Selector selector;
478 final List<Reference<Primitive>> arguments; 522 final List<Reference<Primitive>> arguments;
479 final SourceInformation sourceInformation; 523 final SourceInformation sourceInformation;
480 524
481 InvokeStatic(this.target, 525 InvokeStatic(this.target,
482 this.selector, 526 this.selector,
483 List<Primitive> args, 527 List<Primitive> args,
484 [this.sourceInformation]) 528 [this.sourceInformation])
485 : arguments = _referenceList(args); 529 : arguments = _referenceList(args);
486 530
487 InvokeStatic.byReference(this.target, 531 InvokeStatic.byReference(this.target,
488 this.selector, 532 this.selector,
489 this.arguments, 533 this.arguments,
490 [this.sourceInformation]); 534 [this.sourceInformation]);
491 535
492 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 536 accept(Visitor visitor) => visitor.visitInvokeStatic(this);
493 537
494 bool get hasValue => true; 538 bool get hasValue => true;
495 539
496 void setParentPointers() { 540 void setParentPointers() {
497 _setParentsOnList(arguments, this); 541 _setParentsOnList(arguments, this);
498 } 542 }
499 } 543 }
500 544
501 enum CallingConvention {
502 /// JS receiver is the Dart receiver, there are no extra arguments.
503 ///
504 /// For example: `foo.bar$1(x)`
505 Normal,
506
507 /// JS receiver is an interceptor, the first argument is the Dart receiver.
508 ///
509 /// For example: `getInterceptor(foo).bar$1(foo, x)`
510 Intercepted,
511
512 /// JS receiver is the Dart receiver, the first argument is a dummy value.
513 ///
514 /// For example: `foo.bar$1(0, x)`
515 DummyIntercepted,
516
517 /// JS receiver is the Dart receiver, there are no extra arguments.
518 ///
519 /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
520 OneShotIntercepted,
521 }
522
523 /// Invoke a method on an object. 545 /// Invoke a method on an object.
524 /// 546 ///
525 /// This includes getters, setters, operators, and index getter/setters. 547 /// This includes getters, setters, operators, and index getter/setters.
526 /// 548 ///
527 /// Tearing off a method is treated like a getter invocation (getters and 549 /// Tearing off a method is treated like a getter invocation (getters and
528 /// tear-offs cannot be distinguished at compile-time). 550 /// tear-offs cannot be distinguished at compile-time).
529 /// 551 ///
530 /// The [selector] records the names of named arguments. The value of named 552 /// The [selector] records the names of named arguments. The value of named
531 /// arguments occur at the end of the [arguments] list, in normalized order. 553 /// arguments occur at the end of the [arguments] list, in normalized order.
532 class InvokeMethod extends UnsafePrimitive { 554 class InvokeMethod extends InvocationPrimitive {
533 Reference<Primitive> receiver; 555 Reference<Primitive> receiver;
534 Selector selector; 556 Selector selector;
535 TypeMask mask; 557 TypeMask mask;
536 final List<Reference<Primitive>> arguments; 558 final List<Reference<Primitive>> arguments;
537 final SourceInformation sourceInformation; 559 final SourceInformation sourceInformation;
538 560
539 CallingConvention callingConvention = CallingConvention.Normal; 561 CallingConvention callingConvention = CallingConvention.Normal;
540 562
541 Reference<Primitive> get dartReceiverReference { 563 Reference<Primitive> get dartReceiverReference {
542 return callingConvention == CallingConvention.Intercepted 564 return callingConvention == CallingConvention.Intercepted
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 /// If it is known that [target] does not use its receiver argument, then 621 /// If it is known that [target] does not use its receiver argument, then
600 /// [receiver] may refer to a null constant primitive. This happens for direct 622 /// [receiver] may refer to a null constant primitive. This happens for direct
601 /// invocations to intercepted methods, where the effective receiver is instead 623 /// invocations to intercepted methods, where the effective receiver is instead
602 /// passed as a formal parameter. 624 /// passed as a formal parameter.
603 /// 625 ///
604 /// TODO(sra): Review. A direct call to a method that is mixed into a native 626 /// TODO(sra): Review. A direct call to a method that is mixed into a native
605 /// class will still require an explicit argument. 627 /// class will still require an explicit argument.
606 /// 628 ///
607 /// All optional arguments declared by [target] are passed in explicitly, and 629 /// All optional arguments declared by [target] are passed in explicitly, and
608 /// occur at the end of [arguments] list, in normalized order. 630 /// occur at the end of [arguments] list, in normalized order.
609 class InvokeMethodDirectly extends UnsafePrimitive { 631 class InvokeMethodDirectly extends InvocationPrimitive {
610 Reference<Primitive> receiver; 632 Reference<Primitive> receiver;
611 final FunctionElement target; 633 final FunctionElement target;
612 final Selector selector; 634 final Selector selector;
613 final List<Reference<Primitive>> arguments; 635 final List<Reference<Primitive>> arguments;
614 final SourceInformation sourceInformation; 636 final SourceInformation sourceInformation;
615 637
616 CallingConvention callingConvention = CallingConvention.Normal; 638 CallingConvention callingConvention = CallingConvention.Normal;
617 639
618 Reference<Primitive> get dartReceiverReference { 640 Reference<Primitive> get dartReceiverReference {
619 return callingConvention == CallingConvention.Intercepted 641 return callingConvention == CallingConvention.Intercepted
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 /// All optional arguments declared by [target] are passed in explicitly, and 679 /// All optional arguments declared by [target] are passed in explicitly, and
658 /// occur in the [arguments] list, in normalized order. 680 /// occur in the [arguments] list, in normalized order.
659 /// 681 ///
660 /// Last in the [arguments] list, after the mandatory and optional arguments, 682 /// Last in the [arguments] list, after the mandatory and optional arguments,
661 /// the internal representation of each type argument occurs, unless it could 683 /// the internal representation of each type argument occurs, unless it could
662 /// be determined at build-time that the constructed class has no need for its 684 /// be determined at build-time that the constructed class has no need for its
663 /// runtime type information. 685 /// runtime type information.
664 /// 686 ///
665 /// Note that [InvokeConstructor] does it itself allocate an object. 687 /// Note that [InvokeConstructor] does it itself allocate an object.
666 /// The invoked constructor will do that using [CreateInstance]. 688 /// The invoked constructor will do that using [CreateInstance].
667 class InvokeConstructor extends UnsafePrimitive { 689 class InvokeConstructor extends InvocationPrimitive {
668 final DartType dartType; 690 final DartType dartType;
669 final ConstructorElement target; 691 final ConstructorElement target;
670 final List<Reference<Primitive>> arguments; 692 final List<Reference<Primitive>> arguments;
671 final Selector selector; 693 final Selector selector;
672 final SourceInformation sourceInformation; 694 final SourceInformation sourceInformation;
673 695
674 /// If non-null, this is an allocation site-specific type that is potentially 696 /// If non-null, this is an allocation site-specific type that is potentially
675 /// better than the inferred return type of [target]. 697 /// better than the inferred return type of [target].
676 /// 698 ///
677 /// In particular, container type masks depend on the allocation site and 699 /// In particular, container type masks depend on the allocation site and
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 if (body != null) body.parent = this; 1703 if (body != null) body.parent = this;
1682 } 1704 }
1683 } 1705 }
1684 1706
1685 /// Common interface for [Primitive] and [MutableVariable]. 1707 /// Common interface for [Primitive] and [MutableVariable].
1686 abstract class Variable<T extends Variable<T>> extends Definition<T> { 1708 abstract class Variable<T extends Variable<T>> extends Definition<T> {
1687 /// Type of value held in the variable. 1709 /// Type of value held in the variable.
1688 /// 1710 ///
1689 /// Is `null` until initialized by type propagation. 1711 /// Is `null` until initialized by type propagation.
1690 TypeMask type; 1712 TypeMask type;
1713
1714 /// The [VariableElement] or [ParameterElement] from which the variable
1715 /// binding originated.
1716 Entity hint;
1717
1718 Variable(this.hint);
1719
1720 /// Use the given element as a hint for naming this primitive.
1721 ///
1722 /// Has no effect if this primitive already has a non-null [element].
1723 void useElementAsHint(Entity hint) {
1724 this.hint ??= hint;
1725 }
1691 } 1726 }
1692 1727
1693 /// Identifies a mutable variable. 1728 /// Identifies a mutable variable.
1694 class MutableVariable extends Variable<MutableVariable> { 1729 class MutableVariable extends Variable<MutableVariable> {
1695 Entity hint; 1730 MutableVariable(Entity hint) : super(hint);
1696
1697 MutableVariable(this.hint);
1698 1731
1699 accept(Visitor v) => v.visitMutableVariable(this); 1732 accept(Visitor v) => v.visitMutableVariable(this);
1700 1733
1701 void setParentPointers() {} 1734 void setParentPointers() {}
1702 } 1735 }
1703 1736
1704 /// A function definition, consisting of parameters and a body. 1737 /// A function definition, consisting of parameters and a body.
1705 /// 1738 ///
1706 /// There is an explicit parameter for the `this` argument, and a return 1739 /// There is an explicit parameter for the `this` argument, and a return
1707 /// continuation to invoke when returning from the function. 1740 /// continuation to invoke when returning from the function.
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 1900
1868 // Concrete classes. 1901 // Concrete classes.
1869 T visitFunctionDefinition(FunctionDefinition node); 1902 T visitFunctionDefinition(FunctionDefinition node);
1870 1903
1871 // Expressions. 1904 // Expressions.
1872 T visitLetPrim(LetPrim node); 1905 T visitLetPrim(LetPrim node);
1873 T visitLetCont(LetCont node); 1906 T visitLetCont(LetCont node);
1874 T visitLetHandler(LetHandler node); 1907 T visitLetHandler(LetHandler node);
1875 T visitLetMutable(LetMutable node); 1908 T visitLetMutable(LetMutable node);
1876 T visitInvokeContinuation(InvokeContinuation node); 1909 T visitInvokeContinuation(InvokeContinuation node);
1910 T visitThrow(Throw node);
1911 T visitRethrow(Rethrow node);
1912 T visitBranch(Branch node);
1913 T visitUnreachable(Unreachable node);
1914
1915 // Definitions.
1877 T visitInvokeStatic(InvokeStatic node); 1916 T visitInvokeStatic(InvokeStatic node);
1878 T visitInvokeMethod(InvokeMethod node); 1917 T visitInvokeMethod(InvokeMethod node);
1879 T visitInvokeMethodDirectly(InvokeMethodDirectly node); 1918 T visitInvokeMethodDirectly(InvokeMethodDirectly node);
1880 T visitInvokeConstructor(InvokeConstructor node); 1919 T visitInvokeConstructor(InvokeConstructor node);
1881 T visitThrow(Throw node);
1882 T visitRethrow(Rethrow node);
1883 T visitBranch(Branch node);
1884 T visitTypeCast(TypeCast node); 1920 T visitTypeCast(TypeCast node);
1885 T visitSetMutable(SetMutable node); 1921 T visitSetMutable(SetMutable node);
1886 T visitSetStatic(SetStatic node); 1922 T visitSetStatic(SetStatic node);
1923 T visitSetField(SetField node);
1887 T visitGetLazyStatic(GetLazyStatic node); 1924 T visitGetLazyStatic(GetLazyStatic node);
1888 T visitSetField(SetField node);
1889 T visitUnreachable(Unreachable node);
1890 T visitAwait(Await node); 1925 T visitAwait(Await node);
1891 T visitYield(Yield node); 1926 T visitYield(Yield node);
1892
1893 // Definitions.
1894 T visitLiteralList(LiteralList node); 1927 T visitLiteralList(LiteralList node);
1895 T visitLiteralMap(LiteralMap node); 1928 T visitLiteralMap(LiteralMap node);
1896 T visitConstant(Constant node); 1929 T visitConstant(Constant node);
1897 T visitGetMutable(GetMutable node); 1930 T visitGetMutable(GetMutable node);
1898 T visitParameter(Parameter node); 1931 T visitParameter(Parameter node);
1899 T visitContinuation(Continuation node); 1932 T visitContinuation(Continuation node);
1900 T visitMutableVariable(MutableVariable node); 1933 T visitMutableVariable(MutableVariable node);
1901 T visitGetStatic(GetStatic node); 1934 T visitGetStatic(GetStatic node);
1902 T visitInterceptor(Interceptor node); 1935 T visitInterceptor(Interceptor node);
1903 T visitCreateInstance(CreateInstance node); 1936 T visitCreateInstance(CreateInstance node);
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2385 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 2418 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
2386 class RemovalVisitor extends TrampolineRecursiveVisitor { 2419 class RemovalVisitor extends TrampolineRecursiveVisitor {
2387 processReference(Reference reference) { 2420 processReference(Reference reference) {
2388 reference.unlink(); 2421 reference.unlink();
2389 } 2422 }
2390 2423
2391 static void remove(Node node) { 2424 static void remove(Node node) {
2392 (new RemovalVisitor()).visit(node); 2425 (new RemovalVisitor()).visit(node);
2393 } 2426 }
2394 } 2427 }
2428
2429 /// A visitor to copy instances of [Definition] or its subclasses, except for
2430 /// instances of [Continuation].
2431 ///
2432 /// The visitor maintains a map from original definitions to their copies.
2433 /// When the [copy] method is called for a non-Continuation definition,
2434 /// a copy is created, added to the map and returned as the result. Copying a
2435 /// definition assumes that the definitions of all references have already
2436 /// been copied by the same visitor.
2437 class DefinitionCopyingVisitor extends Visitor<Definition> {
2438 Map<Definition, Definition> _copies = <Definition, Definition>{};
2439
2440 /// Put a copy into the map.
2441 ///
2442 /// This method should be used instead of directly adding copies to the map.
2443 Definition putCopy(Definition original, Definition copy) {
2444 if (copy is Variable) {
2445 Variable originalVariable = original;
2446 copy.type = originalVariable.type;
2447 copy.hint = originalVariable.hint;
2448 }
2449 return _copies[original] = copy;
2450 }
2451
2452 /// Get the copy of a [Reference]'s definition from the map.
2453 Definition getCopy(Reference reference) => _copies[reference.definition];
2454
2455 /// Map a list of [Reference]s to the list of their definition's copies.
2456 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList();
2457
2458 /// Copy a non-[Continuation] [Definition].
2459 Definition copy(Definition node) {
2460 assert (node is! Continuation);
2461 return putCopy(node, visit(node));
2462 }
2463
2464 Definition visit(Node node) => node.accept(this);
2465
2466 Definition visitFunctionDefinition(FunctionDefinition node) {}
2467 Definition visitLetPrim(LetPrim node) {}
2468 Definition visitLetCont(LetCont node) {}
2469 Definition visitLetHandler(LetHandler node) {}
2470 Definition visitLetMutable(LetMutable node) {}
2471 Definition visitInvokeContinuation(InvokeContinuation node) {}
2472 Definition visitThrow(Throw node) {}
2473 Definition visitRethrow(Rethrow node) {}
2474 Definition visitBranch(Branch node) {}
2475 Definition visitUnreachable(Unreachable node) {}
2476 Definition visitContinuation(Continuation node) {}
2477
2478 Definition visitInvokeStatic(InvokeStatic node) {
2479 return new InvokeStatic(node.target, node.selector, getList(node.arguments),
2480 node.sourceInformation);
2481 }
2482
2483 Definition visitInvokeMethod(InvokeMethod node) {
2484 return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask,
2485 getList(node.arguments),
2486 node.sourceInformation);
2487 }
2488
2489 Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) {
2490 return new InvokeMethodDirectly(getCopy(node.receiver), node.target,
2491 node.selector,
2492 getList(node.arguments),
2493 node.sourceInformation);
2494 }
2495
2496 Definition visitInvokeConstructor(InvokeConstructor node) {
2497 return new InvokeConstructor(node.dartType, node.target, node.selector,
2498 getList(node.arguments),
2499 node.sourceInformation);
2500 }
2501
2502 Definition visitTypeCast(TypeCast node) {
2503 return new TypeCast(getCopy(node.value), node.dartType,
2504 getList(node.typeArguments));
2505 }
2506
2507 Definition visitSetMutable(SetMutable node) {
2508 return new SetMutable(getCopy(node.variable), getCopy(node.value));
2509 }
2510
2511 Definition visitSetStatic(SetStatic node) {
2512 return new SetStatic(node.element, getCopy(node.value),
2513 node.sourceInformation);
2514 }
2515
2516 Definition visitSetField(SetField node) {
2517 return new SetField(getCopy(node.object), node.field, getCopy(node.value));
2518 }
2519
2520 Definition visitGetLazyStatic(GetLazyStatic node) {
2521 return new GetLazyStatic(node.element, node.sourceInformation);
2522 }
2523
2524 Definition visitAwait(Await node) {
2525 return new Await(getCopy(node.input));
2526 }
2527
2528 Definition visitYield(Yield node) {
2529 return new Yield(getCopy(node.input), node.hasStar);
2530 }
2531
2532 Definition visitLiteralList(LiteralList node) {
2533 return new LiteralList(node.dartType, getList(node.values));
2534 }
2535
2536 Definition visitLiteralMap(LiteralMap node) {
2537 List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) {
2538 return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value));
2539 }).toList();
2540 return new LiteralMap(node.dartType, entries);
2541 }
2542
2543 Definition visitConstant(Constant node) {
2544 return new Constant(node.value, sourceInformation: node.sourceInformation);
2545 }
2546
2547 Definition visitGetMutable(GetMutable node) {
2548 return new GetMutable(getCopy(node.variable));
2549 }
2550
2551 Definition visitParameter(Parameter node) {
2552 return new Parameter(node.hint);
2553 }
2554
2555 Definition visitMutableVariable(MutableVariable node) {
2556 return new MutableVariable(node.hint);
2557 }
2558
2559 Definition visitGetStatic(GetStatic node) {
2560 return new GetStatic(node.element, node.sourceInformation);
2561 }
2562
2563 Definition visitInterceptor(Interceptor node) {
2564 return new Interceptor(getCopy(node.input), node.sourceInformation)
2565 ..interceptedClasses.addAll(node.interceptedClasses);
2566 }
2567
2568 Definition visitCreateInstance(CreateInstance node) {
2569 return new CreateInstance(node.classElement, getList(node.arguments),
2570 getList(node.typeInformation),
2571 node.sourceInformation);
2572 }
2573
2574 Definition visitGetField(GetField node) {
2575 return new GetField(getCopy(node.object), node.field);
2576 }
2577
2578 Definition visitCreateBox(CreateBox node) {
2579 return new CreateBox();
2580 }
2581
2582 Definition visitReifyRuntimeType(ReifyRuntimeType node) {
2583 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation);
2584 }
2585
2586 Definition visitReadTypeVariable(ReadTypeVariable node) {
2587 return new ReadTypeVariable(node.variable, getCopy(node.target),
2588 node.sourceInformation);
2589 }
2590
2591 Definition visitTypeExpression(TypeExpression node) {
2592 return new TypeExpression(node.dartType, getList(node.arguments));
2593 }
2594
2595 Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
2596 return new CreateInvocationMirror(node.selector, getList(node.arguments));
2597 }
2598
2599 Definition visitTypeTest(TypeTest node) {
2600 return new TypeTest(getCopy(node.value), node.dartType,
2601 getList(node.typeArguments));
2602 }
2603
2604 Definition visitTypeTestViaFlag(TypeTestViaFlag node) {
2605 return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType);
2606 }
2607
2608 Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
2609 return new ApplyBuiltinOperator(node.operator, getList(node.arguments),
2610 node.sourceInformation);
2611 }
2612
2613 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
2614 return new ApplyBuiltinMethod(node.method, getCopy(node.receiver),
2615 getList(node.arguments),
2616 node.sourceInformation,
2617 receiverIsNotNull: node.receiverIsNotNull);
2618 }
2619
2620 Definition visitGetLength(GetLength node) {
2621 return new GetLength(getCopy(node.object));
2622 }
2623
2624 Definition visitGetIndex(GetIndex node) {
2625 return new GetIndex(getCopy(node.object), getCopy(node.index));
2626 }
2627
2628 Definition visitSetIndex(SetIndex node) {
2629 return new SetIndex(getCopy(node.object), getCopy(node.index),
2630 getCopy(node.value));
2631 }
2632
2633 Definition visitRefinement(Refinement node) {
2634 return new Refinement(getCopy(node.value), node.refineType);
2635 }
2636
2637 Definition visitBoundsCheck(BoundsCheck node) {
2638 if (node.hasNoChecks) {
2639 return new BoundsCheck.noCheck(getCopy(node.object),
2640 node.sourceInformation);
2641 } else {
2642 return new BoundsCheck(getCopy(node.object), getCopy(node.index),
2643 getCopy(node.length),
2644 node.checks,
2645 node.sourceInformation);
2646 }
2647 }
2648
2649 Definition visitNullCheck(NullCheck node) {
2650 return new NullCheck(getCopy(node.value), node.sourceInformation);
2651 }
2652
2653 Definition visitForeignCode(ForeignCode node) {
2654 return new ForeignCode(node.codeTemplate, node.type,
2655 getList(node.arguments),
2656 node.nativeBehavior,
2657 dependency: node.dependency);
2658 }
2659 }
2660
2661 /// A trampolining visitor to copy [FunctionDefinition]s.
2662 class CopyingVisitor extends TrampolineRecursiveVisitor {
2663 // The visitor maintains a map from original continuations to their copies.
2664 Map<Continuation, Continuation> _copies = <Continuation, Continuation>{};
2665
2666 // The visitor uses an auxiliary visitor to copy definitions.
2667 DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor();
2668
2669 // While copying a block, the state of the visitor is a 'linked list' of
2670 // the expressions in the block's body, with a pointer to the last element
2671 // of the list.
2672 Expression _first = null;
2673 Expression _current = null;
2674
2675 void plug(Expression body) {
2676 if (_first == null) {
2677 _first = body;
2678 } else {
2679 assert(_current != null);
2680 InteriorExpression interior = _current;
2681 interior.body = body;
2682 }
2683 _current = body;
2684 }
2685
2686 // Continuations are added to the visitor's stack to be visited after copying
2687 // the current block is finished. The stack action saves the current block,
2688 // copies the continuation's body, sets the body on the copy of the
2689 // continuation, and restores the current block.
2690 //
2691 // Note that continuations are added to the copy map before the stack action
2692 // to visit them is performed.
2693 void push(Continuation cont) {
2694 assert(!cont.isReturnContinuation);
2695 _stack.add(() {
2696 Expression savedFirst = _first;
2697 _first = _current = null;
2698 _processBlock(cont.body);
2699 _copies[cont].body = _first;
2700 _first = savedFirst;
2701 _current = null;
2702 });
2703 }
2704
2705 FunctionDefinition copy(FunctionDefinition node) {
2706 assert(_first == null && _current == null);
2707 _first = _current = null;
2708 // Definitions are copied where they are bound, before processing
2709 // expressions in the scope of their binding.
2710 Parameter thisParameter = node.thisParameter == null
2711 ? null
2712 : _definitions.copy(node.thisParameter);
2713 List<Parameter> parameters =
2714 node.parameters.map(_definitions.copy).toList();
2715 // Though the return continuation's parameter does not have any uses,
2716 // we still make a proper copy to ensure that hints, type, etc. are
2717 // copied.
2718 Parameter returnParameter =
2719 _definitions.copy(node.returnContinuation.parameters.first);
2720 Continuation returnContinuation = _copies[node.returnContinuation] =
2721 new Continuation([returnParameter]);
2722
2723 visit(node.body);
2724 FunctionDefinition copy = new FunctionDefinition(node.element,
2725 thisParameter,
2726 parameters,
2727 returnContinuation,
2728 _first);
2729 _first = _current = null;
2730 return copy;
2731 }
2732
2733 Node visit(Node node) => node.accept(this);
2734
2735 Expression traverseLetCont(LetCont node) {
2736 // Continuations are copied where they are bound, before processing
2737 // expressions in the scope of their binding.
2738 List<Continuation> continuations = node.continuations.map((Continuation c) {
2739 push(c);
2740 return _copies[c] =
2741 new Continuation(c.parameters.map(_definitions.copy).toList());
2742 }).toList();
2743 plug(new LetCont.many(continuations, null));
2744 return node.body;
2745 }
2746
2747 Expression traverseLetHandler(LetHandler node) {
2748 // Continuations are copied where they are bound, before processing
2749 // expressions in the scope of their binding.
2750 push(node.handler);
2751 Continuation handler = _copies[node.handler] =
2752 new Continuation(node.handler.parameters.map(_definitions.copy)
2753 .toList());
2754 plug(new LetHandler(handler, null));
2755 return node.body;
2756 }
2757
2758 Expression traverseLetPrim(LetPrim node) {
2759 plug(new LetPrim(_definitions.copy(node.primitive)));
2760 return node.body;
2761 }
2762
2763 Expression traverseLetMutable(LetMutable node) {
2764 plug(new LetMutable(_definitions.copy(node.variable),
2765 _definitions.getCopy(node.value)));
2766 return node.body;
2767 }
2768
2769 // Tail expressions do not have references, so we do not need to map them
2770 // to their copies.
2771 visitInvokeContinuation(InvokeContinuation node) {
2772 plug(new InvokeContinuation(_copies[node.continuation.definition],
2773 _definitions.getList(node.arguments),
2774 isRecursive: node.isRecursive,
2775 isEscapingTry: node.isEscapingTry,
2776 sourceInformation: node.sourceInformation));
2777 }
2778
2779 Node visitThrow(Throw node) {
2780 plug(new Throw(_definitions.getCopy(node.value)));
2781 }
2782
2783 Node visitRethrow(Rethrow node) {
2784 plug(new Rethrow());
2785 }
2786
2787 Node visitBranch(Branch node) {
2788 plug(new Branch.loose(_definitions.getCopy(node.condition),
2789 _copies[node.trueContinuation.definition],
2790 _copies[node.falseContinuation.definition])
2791 ..isStrictCheck = node.isStrictCheck);
2792 }
2793
2794 Node visitUnreachable(Unreachable node) {
2795 plug(new Unreachable());
2796 }
2797 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_fragment.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698