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

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: 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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 assert(this is! Parameter); 289 assert(this is! Parameter);
289 assert(newDefinition is! Parameter); 290 assert(newDefinition is! Parameter);
290 assert(newDefinition.parent == null); 291 assert(newDefinition.parent == null);
291 replaceUsesWith(newDefinition); 292 replaceUsesWith(newDefinition);
292 destroy(); 293 destroy();
293 LetPrim let = parent; 294 LetPrim let = parent;
294 let.primitive = newDefinition; 295 let.primitive = newDefinition;
295 newDefinition.parent = let; 296 newDefinition.parent = let;
296 newDefinition.useElementAsHint(hint); 297 newDefinition.useElementAsHint(hint);
297 } 298 }
299
300 /// Replaces this definition with a CPS fragment (a term with a hole in it),
301 /// given the value to replace the uses of the definition with.
302 ///
303 /// This can be thought of as substituting:
304 ///
305 /// let x = OLD in BODY
306 /// ==>
307 /// FRAGMENT[BODY{newPrimitive/x}]
308 void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) {
309 assert(this is! Parameter);
310 replaceUsesWith(newPrimitive);
311 destroy();
312 LetPrim let = parent;
313 fragment.insertBelow(let);
314 let.remove();
315 }
298 } 316 }
299 317
300 /// A primitive that is generally not safe for elimination, but may be marked 318 /// A primitive that is generally not safe for elimination, but may be marked
301 /// as safe by type propagation 319 /// as safe by type propagation
302 // 320 //
303 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this 321 // TODO(asgerf): Store the flag in a bitmask in [Primitive] and get rid of this
304 // class. 322 // class.
305 abstract class UnsafePrimitive extends Primitive { 323 abstract class UnsafePrimitive extends Primitive {
306 bool isSafeForElimination = false; 324 bool isSafeForElimination = false;
307 bool isSafeForReordering = false; 325 bool isSafeForReordering = false;
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 475
458 accept(Visitor visitor) => visitor.visitLetMutable(this); 476 accept(Visitor visitor) => visitor.visitLetMutable(this);
459 477
460 void setParentPointers() { 478 void setParentPointers() {
461 variable.parent = this; 479 variable.parent = this;
462 value.parent = this; 480 value.parent = this;
463 if (body != null) body.parent = this; 481 if (body != null) body.parent = this;
464 } 482 }
465 } 483 }
466 484
485 /// Base class of function invocations.
486 ///
487 /// This class defines the common interface of function invocations.
488 abstract class InvocationPrimitive extends UnsafePrimitive {
489 Reference<Primitive> get receiver => null;
490 List<Reference<Primitive>> get arguments;
491 SourceInformation get sourceInformation;
492 }
493
467 /// Invoke a static function. 494 /// Invoke a static function.
468 /// 495 ///
469 /// All optional arguments declared by [target] are passed in explicitly, and 496 /// All optional arguments declared by [target] are passed in explicitly, and
470 /// occur at the end of [arguments] list, in normalized order. 497 /// occur at the end of [arguments] list, in normalized order.
471 /// 498 ///
472 /// Discussion: 499 /// Discussion:
473 /// All information in the [selector] is technically redundant; it will likely 500 /// All information in the [selector] is technically redundant; it will likely
474 /// be removed. 501 /// be removed.
475 class InvokeStatic extends UnsafePrimitive { 502 class InvokeStatic extends InvocationPrimitive {
476 final FunctionElement target; 503 final FunctionElement target;
477 final Selector selector; 504 final Selector selector;
478 final List<Reference<Primitive>> arguments; 505 final List<Reference<Primitive>> arguments;
479 final SourceInformation sourceInformation; 506 final SourceInformation sourceInformation;
480 507
481 InvokeStatic(this.target, 508 InvokeStatic(this.target,
482 this.selector, 509 this.selector,
483 List<Primitive> args, 510 List<Primitive> args,
484 [this.sourceInformation]) 511 [this.sourceInformation])
485 : arguments = _referenceList(args); 512 : arguments = _referenceList(args);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 549
523 /// Invoke a method on an object. 550 /// Invoke a method on an object.
524 /// 551 ///
525 /// This includes getters, setters, operators, and index getter/setters. 552 /// This includes getters, setters, operators, and index getter/setters.
526 /// 553 ///
527 /// Tearing off a method is treated like a getter invocation (getters and 554 /// Tearing off a method is treated like a getter invocation (getters and
528 /// tear-offs cannot be distinguished at compile-time). 555 /// tear-offs cannot be distinguished at compile-time).
529 /// 556 ///
530 /// The [selector] records the names of named arguments. The value of named 557 /// 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. 558 /// arguments occur at the end of the [arguments] list, in normalized order.
532 class InvokeMethod extends UnsafePrimitive { 559 class InvokeMethod extends InvocationPrimitive {
533 Reference<Primitive> receiver; 560 Reference<Primitive> receiver;
534 Selector selector; 561 Selector selector;
535 TypeMask mask; 562 TypeMask mask;
536 final List<Reference<Primitive>> arguments; 563 final List<Reference<Primitive>> arguments;
537 final SourceInformation sourceInformation; 564 final SourceInformation sourceInformation;
538 565
539 CallingConvention callingConvention = CallingConvention.Normal; 566 CallingConvention callingConvention = CallingConvention.Normal;
540 567
541 Reference<Primitive> get dartReceiverReference { 568 Reference<Primitive> get dartReceiverReference {
542 return callingConvention == CallingConvention.Intercepted 569 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 626 /// 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 627 /// [receiver] may refer to a null constant primitive. This happens for direct
601 /// invocations to intercepted methods, where the effective receiver is instead 628 /// invocations to intercepted methods, where the effective receiver is instead
602 /// passed as a formal parameter. 629 /// passed as a formal parameter.
603 /// 630 ///
604 /// TODO(sra): Review. A direct call to a method that is mixed into a native 631 /// TODO(sra): Review. A direct call to a method that is mixed into a native
605 /// class will still require an explicit argument. 632 /// class will still require an explicit argument.
606 /// 633 ///
607 /// All optional arguments declared by [target] are passed in explicitly, and 634 /// All optional arguments declared by [target] are passed in explicitly, and
608 /// occur at the end of [arguments] list, in normalized order. 635 /// occur at the end of [arguments] list, in normalized order.
609 class InvokeMethodDirectly extends UnsafePrimitive { 636 class InvokeMethodDirectly extends InvocationPrimitive {
610 Reference<Primitive> receiver; 637 Reference<Primitive> receiver;
611 final FunctionElement target; 638 final FunctionElement target;
612 final Selector selector; 639 final Selector selector;
613 final List<Reference<Primitive>> arguments; 640 final List<Reference<Primitive>> arguments;
614 final SourceInformation sourceInformation; 641 final SourceInformation sourceInformation;
615 642
616 CallingConvention callingConvention = CallingConvention.Normal; 643 CallingConvention callingConvention = CallingConvention.Normal;
617 644
618 Reference<Primitive> get dartReceiverReference { 645 Reference<Primitive> get dartReceiverReference {
619 return callingConvention == CallingConvention.Intercepted 646 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 684 /// All optional arguments declared by [target] are passed in explicitly, and
658 /// occur in the [arguments] list, in normalized order. 685 /// occur in the [arguments] list, in normalized order.
659 /// 686 ///
660 /// Last in the [arguments] list, after the mandatory and optional arguments, 687 /// Last in the [arguments] list, after the mandatory and optional arguments,
661 /// the internal representation of each type argument occurs, unless it could 688 /// 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 689 /// be determined at build-time that the constructed class has no need for its
663 /// runtime type information. 690 /// runtime type information.
664 /// 691 ///
665 /// Note that [InvokeConstructor] does it itself allocate an object. 692 /// Note that [InvokeConstructor] does it itself allocate an object.
666 /// The invoked constructor will do that using [CreateInstance]. 693 /// The invoked constructor will do that using [CreateInstance].
667 class InvokeConstructor extends UnsafePrimitive { 694 class InvokeConstructor extends InvocationPrimitive {
668 final DartType dartType; 695 final DartType dartType;
669 final ConstructorElement target; 696 final ConstructorElement target;
670 final List<Reference<Primitive>> arguments; 697 final List<Reference<Primitive>> arguments;
671 final Selector selector; 698 final Selector selector;
672 final SourceInformation sourceInformation; 699 final SourceInformation sourceInformation;
673 700
674 /// If non-null, this is an allocation site-specific type that is potentially 701 /// If non-null, this is an allocation site-specific type that is potentially
675 /// better than the inferred return type of [target]. 702 /// better than the inferred return type of [target].
676 /// 703 ///
677 /// In particular, container type masks depend on the allocation site and 704 /// In particular, container type masks depend on the allocation site and
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 1894
1868 // Concrete classes. 1895 // Concrete classes.
1869 T visitFunctionDefinition(FunctionDefinition node); 1896 T visitFunctionDefinition(FunctionDefinition node);
1870 1897
1871 // Expressions. 1898 // Expressions.
1872 T visitLetPrim(LetPrim node); 1899 T visitLetPrim(LetPrim node);
1873 T visitLetCont(LetCont node); 1900 T visitLetCont(LetCont node);
1874 T visitLetHandler(LetHandler node); 1901 T visitLetHandler(LetHandler node);
1875 T visitLetMutable(LetMutable node); 1902 T visitLetMutable(LetMutable node);
1876 T visitInvokeContinuation(InvokeContinuation node); 1903 T visitInvokeContinuation(InvokeContinuation node);
1904 T visitThrow(Throw node);
1905 T visitRethrow(Rethrow node);
1906 T visitBranch(Branch node);
1907 T visitUnreachable(Unreachable node);
1908
1909 // Definitions.
1877 T visitInvokeStatic(InvokeStatic node); 1910 T visitInvokeStatic(InvokeStatic node);
1878 T visitInvokeMethod(InvokeMethod node); 1911 T visitInvokeMethod(InvokeMethod node);
1879 T visitInvokeMethodDirectly(InvokeMethodDirectly node); 1912 T visitInvokeMethodDirectly(InvokeMethodDirectly node);
1880 T visitInvokeConstructor(InvokeConstructor node); 1913 T visitInvokeConstructor(InvokeConstructor node);
1881 T visitThrow(Throw node);
1882 T visitRethrow(Rethrow node);
1883 T visitBranch(Branch node);
1884 T visitTypeCast(TypeCast node); 1914 T visitTypeCast(TypeCast node);
1885 T visitSetMutable(SetMutable node); 1915 T visitSetMutable(SetMutable node);
1886 T visitSetStatic(SetStatic node); 1916 T visitSetStatic(SetStatic node);
1917 T visitSetField(SetField node);
1887 T visitGetLazyStatic(GetLazyStatic node); 1918 T visitGetLazyStatic(GetLazyStatic node);
1888 T visitSetField(SetField node);
1889 T visitUnreachable(Unreachable node);
1890 T visitAwait(Await node); 1919 T visitAwait(Await node);
1891 T visitYield(Yield node); 1920 T visitYield(Yield node);
1892
1893 // Definitions.
1894 T visitLiteralList(LiteralList node); 1921 T visitLiteralList(LiteralList node);
1895 T visitLiteralMap(LiteralMap node); 1922 T visitLiteralMap(LiteralMap node);
1896 T visitConstant(Constant node); 1923 T visitConstant(Constant node);
1897 T visitGetMutable(GetMutable node); 1924 T visitGetMutable(GetMutable node);
1898 T visitParameter(Parameter node); 1925 T visitParameter(Parameter node);
1899 T visitContinuation(Continuation node); 1926 T visitContinuation(Continuation node);
1900 T visitMutableVariable(MutableVariable node); 1927 T visitMutableVariable(MutableVariable node);
1901 T visitGetStatic(GetStatic node); 1928 T visitGetStatic(GetStatic node);
1902 T visitInterceptor(Interceptor node); 1929 T visitInterceptor(Interceptor node);
1903 T visitCreateInstance(CreateInstance node); 1930 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. 2412 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
2386 class RemovalVisitor extends TrampolineRecursiveVisitor { 2413 class RemovalVisitor extends TrampolineRecursiveVisitor {
2387 processReference(Reference reference) { 2414 processReference(Reference reference) {
2388 reference.unlink(); 2415 reference.unlink();
2389 } 2416 }
2390 2417
2391 static void remove(Node node) { 2418 static void remove(Node node) {
2392 (new RemovalVisitor()).visit(node); 2419 (new RemovalVisitor()).visit(node);
2393 } 2420 }
2394 } 2421 }
2422
2423 /// A visitor to copy instances of [Definition] or its subclasses, except for
2424 /// instances of [Continuation].
2425 ///
2426 /// The visitor maintains a map from original definitions to their copies.
2427 /// When the [copy] method is called for a non-Continuation definition,
2428 /// a copy is created, added to the map and returned as the result. Copying a
2429 /// definition assumes that the definitions of all references have already
2430 /// been copied by the same visitor.
2431 class DefinitionCopyingVisitor extends Visitor<Definition> {
2432 Map<Definition, Definition> _copies = <Definition, Definition>{};
2433
2434 /// Put a copy into the map.
2435 ///
2436 /// This method should be used instead of directly adding copies to the map.
2437 Definition putCopy(Definition original, Definition copy) {
2438 if (copy is Variable) {
2439 copy.type = (original as Variable).type;
sra1 2015/12/18 02:16:26 We usually use a typed local rather than 'as'.
Kevin Millikin (Google) 2015/12/21 12:28:02 I know, but it looks horrible. We shouldn't have
2440 if (copy is Primitive) {
asgerf 2015/12/17 15:40:34 MutableVariable also has a hint, so we could just
Kevin Millikin (Google) 2015/12/21 12:28:02 Done.
2441 copy.hint = (original as Primitive).hint;
2442 }
2443 }
2444 return _copies[original] = copy;
2445 }
2446
2447 /// Get the copy of a [Reference]'s definition from the map.
2448 Definition getCopy(Reference reference) => _copies[reference.definition];
2449
2450 /// Map a list of [Reference]s to the list of their definition's copies.
2451 List<Definition> getList(List<Reference> list) => list.map(getCopy).toList();
2452
2453 /// Copy a non-[Continuation] [Definition].
2454 Definition copy(Definition node) {
2455 assert (node is! Continuation);
2456 return putCopy(node, visit(node));
2457 }
2458
2459 Definition visit(Node node) => node.accept(this);
2460
2461 Definition visitFunctionDefinition(FunctionDefinition node) {}
2462 Definition visitLetPrim(LetPrim node) {}
2463 Definition visitLetCont(LetCont node) {}
2464 Definition visitLetHandler(LetHandler node) {}
2465 Definition visitLetMutable(LetMutable node) {}
2466 Definition visitInvokeContinuation(InvokeContinuation node) {}
2467 Definition visitThrow(Throw node) {}
2468 Definition visitRethrow(Rethrow node) {}
2469 Definition visitBranch(Branch node) {}
2470 Definition visitUnreachable(Unreachable node) {}
2471 Definition visitContinuation(Continuation node) {}
2472
2473 Definition visitInvokeStatic(InvokeStatic node) {
2474 return new InvokeStatic(node.target, node.selector, getList(node.arguments),
2475 node.sourceInformation);
2476 }
2477
2478 Definition visitInvokeMethod(InvokeMethod node) {
2479 return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask,
2480 getList(node.arguments),
2481 node.sourceInformation);
2482 }
2483
2484 Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) {
2485 return new InvokeMethodDirectly(getCopy(node.receiver), node.target,
2486 node.selector,
2487 getList(node.arguments),
2488 node.sourceInformation);
2489 }
2490
2491 Definition visitInvokeConstructor(InvokeConstructor node) {
2492 return new InvokeConstructor(node.dartType, node.target, node.selector,
2493 getList(node.arguments),
2494 node.sourceInformation);
2495 }
2496
2497 Definition visitTypeCast(TypeCast node) {
2498 return new TypeCast(getCopy(node.value), node.dartType,
2499 getList(node.typeArguments));
2500 }
2501
2502 Definition visitSetMutable(SetMutable node) {
2503 return new SetMutable(getCopy(node.variable), getCopy(node.value));
2504 }
2505
2506 Definition visitSetStatic(SetStatic node) {
2507 return new SetStatic(node.element, getCopy(node.value),
2508 node.sourceInformation);
2509 }
2510
2511 Definition visitSetField(SetField node) {
2512 return new SetField(getCopy(node.object), node.field, getCopy(node.value));
2513 }
2514
2515 Definition visitGetLazyStatic(GetLazyStatic node) {
2516 return new GetLazyStatic(node.element, node.sourceInformation);
2517 }
2518
2519 Definition visitAwait(Await node) {
2520 return new Await(getCopy(node.input));
2521 }
2522
2523 Definition visitYield(Yield node) {
2524 return new Yield(getCopy(node.input), node.hasStar);
2525 }
2526
2527 Definition visitLiteralList(LiteralList node) {
2528 return new LiteralList(node.dartType, getList(node.values));
2529 }
2530
2531 Definition visitLiteralMap(LiteralMap node) {
2532 List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) {
2533 return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value));
2534 }).toList();
2535 return new LiteralMap(node.dartType, entries);
2536 }
2537
2538 Definition visitConstant(Constant node) {
2539 return new Constant(node.value, sourceInformation: node.sourceInformation);
2540 }
2541
2542 Definition visitGetMutable(GetMutable node) {
2543 return new GetMutable(getCopy(node.variable));
2544 }
2545
2546 Definition visitParameter(Parameter node) {
2547 return new Parameter(node.hint);
2548 }
2549
2550 Definition visitMutableVariable(MutableVariable node) {
2551 return new MutableVariable(node.hint);
2552 }
2553
2554 Definition visitGetStatic(GetStatic node) {
2555 return new GetStatic(node.element, node.sourceInformation);
2556 }
2557
2558 Definition visitInterceptor(Interceptor node) {
2559 return new Interceptor(getCopy(node.input), node.sourceInformation)
2560 ..interceptedClasses.addAll(node.interceptedClasses);
2561 }
2562
2563 Definition visitCreateInstance(CreateInstance node) {
2564 return new CreateInstance(node.classElement, getList(node.arguments),
2565 getList(node.typeInformation),
2566 node.sourceInformation);
2567 }
2568
2569 Definition visitGetField(GetField node) {
2570 return new GetField(getCopy(node.object), node.field);
2571 }
2572
2573 Definition visitCreateBox(CreateBox node) {
2574 return new CreateBox();
2575 }
2576
2577 Definition visitReifyRuntimeType(ReifyRuntimeType node) {
2578 return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation);
2579 }
2580
2581 Definition visitReadTypeVariable(ReadTypeVariable node) {
2582 return new ReadTypeVariable(node.variable, getCopy(node.target),
2583 node.sourceInformation);
2584 }
2585
2586 Definition visitTypeExpression(TypeExpression node) {
2587 return new TypeExpression(node.dartType, getList(node.arguments));
2588 }
2589
2590 Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
2591 return new CreateInvocationMirror(node.selector, getList(node.arguments));
2592 }
2593
2594 Definition visitTypeTest(TypeTest node) {
2595 return new TypeTest(getCopy(node.value), node.dartType,
2596 getList(node.typeArguments));
2597 }
2598
2599 Definition visitTypeTestViaFlag(TypeTestViaFlag node) {
2600 return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType);
2601 }
2602
2603 Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
2604 return new ApplyBuiltinOperator(node.operator, getList(node.arguments),
2605 node.sourceInformation);
2606 }
2607
2608 Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
2609 return new ApplyBuiltinMethod(node.method, getCopy(node.receiver),
2610 getList(node.arguments),
2611 node.sourceInformation,
2612 receiverIsNotNull: node.receiverIsNotNull);
2613 }
2614
2615 Definition visitGetLength(GetLength node) {
2616 return new GetLength(getCopy(node.object));
2617 }
2618
2619 Definition visitGetIndex(GetIndex node) {
2620 return new GetIndex(getCopy(node.object), getCopy(node.index));
2621 }
2622
2623 Definition visitSetIndex(SetIndex node) {
2624 return new SetIndex(getCopy(node.object), getCopy(node.index),
2625 getCopy(node.value));
2626 }
2627
2628 Definition visitRefinement(Refinement node) {
2629 return new Refinement(getCopy(node.value), node.refineType);
2630 }
2631
2632 Definition visitBoundsCheck(BoundsCheck node) {
2633 if (node.hasNoChecks) {
2634 return new BoundsCheck.noCheck(getCopy(node.object),
2635 node.sourceInformation);
2636 } else {
2637 return new BoundsCheck(getCopy(node.object), getCopy(node.index),
2638 getCopy(node.length),
2639 node.checks,
2640 node.sourceInformation);
2641 }
2642 }
2643
2644 Definition visitNullCheck(NullCheck node) {
2645 return new NullCheck(getCopy(node.value), node.sourceInformation);
2646 }
2647
2648 Definition visitForeignCode(ForeignCode node) {
2649 return new ForeignCode(node.codeTemplate, node.type,
2650 getList(node.arguments),
2651 node.nativeBehavior,
2652 dependency: node.dependency);
2653 }
2654 }
2655
2656 /// A trampolining visitor to copy [FunctionDefinition]s.
2657 class CopyingVisitor extends TrampolineRecursiveVisitor {
2658 // The visitor maintains a map from original continuations to their copies.
2659 Map<Continuation, Continuation> _copies = <Continuation, Continuation>{};
2660
2661 // The visitor uses an auxiliary visitor to copy definitions.
2662 DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor();
2663
2664 // While copying a block, the state of the visitor is a 'linked list' of
2665 // the expressions in the block's body, with a pointer to the last element
2666 // of the list.
2667 Expression _first = null;
2668 Expression _current = null;
2669
2670 void plug(Expression body) {
2671 if (_first == null) {
2672 _first = body;
2673 } else {
2674 assert(_current != null);
2675 (_current as InteriorExpression).body = body;
2676 }
2677 _current = body;
2678 }
2679
2680 // Continuations are added to the visitor's stack to be visited after copying
2681 // the current block is finished. The stack action saves the current block,
2682 // copies the continuation's body, sets the body on the copy of the
2683 // continuation, and restores the current block.
2684 //
2685 // Note that continuations are added to the copy map before the stack action
2686 // to visit them is performed.
2687 void push(Continuation cont) {
2688 assert(!cont.isReturnContinuation);
2689 _stack.add(() {
2690 Expression savedFirst = _first;
2691 Expression savedPrevious = _current;
asgerf 2015/12/17 15:40:34 Do we need to cache _current?
Kevin Millikin (Google) 2015/12/21 12:28:02 Nope. And that nicely dodges the issue of whether
2692 _first = _current = null;
2693 _processBlock(cont.body);
2694 _copies[cont].body = _first;
2695 _first = savedFirst;
2696 _current = savedPrevious;
2697 });
2698 }
2699
2700 FunctionDefinition copy(FunctionDefinition node) {
2701 assert(_first == null && _current == null);
2702 _first = _current = null;
2703 // Definitions are copied where they are bound, before processing
2704 // expressions in the scope of their binding.
2705 Parameter thisParameter = node.thisParameter == null
2706 ? null
2707 : _definitions.copy(node.thisParameter);
2708 List<Parameter> parameters =
2709 node.parameters.map(_definitions.copy).toList();
2710 // Though the return continuation's parameter does not have any uses,
2711 // we still make a proper copy to ensure that hints, type, etc. are
2712 // copied.
2713 Parameter returnParameter =
2714 _definitions.copy(node.returnContinuation.parameters.first);
2715 Continuation returnContinuation = _copies[node.returnContinuation] =
2716 new Continuation([returnParameter]);
2717
2718 visit(node.body);
2719 FunctionDefinition copy = new FunctionDefinition(node.element,
2720 thisParameter,
2721 parameters,
2722 returnContinuation,
2723 _first);
2724 _first = _current = null;
2725 return copy;
2726 }
2727
2728 Node visit(Node node) => node.accept(this);
2729
2730 Expression traverseLetCont(LetCont node) {
2731 // Continuations are copied where they are bound, before processing
2732 // expressions in the scope of their binding.
2733 List<Continuation> continuations = node.continuations.map((Continuation c) {
2734 push(c);
2735 return _copies[c] =
2736 new Continuation(c.parameters.map(_definitions.copy).toList());
2737 }).toList();
2738 plug(new LetCont.many(continuations, null));
2739 return node.body;
2740 }
2741
2742 Expression traverseLetHandler(LetHandler node) {
2743 // Continuations are copied where they are bound, before processing
2744 // expressions in the scope of their binding.
2745 push(node.handler);
2746 Continuation handler = _copies[node.handler] =
2747 new Continuation(node.handler.parameters.map(_definitions.copy)
2748 .toList());
2749 plug(new LetHandler(handler, null));
2750 return node.body;
2751 }
2752
2753 Expression traverseLetPrim(LetPrim node) {
2754 plug(new LetPrim(_definitions.copy(node.primitive)));
2755 return node.body;
2756 }
2757
2758 Expression traverseLetMutable(LetMutable node) {
2759 plug(new LetMutable(_definitions.copy(node.variable),
2760 _definitions.getCopy(node.value)));
2761 return node.body;
2762 }
2763
2764 // Tail expressions do not have references, so we do not need to map them
2765 // to their copies.
2766 visitInvokeContinuation(InvokeContinuation node) {
2767 plug(new InvokeContinuation(_copies[node.continuation.definition],
2768 _definitions.getList(node.arguments),
2769 isRecursive: node.isRecursive,
2770 isEscapingTry: node.isEscapingTry,
2771 sourceInformation: node.sourceInformation));
2772 }
2773
2774 Node visitThrow(Throw node) {
2775 plug(new Throw(_definitions.getCopy(node.value)));
2776 }
2777
2778 Node visitRethrow(Rethrow node) {
2779 plug(new Rethrow());
2780 }
2781
2782 Node visitBranch(Branch node) {
2783 plug(new Branch.loose(_definitions.getCopy(node.condition),
2784 _copies[node.trueContinuation.definition],
2785 _copies[node.falseContinuation.definition])
2786 ..isStrictCheck = node.isStrictCheck);
2787 }
2788
2789 Node visitUnreachable(Unreachable node) {
2790 plug(new Unreachable());
2791 }
2792 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698