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

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

Issue 1375213003: dart2js cps: Maintain parent pointers instead of recomputing them. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 2 months 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 '../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 10 matching lines...) Expand all
21 import '../native/native.dart' as native show NativeBehavior; 21 import '../native/native.dart' as native show NativeBehavior;
22 22
23 abstract class Node { 23 abstract class Node {
24 /// A pointer to the parent node. Is null until set by optimization passes. 24 /// A pointer to the parent node. Is null until set by optimization passes.
25 Node parent; 25 Node parent;
26 26
27 /// Workaround for a slow Object.hashCode in the VM. 27 /// Workaround for a slow Object.hashCode in the VM.
28 static int _usedHashCodes = 0; 28 static int _usedHashCodes = 0;
29 final int hashCode = ++_usedHashCodes; 29 final int hashCode = ++_usedHashCodes;
30 30
31 Node() {
32 setParentPointers();
33 }
34
31 accept(Visitor visitor); 35 accept(Visitor visitor);
36
37 /// Updates the [parent] of the immediate children to refer to this node.
38 ///
39 /// All constructors call this method to initialize parent pointers.
40 void setParentPointers();
32 } 41 }
33 42
34 /// Expressions can be evaluated, and may diverge, throw, and/or have 43 /// Expressions can be evaluated, and may diverge, throw, and/or have
35 /// side-effects. 44 /// side-effects.
36 /// 45 ///
37 /// Evaluation continues by stepping into a sub-expression, invoking a 46 /// Evaluation continues by stepping into a sub-expression, invoking a
38 /// continuation, or throwing an exception. 47 /// continuation, or throwing an exception.
39 /// 48 ///
40 /// Expressions do not a return value. Expressions that produce values should 49 /// Expressions do not a return value. Expressions that produce values should
41 /// invoke a [Continuation] with the result as argument. Alternatively, values 50 /// invoke a [Continuation] with the result as argument. Alternatively, values
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 Expression body; 320 Expression body;
312 321
313 LetPrim(this.primitive, [this.body = null]); 322 LetPrim(this.primitive, [this.body = null]);
314 323
315 Expression plug(Expression expr) { 324 Expression plug(Expression expr) {
316 assert(body == null); 325 assert(body == null);
317 return body = expr; 326 return body = expr;
318 } 327 }
319 328
320 accept(Visitor visitor) => visitor.visitLetPrim(this); 329 accept(Visitor visitor) => visitor.visitLetPrim(this);
330
331 void setParentPointers() {
332 primitive.parent = this;
333 if (body != null) body.parent = this;
334 }
321 } 335 }
322 336
323
324 /// Binding continuations. 337 /// Binding continuations.
325 /// 338 ///
326 /// let cont k0(v0 ...) = E0 339 /// let cont k0(v0 ...) = E0
327 /// k1(v1 ...) = E1 340 /// k1(v1 ...) = E1
328 /// ... 341 /// ...
329 /// in E 342 /// in E
330 /// 343 ///
331 /// The bound continuations are in scope in the body and the continuation 344 /// The bound continuations are in scope in the body and the continuation
332 /// parameters are in scope in the respective continuation bodies. 345 /// parameters are in scope in the respective continuation bodies.
333 /// 346 ///
(...skipping 13 matching lines...) Expand all
347 LetCont.many(this.continuations, this.body); 360 LetCont.many(this.continuations, this.body);
348 361
349 Expression plug(Expression expr) { 362 Expression plug(Expression expr) {
350 assert(continuations != null && 363 assert(continuations != null &&
351 continuations.isNotEmpty && 364 continuations.isNotEmpty &&
352 continuations.first.body == null); 365 continuations.first.body == null);
353 return continuations.first.body = expr; 366 return continuations.first.body = expr;
354 } 367 }
355 368
356 accept(Visitor visitor) => visitor.visitLetCont(this); 369 accept(Visitor visitor) => visitor.visitLetCont(this);
370
371 void setParentPointers() {
372 _setParentsOnNodes(continuations, this);
373 if (body != null) body.parent = this;
374 }
357 } 375 }
358 376
359 // Binding an exception handler. 377 // Binding an exception handler.
360 // 378 //
361 // let handler h(v0, v1) = E0 in E1 379 // let handler h(v0, v1) = E0 in E1
362 // 380 //
363 // The handler is a two-argument (exception, stack trace) continuation which 381 // The handler is a two-argument (exception, stack trace) continuation which
364 // is implicitly the error continuation of all the code in its body E1. 382 // is implicitly the error continuation of all the code in its body E1.
365 // [LetHandler] differs from a [LetCont] binding in that it (1) has the 383 // [LetHandler] differs from a [LetCont] binding in that it (1) has the
366 // runtime semantics of pushing/popping a handler from the dynamic exception 384 // runtime semantics of pushing/popping a handler from the dynamic exception
367 // handler stack and (2) it does not have any explicit invocations. 385 // handler stack and (2) it does not have any explicit invocations.
368 class LetHandler extends InteriorExpression { 386 class LetHandler extends InteriorExpression {
369 Continuation handler; 387 Continuation handler;
370 Expression body; 388 Expression body;
371 389
372 LetHandler(this.handler, this.body); 390 LetHandler(this.handler, this.body);
373 391
374 accept(Visitor visitor) => visitor.visitLetHandler(this); 392 accept(Visitor visitor) => visitor.visitLetHandler(this);
393
394 void setParentPointers() {
395 handler.parent = this;
396 if (body != null) body.parent = this;
397 }
375 } 398 }
376 399
377 /// Binding mutable variables. 400 /// Binding mutable variables.
378 /// 401 ///
379 /// let mutable v = P in E 402 /// let mutable v = P in E
380 /// 403 ///
381 /// [MutableVariable]s can be seen as ref cells that are not first-class 404 /// [MutableVariable]s can be seen as ref cells that are not first-class
382 /// values. They are therefore not [Primitive]s and not bound by [LetPrim] 405 /// values. They are therefore not [Primitive]s and not bound by [LetPrim]
383 /// to prevent unrestricted use of references to them. During one-pass 406 /// to prevent unrestricted use of references to them. During one-pass
384 /// construction, a [LetMutable] with an empty body is use to represent the 407 /// construction, a [LetMutable] with an empty body is use to represent the
385 /// one-hole context 'let mutable v = P in []'. 408 /// one-hole context 'let mutable v = P in []'.
386 class LetMutable extends InteriorExpression { 409 class LetMutable extends InteriorExpression {
387 final MutableVariable variable; 410 final MutableVariable variable;
388 final Reference<Primitive> value; 411 final Reference<Primitive> value;
389 Expression body; 412 Expression body;
390 413
391 LetMutable(this.variable, Primitive value) 414 LetMutable(this.variable, Primitive value)
392 : this.value = new Reference<Primitive>(value); 415 : this.value = new Reference<Primitive>(value);
393 416
394 Expression plug(Expression expr) { 417 Expression plug(Expression expr) {
395 return body = expr; 418 return body = expr;
396 } 419 }
397 420
398 accept(Visitor visitor) => visitor.visitLetMutable(this); 421 accept(Visitor visitor) => visitor.visitLetMutable(this);
422
423 void setParentPointers() {
424 variable.parent = this;
425 value.parent = this;
426 if (body != null) body.parent = this;
427 }
399 } 428 }
400 429
401 /// Invoke a static function. 430 /// Invoke a static function.
402 /// 431 ///
403 /// All optional arguments declared by [target] are passed in explicitly, and 432 /// All optional arguments declared by [target] are passed in explicitly, and
404 /// occur at the end of [arguments] list, in normalized order. 433 /// occur at the end of [arguments] list, in normalized order.
405 /// 434 ///
406 /// Discussion: 435 /// Discussion:
407 /// All information in the [selector] is technically redundant; it will likely 436 /// All information in the [selector] is technically redundant; it will likely
408 /// be removed. 437 /// be removed.
(...skipping 12 matching lines...) Expand all
421 : arguments = _referenceList(args), 450 : arguments = _referenceList(args),
422 continuation = new Reference<Continuation>(cont); 451 continuation = new Reference<Continuation>(cont);
423 452
424 InvokeStatic.byReference(this.target, 453 InvokeStatic.byReference(this.target,
425 this.selector, 454 this.selector,
426 this.arguments, 455 this.arguments,
427 this.continuation, 456 this.continuation,
428 [this.sourceInformation]); 457 [this.sourceInformation]);
429 458
430 accept(Visitor visitor) => visitor.visitInvokeStatic(this); 459 accept(Visitor visitor) => visitor.visitInvokeStatic(this);
460
461 void setParentPointers() {
462 _setParentsOnList(arguments, this);
463 continuation.parent = this;
464 }
431 } 465 }
432 466
433 /// Invoke a method on an object. 467 /// Invoke a method on an object.
434 /// 468 ///
435 /// This includes getters, setters, operators, and index getter/setters. 469 /// This includes getters, setters, operators, and index getter/setters.
436 /// 470 ///
437 /// Tearing off a method is treated like a getter invocation (getters and 471 /// Tearing off a method is treated like a getter invocation (getters and
438 /// tear-offs cannot be distinguished at compile-time). 472 /// tear-offs cannot be distinguished at compile-time).
439 /// 473 ///
440 /// The [selector] records the names of named arguments. The value of named 474 /// The [selector] records the names of named arguments. The value of named
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 this.continuation = new Reference<Continuation>(continuation); 506 this.continuation = new Reference<Continuation>(continuation);
473 507
474 InvokeMethod.byReference(this.receiver, 508 InvokeMethod.byReference(this.receiver,
475 this.selector, 509 this.selector,
476 this.mask, 510 this.mask,
477 this.arguments, 511 this.arguments,
478 this.continuation, 512 this.continuation,
479 this.sourceInformation); 513 this.sourceInformation);
480 514
481 accept(Visitor visitor) => visitor.visitInvokeMethod(this); 515 accept(Visitor visitor) => visitor.visitInvokeMethod(this);
516
517 void setParentPointers() {
518 receiver.parent = this;
519 _setParentsOnList(arguments, this);
520 continuation.parent = this;
521 }
482 } 522 }
483 523
484 /// Invoke [target] on [receiver], bypassing dispatch and override semantics. 524 /// Invoke [target] on [receiver], bypassing dispatch and override semantics.
485 /// 525 ///
486 /// That is, if [receiver] is an instance of a class that overrides [target] 526 /// That is, if [receiver] is an instance of a class that overrides [target]
487 /// with a different implementation, the overriding implementation is bypassed 527 /// with a different implementation, the overriding implementation is bypassed
488 /// and [target]'s implementation is invoked. 528 /// and [target]'s implementation is invoked.
489 /// 529 ///
490 /// As with [InvokeMethod], this can be used to invoke a method, operator, 530 /// As with [InvokeMethod], this can be used to invoke a method, operator,
491 /// getter, setter, or index getter/setter. 531 /// getter, setter, or index getter/setter.
(...skipping 20 matching lines...) Expand all
512 this.target, 552 this.target,
513 this.selector, 553 this.selector,
514 List<Primitive> arguments, 554 List<Primitive> arguments,
515 Continuation continuation, 555 Continuation continuation,
516 this.sourceInformation) 556 this.sourceInformation)
517 : this.receiver = new Reference<Primitive>(receiver), 557 : this.receiver = new Reference<Primitive>(receiver),
518 this.arguments = _referenceList(arguments), 558 this.arguments = _referenceList(arguments),
519 this.continuation = new Reference<Continuation>(continuation); 559 this.continuation = new Reference<Continuation>(continuation);
520 560
521 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this); 561 accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);
562
563 void setParentPointers() {
564 receiver.parent = this;
565 _setParentsOnList(arguments, this);
566 continuation.parent = this;
567 }
522 } 568 }
523 569
524 /// Non-const call to a constructor. 570 /// Non-const call to a constructor.
525 /// 571 ///
526 /// The [target] may be a generative constructor (forwarding or normal) 572 /// The [target] may be a generative constructor (forwarding or normal)
527 /// or a non-redirecting factory. 573 /// or a non-redirecting factory.
528 /// 574 ///
529 /// All optional arguments declared by [target] are passed in explicitly, and 575 /// All optional arguments declared by [target] are passed in explicitly, and
530 /// occur in the [arguments] list, in normalized order. 576 /// occur in the [arguments] list, in normalized order.
531 /// 577 ///
(...skipping 15 matching lines...) Expand all
547 InvokeConstructor(this.dartType, 593 InvokeConstructor(this.dartType,
548 this.target, 594 this.target,
549 this.selector, 595 this.selector,
550 List<Primitive> args, 596 List<Primitive> args,
551 Continuation cont, 597 Continuation cont,
552 this.sourceInformation) 598 this.sourceInformation)
553 : arguments = _referenceList(args), 599 : arguments = _referenceList(args),
554 continuation = new Reference<Continuation>(cont); 600 continuation = new Reference<Continuation>(cont);
555 601
556 accept(Visitor visitor) => visitor.visitInvokeConstructor(this); 602 accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
603
604 void setParentPointers() {
605 _setParentsOnList(arguments, this);
606 continuation.parent = this;
607 }
557 } 608 }
558 609
559 /// An alias for [value] in a context where the value is known to satisfy 610 /// An alias for [value] in a context where the value is known to satisfy
560 /// [type]. 611 /// [type].
561 /// 612 ///
562 /// Refinement nodes are inserted before the type propagator pass and removed 613 /// Refinement nodes are inserted before the type propagator pass and removed
563 /// afterwards, so as not to complicate passes that don't reason about types, 614 /// afterwards, so as not to complicate passes that don't reason about types,
564 /// but need to reason about value references being identical (i.e. referring 615 /// but need to reason about value references being identical (i.e. referring
565 /// to the same primitive). 616 /// to the same primitive).
566 class Refinement extends Primitive { 617 class Refinement extends Primitive {
567 Reference<Primitive> value; 618 Reference<Primitive> value;
568 final TypeMask refineType; 619 final TypeMask refineType;
569 620
570 Refinement(Primitive value, this.refineType) 621 Refinement(Primitive value, this.refineType)
571 : value = new Reference<Primitive>(value); 622 : value = new Reference<Primitive>(value);
572 623
573 bool get isSafeForElimination => true; 624 bool get isSafeForElimination => true;
574 bool get isSafeForReordering => false; 625 bool get isSafeForReordering => false;
575 626
576 accept(Visitor visitor) => visitor.visitRefinement(this); 627 accept(Visitor visitor) => visitor.visitRefinement(this);
577 628
578 Primitive get effectiveDefinition => value.definition.effectiveDefinition; 629 Primitive get effectiveDefinition => value.definition.effectiveDefinition;
630
631 void setParentPointers() {
632 value.parent = this;
633 }
579 } 634 }
580 635
581 /// An "is" type test. 636 /// An "is" type test.
582 /// 637 ///
583 /// Returns `true` if [value] is an instance of [type]. 638 /// Returns `true` if [value] is an instance of [type].
584 /// 639 ///
585 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might 640 /// [type] must not be the [Object], `dynamic` or [Null] types (though it might
586 /// be a type variable containing one of these types). This design is chosen 641 /// be a type variable containing one of these types). This design is chosen
587 /// to simplify code generation for type tests. 642 /// to simplify code generation for type tests.
588 class TypeTest extends Primitive { 643 class TypeTest extends Primitive {
(...skipping 22 matching lines...) Expand all
611 TypeTest(Primitive value, 666 TypeTest(Primitive value,
612 this.dartType, 667 this.dartType,
613 List<Primitive> typeArguments) 668 List<Primitive> typeArguments)
614 : this.value = new Reference<Primitive>(value), 669 : this.value = new Reference<Primitive>(value),
615 this.typeArguments = _referenceList(typeArguments); 670 this.typeArguments = _referenceList(typeArguments);
616 671
617 accept(Visitor visitor) => visitor.visitTypeTest(this); 672 accept(Visitor visitor) => visitor.visitTypeTest(this);
618 673
619 bool get isSafeForElimination => true; 674 bool get isSafeForElimination => true;
620 bool get isSafeForReordering => true; 675 bool get isSafeForReordering => true;
676
677 void setParentPointers() {
678 value.parent = this;
679 _setParentsOnList(typeArguments, this);
680 if (interceptor != null) interceptor.parent = this;
681 }
621 } 682 }
622 683
623 /// An "is" type test for a raw type, performed by testing a flag property. 684 /// An "is" type test for a raw type, performed by testing a flag property.
624 /// 685 ///
625 /// Returns `true` if [interceptor] is for [dartType]. 686 /// Returns `true` if [interceptor] is for [dartType].
626 class TypeTestViaFlag extends Primitive { 687 class TypeTestViaFlag extends Primitive {
627 Reference<Primitive> interceptor; 688 Reference<Primitive> interceptor;
628 final DartType dartType; 689 final DartType dartType;
629 690
630 TypeTestViaFlag(Primitive interceptor, this.dartType) 691 TypeTestViaFlag(Primitive interceptor, this.dartType)
631 : this.interceptor = new Reference<Primitive>(interceptor); 692 : this.interceptor = new Reference<Primitive>(interceptor);
632 693
633 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this); 694 accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this);
634 695
635 bool get isSafeForElimination => true; 696 bool get isSafeForElimination => true;
636 bool get isSafeForReordering => true; 697 bool get isSafeForReordering => true;
698
699 void setParentPointers() {
700 interceptor.parent = this;
701 }
637 } 702 }
638 703
639 /// An "as" type cast. 704 /// An "as" type cast.
640 /// 705 ///
641 /// If [value] is `null` or is an instance of [type], [continuation] is invoked 706 /// If [value] is `null` or is an instance of [type], [continuation] is invoked
642 /// with [value] as argument. Otherwise, a [CastError] is thrown. 707 /// with [value] as argument. Otherwise, a [CastError] is thrown.
643 /// 708 ///
644 /// Discussion: 709 /// Discussion:
645 /// The parameter to [continuation] is redundant since it will always equal 710 /// The parameter to [continuation] is redundant since it will always equal
646 /// [value], which is typically in scope in the continuation. However, it might 711 /// [value], which is typically in scope in the continuation. However, it might
647 /// simplify type propagation, since a better type can be computed for the 712 /// simplify type propagation, since a better type can be computed for the
648 /// continuation parameter without needing flow-sensitive analysis. 713 /// continuation parameter without needing flow-sensitive analysis.
649 class TypeCast extends CallExpression { 714 class TypeCast extends CallExpression {
650 Reference<Primitive> value; 715 Reference<Primitive> value;
651 final DartType dartType; 716 final DartType dartType;
652 717
653 /// See the corresponding field on [TypeTest]. 718 /// See the corresponding field on [TypeTest].
654 final List<Reference<Primitive>> typeArguments; 719 final List<Reference<Primitive>> typeArguments;
655 final Reference<Continuation> continuation; 720 final Reference<Continuation> continuation;
656 721
657 TypeCast(Primitive value, 722 TypeCast(Primitive value,
658 this.dartType, 723 this.dartType,
659 List<Primitive> typeArguments, 724 List<Primitive> typeArguments,
660 Continuation cont) 725 Continuation cont)
661 : this.value = new Reference<Primitive>(value), 726 : this.value = new Reference<Primitive>(value),
662 this.typeArguments = _referenceList(typeArguments), 727 this.typeArguments = _referenceList(typeArguments),
663 this.continuation = new Reference<Continuation>(cont); 728 this.continuation = new Reference<Continuation>(cont);
664 729
665 accept(Visitor visitor) => visitor.visitTypeCast(this); 730 accept(Visitor visitor) => visitor.visitTypeCast(this);
731
732 void setParentPointers() {
733 value.parent = this;
734 }
666 } 735 }
667 736
668 /// Apply a built-in operator. 737 /// Apply a built-in operator.
669 /// 738 ///
670 /// It must be known that the arguments have the proper types. 739 /// It must be known that the arguments have the proper types.
671 class ApplyBuiltinOperator extends Primitive { 740 class ApplyBuiltinOperator extends Primitive {
672 BuiltinOperator operator; 741 BuiltinOperator operator;
673 List<Reference<Primitive>> arguments; 742 List<Reference<Primitive>> arguments;
674 final SourceInformation sourceInformation; 743 final SourceInformation sourceInformation;
675 744
676 ApplyBuiltinOperator(this.operator, 745 ApplyBuiltinOperator(this.operator,
677 List<Primitive> arguments, 746 List<Primitive> arguments,
678 this.sourceInformation) 747 this.sourceInformation)
679 : this.arguments = _referenceList(arguments); 748 : this.arguments = _referenceList(arguments);
680 749
681 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); 750 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);
682 751
683 bool get isSafeForElimination => true; 752 bool get isSafeForElimination => true;
684 bool get isSafeForReordering => true; 753 bool get isSafeForReordering => true;
754
755 void setParentPointers() {
756 _setParentsOnList(arguments, this);
757 }
685 } 758 }
686 759
687 /// Apply a built-in method. 760 /// Apply a built-in method.
688 /// 761 ///
689 /// It must be known that the arguments have the proper types. 762 /// It must be known that the arguments have the proper types.
690 class ApplyBuiltinMethod extends Primitive { 763 class ApplyBuiltinMethod extends Primitive {
691 BuiltinMethod method; 764 BuiltinMethod method;
692 Reference<Primitive> receiver; 765 Reference<Primitive> receiver;
693 List<Reference<Primitive>> arguments; 766 List<Reference<Primitive>> arguments;
694 final SourceInformation sourceInformation; 767 final SourceInformation sourceInformation;
695 768
696 bool receiverIsNotNull; 769 bool receiverIsNotNull;
697 770
698 ApplyBuiltinMethod(this.method, 771 ApplyBuiltinMethod(this.method,
699 Primitive receiver, 772 Primitive receiver,
700 List<Primitive> arguments, 773 List<Primitive> arguments,
701 this.sourceInformation, 774 this.sourceInformation,
702 {this.receiverIsNotNull: false}) 775 {this.receiverIsNotNull: false})
703 : this.receiver = new Reference<Primitive>(receiver), 776 : this.receiver = new Reference<Primitive>(receiver),
704 this.arguments = _referenceList(arguments); 777 this.arguments = _referenceList(arguments);
705 778
706 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); 779 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this);
707 780
708 bool get isSafeForElimination => false; 781 bool get isSafeForElimination => false;
709 bool get isSafeForReordering => false; 782 bool get isSafeForReordering => false;
783
784 void setParentPointers() {
785 receiver.parent = this;
786 _setParentsOnList(arguments, this);
787 }
710 } 788 }
711 789
712 /// Throw a value. 790 /// Throw a value.
713 /// 791 ///
714 /// Throw is an expression, i.e., it always occurs in tail position with 792 /// Throw is an expression, i.e., it always occurs in tail position with
715 /// respect to a body or expression. 793 /// respect to a body or expression.
716 class Throw extends TailExpression { 794 class Throw extends TailExpression {
717 Reference<Primitive> value; 795 Reference<Primitive> value;
718 796
719 Throw(Primitive value) : value = new Reference<Primitive>(value); 797 Throw(Primitive value) : value = new Reference<Primitive>(value);
720 798
721 accept(Visitor visitor) => visitor.visitThrow(this); 799 accept(Visitor visitor) => visitor.visitThrow(this);
800
801 void setParentPointers() {
802 value.parent = this;
803 }
722 } 804 }
723 805
724 /// Rethrow 806 /// Rethrow
725 /// 807 ///
726 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It 808 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It
727 /// implicitly throws the exception parameter of the enclosing handler with 809 /// implicitly throws the exception parameter of the enclosing handler with
728 /// the same stack trace as the enclosing handler. 810 /// the same stack trace as the enclosing handler.
729 class Rethrow extends TailExpression { 811 class Rethrow extends TailExpression {
730 accept(Visitor visitor) => visitor.visitRethrow(this); 812 accept(Visitor visitor) => visitor.visitRethrow(this);
813 void setParentPointers() {}
731 } 814 }
732 815
733 /// An expression that is known to be unreachable. 816 /// An expression that is known to be unreachable.
734 /// 817 ///
735 /// This can be placed as the body of a call continuation, when the caller is 818 /// This can be placed as the body of a call continuation, when the caller is
736 /// known never to invoke it, e.g. because the calling expression always throws. 819 /// known never to invoke it, e.g. because the calling expression always throws.
737 class Unreachable extends TailExpression { 820 class Unreachable extends TailExpression {
738 accept(Visitor visitor) => visitor.visitUnreachable(this); 821 accept(Visitor visitor) => visitor.visitUnreachable(this);
822 void setParentPointers() {}
739 } 823 }
740 824
741 /// Gets the value from a [MutableVariable]. 825 /// Gets the value from a [MutableVariable].
742 /// 826 ///
743 /// [MutableVariable]s can be seen as ref cells that are not first-class 827 /// [MutableVariable]s can be seen as ref cells that are not first-class
744 /// values. A [LetPrim] with a [GetMutable] can then be seen as: 828 /// values. A [LetPrim] with a [GetMutable] can then be seen as:
745 /// 829 ///
746 /// let prim p = ![variable] in [body] 830 /// let prim p = ![variable] in [body]
747 /// 831 ///
748 class GetMutable extends Primitive { 832 class GetMutable extends Primitive {
749 final Reference<MutableVariable> variable; 833 final Reference<MutableVariable> variable;
750 834
751 GetMutable(MutableVariable variable) 835 GetMutable(MutableVariable variable)
752 : this.variable = new Reference<MutableVariable>(variable); 836 : this.variable = new Reference<MutableVariable>(variable);
753 837
754 accept(Visitor visitor) => visitor.visitGetMutable(this); 838 accept(Visitor visitor) => visitor.visitGetMutable(this);
755 839
756 bool get isSafeForElimination => true; 840 bool get isSafeForElimination => true;
757 bool get isSafeForReordering => false; 841 bool get isSafeForReordering => false;
842
843 void setParentPointers() {
844 variable.parent = this;
845 }
758 } 846 }
759 847
760 /// Assign a [MutableVariable]. 848 /// Assign a [MutableVariable].
761 /// 849 ///
762 /// [MutableVariable]s can be seen as ref cells that are not first-class 850 /// [MutableVariable]s can be seen as ref cells that are not first-class
763 /// values. This can be seen as a dereferencing assignment: 851 /// values. This can be seen as a dereferencing assignment:
764 /// 852 ///
765 /// { [variable] := [value]; [body] } 853 /// { [variable] := [value]; [body] }
766 class SetMutable extends Primitive { 854 class SetMutable extends Primitive {
767 final Reference<MutableVariable> variable; 855 final Reference<MutableVariable> variable;
768 final Reference<Primitive> value; 856 final Reference<Primitive> value;
769 857
770 SetMutable(MutableVariable variable, Primitive value) 858 SetMutable(MutableVariable variable, Primitive value)
771 : this.variable = new Reference<MutableVariable>(variable), 859 : this.variable = new Reference<MutableVariable>(variable),
772 this.value = new Reference<Primitive>(value); 860 this.value = new Reference<Primitive>(value);
773 861
774 accept(Visitor visitor) => visitor.visitSetMutable(this); 862 accept(Visitor visitor) => visitor.visitSetMutable(this);
775 863
776 bool get isSafeForElimination => false; 864 bool get isSafeForElimination => false;
777 bool get isSafeForReordering => false; 865 bool get isSafeForReordering => false;
866
867 void setParentPointers() {
868 variable.parent = this;
869 value.parent = this;
870 }
778 } 871 }
779 872
780 /// Invoke a continuation in tail position. 873 /// Invoke a continuation in tail position.
781 class InvokeContinuation extends TailExpression { 874 class InvokeContinuation extends TailExpression {
782 Reference<Continuation> continuation; 875 Reference<Continuation> continuation;
783 List<Reference<Primitive>> arguments; 876 List<Reference<Primitive>> arguments;
784 SourceInformation sourceInformation; 877 SourceInformation sourceInformation;
785 878
786 // An invocation of a continuation is recursive if it occurs in the body of 879 // An invocation of a continuation is recursive if it occurs in the body of
787 // the continuation itself. 880 // the continuation itself.
(...skipping 18 matching lines...) Expand all
806 /// 899 ///
807 /// Used as a placeholder for a jump whose target is not yet created 900 /// Used as a placeholder for a jump whose target is not yet created
808 /// (e.g., in the translation of break and continue). 901 /// (e.g., in the translation of break and continue).
809 InvokeContinuation.uninitialized({this.isRecursive: false, 902 InvokeContinuation.uninitialized({this.isRecursive: false,
810 this.isEscapingTry: false}) 903 this.isEscapingTry: false})
811 : continuation = null, 904 : continuation = null,
812 arguments = null, 905 arguments = null,
813 sourceInformation = null; 906 sourceInformation = null;
814 907
815 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); 908 accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
909
910 void setParentPointers() {
911 if (continuation != null) continuation.parent = this;
912 if (arguments != null) _setParentsOnList(arguments, this);
913 }
816 } 914 }
817 915
818 /// Choose between a pair of continuations based on a condition value. 916 /// Choose between a pair of continuations based on a condition value.
819 /// 917 ///
820 /// The two continuations must not declare any parameters. 918 /// The two continuations must not declare any parameters.
821 class Branch extends TailExpression { 919 class Branch extends TailExpression {
822 final Reference<Primitive> condition; 920 final Reference<Primitive> condition;
823 final Reference<Continuation> trueContinuation; 921 final Reference<Continuation> trueContinuation;
824 final Reference<Continuation> falseContinuation; 922 final Reference<Continuation> falseContinuation;
825 923
(...skipping 14 matching lines...) Expand all
840 938
841 Branch.loose(Primitive condition, 939 Branch.loose(Primitive condition,
842 Continuation trueCont, 940 Continuation trueCont,
843 Continuation falseCont) 941 Continuation falseCont)
844 : this.condition = new Reference<Primitive>(condition), 942 : this.condition = new Reference<Primitive>(condition),
845 trueContinuation = new Reference<Continuation>(trueCont), 943 trueContinuation = new Reference<Continuation>(trueCont),
846 falseContinuation = new Reference<Continuation>(falseCont), 944 falseContinuation = new Reference<Continuation>(falseCont),
847 this.isStrictCheck = false; 945 this.isStrictCheck = false;
848 946
849 accept(Visitor visitor) => visitor.visitBranch(this); 947 accept(Visitor visitor) => visitor.visitBranch(this);
948
949 void setParentPointers() {
950 condition.parent = this;
951 trueContinuation.parent = this;
952 falseContinuation.parent = this;
953 }
850 } 954 }
851 955
852 /// Directly assigns to a field on a given object. 956 /// Directly assigns to a field on a given object.
853 class SetField extends Primitive { 957 class SetField extends Primitive {
854 final Reference<Primitive> object; 958 final Reference<Primitive> object;
855 FieldElement field; 959 FieldElement field;
856 final Reference<Primitive> value; 960 final Reference<Primitive> value;
857 961
858 SetField(Primitive object, this.field, Primitive value) 962 SetField(Primitive object, this.field, Primitive value)
859 : this.object = new Reference<Primitive>(object), 963 : this.object = new Reference<Primitive>(object),
860 this.value = new Reference<Primitive>(value); 964 this.value = new Reference<Primitive>(value);
861 965
862 accept(Visitor visitor) => visitor.visitSetField(this); 966 accept(Visitor visitor) => visitor.visitSetField(this);
863 967
864 bool get isSafeForElimination => false; 968 bool get isSafeForElimination => false;
865 bool get isSafeForReordering => false; 969 bool get isSafeForReordering => false;
970
971 void setParentPointers() {
972 object.parent = this;
973 value.parent = this;
974 }
866 } 975 }
867 976
868 /// Directly reads from a field on a given object. 977 /// Directly reads from a field on a given object.
869 /// 978 ///
870 /// The [object] must either be `null` or an object that has [field]. 979 /// The [object] must either be `null` or an object that has [field].
871 class GetField extends Primitive { 980 class GetField extends Primitive {
872 final Reference<Primitive> object; 981 final Reference<Primitive> object;
873 FieldElement field; 982 FieldElement field;
874 983
875 /// True if the object is known not to be null. 984 /// True if the object is known not to be null.
876 // TODO(asgerf): This is a placeholder until we agree on how to track 985 // TODO(asgerf): This is a placeholder until we agree on how to track
877 // side effects. 986 // side effects.
878 bool objectIsNotNull = false; 987 bool objectIsNotNull = false;
879 988
880 GetField(Primitive object, this.field) 989 GetField(Primitive object, this.field)
881 : this.object = new Reference<Primitive>(object); 990 : this.object = new Reference<Primitive>(object);
882 991
883 accept(Visitor visitor) => visitor.visitGetField(this); 992 accept(Visitor visitor) => visitor.visitGetField(this);
884 993
885 bool get isSafeForElimination => objectIsNotNull; 994 bool get isSafeForElimination => objectIsNotNull;
886 bool get isSafeForReordering => false; 995 bool get isSafeForReordering => false;
887 996
888 toString() => 'GetField($field)'; 997 toString() => 'GetField($field)';
998
999 void setParentPointers() {
1000 object.parent = this;
1001 }
889 } 1002 }
890 1003
891 /// Get the length of a string or native list. 1004 /// Get the length of a string or native list.
892 class GetLength extends Primitive { 1005 class GetLength extends Primitive {
893 final Reference<Primitive> object; 1006 final Reference<Primitive> object;
894 1007
895 /// True if the object is known not to be null. 1008 /// True if the object is known not to be null.
896 bool objectIsNotNull = false; 1009 bool objectIsNotNull = false;
897 1010
898 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); 1011 GetLength(Primitive object) : this.object = new Reference<Primitive>(object);
899 1012
900 bool get isSafeForElimination => objectIsNotNull; 1013 bool get isSafeForElimination => objectIsNotNull;
901 bool get isSafeForReordering => false; 1014 bool get isSafeForReordering => false;
902 1015
903 accept(Visitor v) => v.visitGetLength(this); 1016 accept(Visitor v) => v.visitGetLength(this);
1017
1018 void setParentPointers() {
1019 object.parent = this;
1020 }
904 } 1021 }
905 1022
906 /// Read an entry from a string or native list. 1023 /// Read an entry from a string or native list.
907 /// 1024 ///
908 /// [object] must be null or a native list or a string, and [index] must be 1025 /// [object] must be null or a native list or a string, and [index] must be
909 /// an integer. 1026 /// an integer.
910 class GetIndex extends Primitive { 1027 class GetIndex extends Primitive {
911 final Reference<Primitive> object; 1028 final Reference<Primitive> object;
912 final Reference<Primitive> index; 1029 final Reference<Primitive> index;
913 1030
914 /// True if the object is known not to be null. 1031 /// True if the object is known not to be null.
915 bool objectIsNotNull = false; 1032 bool objectIsNotNull = false;
916 1033
917 GetIndex(Primitive object, Primitive index) 1034 GetIndex(Primitive object, Primitive index)
918 : this.object = new Reference<Primitive>(object), 1035 : this.object = new Reference<Primitive>(object),
919 this.index = new Reference<Primitive>(index); 1036 this.index = new Reference<Primitive>(index);
920 1037
921 bool get isSafeForElimination => objectIsNotNull; 1038 bool get isSafeForElimination => objectIsNotNull;
922 bool get isSafeForReordering => false; 1039 bool get isSafeForReordering => false;
923 1040
924 accept(Visitor v) => v.visitGetIndex(this); 1041 accept(Visitor v) => v.visitGetIndex(this);
1042
1043 void setParentPointers() {
1044 object.parent = this;
1045 index.parent = this;
1046 }
925 } 1047 }
926 1048
927 /// Set an entry on a native list. 1049 /// Set an entry on a native list.
928 /// 1050 ///
929 /// [object] must be null or a native list, and [index] must be an integer. 1051 /// [object] must be null or a native list, and [index] must be an integer.
930 /// 1052 ///
931 /// The primitive itself has no value and may not be referenced. 1053 /// The primitive itself has no value and may not be referenced.
932 class SetIndex extends Primitive { 1054 class SetIndex extends Primitive {
933 final Reference<Primitive> object; 1055 final Reference<Primitive> object;
934 final Reference<Primitive> index; 1056 final Reference<Primitive> index;
935 final Reference<Primitive> value; 1057 final Reference<Primitive> value;
936 1058
937 SetIndex(Primitive object, Primitive index, Primitive value) 1059 SetIndex(Primitive object, Primitive index, Primitive value)
938 : this.object = new Reference<Primitive>(object), 1060 : this.object = new Reference<Primitive>(object),
939 this.index = new Reference<Primitive>(index), 1061 this.index = new Reference<Primitive>(index),
940 this.value = new Reference<Primitive>(value); 1062 this.value = new Reference<Primitive>(value);
941 1063
942 bool get isSafeForElimination => false; 1064 bool get isSafeForElimination => false;
943 bool get isSafeForReordering => false; 1065 bool get isSafeForReordering => false;
944 1066
945 accept(Visitor v) => v.visitSetIndex(this); 1067 accept(Visitor v) => v.visitSetIndex(this);
1068
1069 void setParentPointers() {
1070 object.parent = this;
1071 index.parent = this;
1072 value.parent = this;
1073 }
946 } 1074 }
947 1075
948 /// Reads the value of a static field or tears off a static method. 1076 /// Reads the value of a static field or tears off a static method.
949 /// 1077 ///
950 /// Note that lazily initialized fields should be read using GetLazyStatic. 1078 /// Note that lazily initialized fields should be read using GetLazyStatic.
951 class GetStatic extends Primitive { 1079 class GetStatic extends Primitive {
952 /// Can be [FieldElement] or [FunctionElement]. 1080 /// Can be [FieldElement] or [FunctionElement].
953 final Element element; 1081 final Element element;
954 final SourceInformation sourceInformation; 1082 final SourceInformation sourceInformation;
955 1083
956 GetStatic(this.element, [this.sourceInformation]); 1084 GetStatic(this.element, [this.sourceInformation]);
957 1085
958 accept(Visitor visitor) => visitor.visitGetStatic(this); 1086 accept(Visitor visitor) => visitor.visitGetStatic(this);
959 1087
960 bool get isSafeForElimination { 1088 bool get isSafeForElimination {
961 return true; 1089 return true;
962 } 1090 }
963 bool get isSafeForReordering { 1091 bool get isSafeForReordering {
964 return element is FunctionElement || element.isFinal; 1092 return element is FunctionElement || element.isFinal;
965 } 1093 }
1094
1095 void setParentPointers() {}
966 } 1096 }
967 1097
968 /// Sets the value of a static field. 1098 /// Sets the value of a static field.
969 class SetStatic extends Primitive { 1099 class SetStatic extends Primitive {
970 final FieldElement element; 1100 final FieldElement element;
971 final Reference<Primitive> value; 1101 final Reference<Primitive> value;
972 final SourceInformation sourceInformation; 1102 final SourceInformation sourceInformation;
973 1103
974 SetStatic(this.element, Primitive value, [this.sourceInformation]) 1104 SetStatic(this.element, Primitive value, [this.sourceInformation])
975 : this.value = new Reference<Primitive>(value); 1105 : this.value = new Reference<Primitive>(value);
976 1106
977 accept(Visitor visitor) => visitor.visitSetStatic(this); 1107 accept(Visitor visitor) => visitor.visitSetStatic(this);
978 1108
979 bool get isSafeForElimination => false; 1109 bool get isSafeForElimination => false;
980 bool get isSafeForReordering => false; 1110 bool get isSafeForReordering => false;
1111
1112 void setParentPointers() {
1113 value.parent = this;
1114 }
981 } 1115 }
982 1116
983 /// Reads the value of a lazily initialized static field. 1117 /// Reads the value of a lazily initialized static field.
984 /// 1118 ///
985 /// If the field has not yet been initialized, its initializer is evaluated 1119 /// If the field has not yet been initialized, its initializer is evaluated
986 /// and assigned to the field. 1120 /// and assigned to the field.
987 /// 1121 ///
988 /// [continuation] is then invoked with the value of the field as argument. 1122 /// [continuation] is then invoked with the value of the field as argument.
989 class GetLazyStatic extends CallExpression { 1123 class GetLazyStatic extends CallExpression {
990 final FieldElement element; 1124 final FieldElement element;
991 final Reference<Continuation> continuation; 1125 final Reference<Continuation> continuation;
992 final SourceInformation sourceInformation; 1126 final SourceInformation sourceInformation;
993 1127
994 GetLazyStatic(this.element, 1128 GetLazyStatic(this.element,
995 Continuation continuation, 1129 Continuation continuation,
996 [this.sourceInformation]) 1130 [this.sourceInformation])
997 : continuation = new Reference<Continuation>(continuation); 1131 : continuation = new Reference<Continuation>(continuation);
998 1132
999 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); 1133 accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
1134
1135 void setParentPointers() {
1136 continuation.parent = this;
1137 }
1000 } 1138 }
1001 1139
1002 /// Creates an object for holding boxed variables captured by a closure. 1140 /// Creates an object for holding boxed variables captured by a closure.
1003 class CreateBox extends Primitive { 1141 class CreateBox extends Primitive {
1004 accept(Visitor visitor) => visitor.visitCreateBox(this); 1142 accept(Visitor visitor) => visitor.visitCreateBox(this);
1005 1143
1006 bool get isSafeForElimination => true; 1144 bool get isSafeForElimination => true;
1007 bool get isSafeForReordering => true; 1145 bool get isSafeForReordering => true;
1146
1147 void setParentPointers() {}
1008 } 1148 }
1009 1149
1010 /// Creates an instance of a class and initializes its fields and runtime type 1150 /// Creates an instance of a class and initializes its fields and runtime type
1011 /// information. 1151 /// information.
1012 class CreateInstance extends Primitive { 1152 class CreateInstance extends Primitive {
1013 final ClassElement classElement; 1153 final ClassElement classElement;
1014 1154
1015 /// Initial values for the fields on the class. 1155 /// Initial values for the fields on the class.
1016 /// The order corresponds to the order of fields on the class. 1156 /// The order corresponds to the order of fields on the class.
1017 final List<Reference<Primitive>> arguments; 1157 final List<Reference<Primitive>> arguments;
(...skipping 12 matching lines...) Expand all
1030 this.sourceInformation) 1170 this.sourceInformation)
1031 : this.arguments = _referenceList(arguments), 1171 : this.arguments = _referenceList(arguments),
1032 this.typeInformation = _referenceList(typeInformation); 1172 this.typeInformation = _referenceList(typeInformation);
1033 1173
1034 accept(Visitor visitor) => visitor.visitCreateInstance(this); 1174 accept(Visitor visitor) => visitor.visitCreateInstance(this);
1035 1175
1036 bool get isSafeForElimination => true; 1176 bool get isSafeForElimination => true;
1037 bool get isSafeForReordering => true; 1177 bool get isSafeForReordering => true;
1038 1178
1039 toString() => 'CreateInstance($classElement)'; 1179 toString() => 'CreateInstance($classElement)';
1180
1181 void setParentPointers() {
1182 _setParentsOnList(arguments, this);
1183 if (typeInformation != null) _setParentsOnList(typeInformation, this);
1184 }
1040 } 1185 }
1041 1186
1042 class Interceptor extends Primitive { 1187 class Interceptor extends Primitive {
1043 final Reference<Primitive> input; 1188 final Reference<Primitive> input;
1044 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); 1189 final Set<ClassElement> interceptedClasses = new Set<ClassElement>();
1045 final SourceInformation sourceInformation; 1190 final SourceInformation sourceInformation;
1046 1191
1047 /// If non-null, all uses of this the interceptor call are guaranteed to 1192 /// If non-null, all uses of this the interceptor call are guaranteed to
1048 /// see this value. 1193 /// see this value.
1049 /// 1194 ///
1050 /// The interceptor call is not immediately replaced by the constant, because 1195 /// The interceptor call is not immediately replaced by the constant, because
1051 /// that might prevent the interceptor from being shared. 1196 /// that might prevent the interceptor from being shared.
1052 /// 1197 ///
1053 /// The precise input type is not known when sharing interceptors, because 1198 /// The precise input type is not known when sharing interceptors, because
1054 /// refinement nodes have been removed by then. So this field carries the 1199 /// refinement nodes have been removed by then. So this field carries the
1055 /// known constant until we know if it should be shared or replaced by 1200 /// known constant until we know if it should be shared or replaced by
1056 /// the constant. 1201 /// the constant.
1057 values.InterceptorConstantValue constantValue; 1202 values.InterceptorConstantValue constantValue;
1058 1203
1059 Interceptor(Primitive input, this.sourceInformation) 1204 Interceptor(Primitive input, this.sourceInformation)
1060 : this.input = new Reference<Primitive>(input); 1205 : this.input = new Reference<Primitive>(input);
1061 1206
1062 accept(Visitor visitor) => visitor.visitInterceptor(this); 1207 accept(Visitor visitor) => visitor.visitInterceptor(this);
1063 1208
1064 bool get isSafeForElimination => true; 1209 bool get isSafeForElimination => true;
1065 bool get isSafeForReordering => true; 1210 bool get isSafeForReordering => true;
1211
1212 void setParentPointers() {
1213 input.parent = this;
1214 }
1066 } 1215 }
1067 1216
1068 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. 1217 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`.
1069 class CreateInvocationMirror extends Primitive { 1218 class CreateInvocationMirror extends Primitive {
1070 final Selector selector; 1219 final Selector selector;
1071 final List<Reference<Primitive>> arguments; 1220 final List<Reference<Primitive>> arguments;
1072 1221
1073 CreateInvocationMirror(this.selector, List<Primitive> arguments) 1222 CreateInvocationMirror(this.selector, List<Primitive> arguments)
1074 : this.arguments = _referenceList(arguments); 1223 : this.arguments = _referenceList(arguments);
1075 1224
1076 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); 1225 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
1077 1226
1078 bool get isSafeForElimination => true; 1227 bool get isSafeForElimination => true;
1079 bool get isSafeForReordering => true; 1228 bool get isSafeForReordering => true;
1229
1230 void setParentPointers() {
1231 _setParentsOnList(arguments, this);
1232 }
1080 } 1233 }
1081 1234
1082 class ForeignCode extends CallExpression { 1235 class ForeignCode extends CallExpression {
1083 final js.Template codeTemplate; 1236 final js.Template codeTemplate;
1084 final TypeMask type; 1237 final TypeMask type;
1085 final List<Reference<Primitive>> arguments; 1238 final List<Reference<Primitive>> arguments;
1086 final native.NativeBehavior nativeBehavior; 1239 final native.NativeBehavior nativeBehavior;
1087 final FunctionElement dependency; 1240 final FunctionElement dependency;
1088 final Reference<Continuation> continuation; 1241 final Reference<Continuation> continuation;
1089 1242
1090 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, 1243 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
1091 this.nativeBehavior, Continuation continuation, {this.dependency}) 1244 this.nativeBehavior, Continuation continuation, {this.dependency})
1092 : this.arguments = _referenceList(arguments), 1245 : this.arguments = _referenceList(arguments),
1093 this.continuation = new Reference<Continuation>(continuation); 1246 this.continuation = new Reference<Continuation>(continuation);
1094 1247
1095 accept(Visitor visitor) => visitor.visitForeignCode(this); 1248 accept(Visitor visitor) => visitor.visitForeignCode(this);
1249
1250 void setParentPointers() {
1251 _setParentsOnList(arguments, this);
1252 continuation.parent = this;
1253 }
1096 } 1254 }
1097 1255
1098 class Constant extends Primitive { 1256 class Constant extends Primitive {
1099 final values.ConstantValue value; 1257 final values.ConstantValue value;
1100 final SourceInformation sourceInformation; 1258 final SourceInformation sourceInformation;
1101 1259
1102 Constant(this.value, {this.sourceInformation}) { 1260 Constant(this.value, {this.sourceInformation}) {
1103 assert(value != null); 1261 assert(value != null);
1104 } 1262 }
1105 1263
1106 accept(Visitor visitor) => visitor.visitConstant(this); 1264 accept(Visitor visitor) => visitor.visitConstant(this);
1107 1265
1108 bool get isSafeForElimination => true; 1266 bool get isSafeForElimination => true;
1109 bool get isSafeForReordering => true; 1267 bool get isSafeForReordering => true;
1268
1269 void setParentPointers() {}
1110 } 1270 }
1111 1271
1112 class LiteralList extends Primitive { 1272 class LiteralList extends Primitive {
1113 /// The List type being created; this is not the type argument. 1273 /// The List type being created; this is not the type argument.
1114 final InterfaceType dartType; 1274 final InterfaceType dartType;
1115 final List<Reference<Primitive>> values; 1275 final List<Reference<Primitive>> values;
1116 1276
1117 LiteralList(this.dartType, List<Primitive> values) 1277 LiteralList(this.dartType, List<Primitive> values)
1118 : this.values = _referenceList(values); 1278 : this.values = _referenceList(values);
1119 1279
1120 accept(Visitor visitor) => visitor.visitLiteralList(this); 1280 accept(Visitor visitor) => visitor.visitLiteralList(this);
1121 1281
1122 bool get isSafeForElimination => true; 1282 bool get isSafeForElimination => true;
1123 bool get isSafeForReordering => true; 1283 bool get isSafeForReordering => true;
1284
1285 void setParentPointers() {
1286 _setParentsOnList(values, this);
1287 }
1124 } 1288 }
1125 1289
1126 class LiteralMapEntry { 1290 class LiteralMapEntry {
1127 final Reference<Primitive> key; 1291 final Reference<Primitive> key;
1128 final Reference<Primitive> value; 1292 final Reference<Primitive> value;
1129 1293
1130 LiteralMapEntry(Primitive key, Primitive value) 1294 LiteralMapEntry(Primitive key, Primitive value)
1131 : this.key = new Reference<Primitive>(key), 1295 : this.key = new Reference<Primitive>(key),
1132 this.value = new Reference<Primitive>(value); 1296 this.value = new Reference<Primitive>(value);
1133 } 1297 }
1134 1298
1135 class LiteralMap extends Primitive { 1299 class LiteralMap extends Primitive {
1136 final InterfaceType dartType; 1300 final InterfaceType dartType;
1137 final List<LiteralMapEntry> entries; 1301 final List<LiteralMapEntry> entries;
1138 1302
1139 LiteralMap(this.dartType, this.entries); 1303 LiteralMap(this.dartType, this.entries);
1140 1304
1141 accept(Visitor visitor) => visitor.visitLiteralMap(this); 1305 accept(Visitor visitor) => visitor.visitLiteralMap(this);
1142 1306
1143 bool get isSafeForElimination => true; 1307 bool get isSafeForElimination => true;
1144 bool get isSafeForReordering => true; 1308 bool get isSafeForReordering => true;
1309
1310 void setParentPointers() {
1311 for (LiteralMapEntry entry in entries) {
1312 entry.key.parent = this;
1313 entry.value.parent = this;
1314 }
1315 }
1145 } 1316 }
1146 1317
1147 /// Currently unused. 1318 /// Currently unused.
1148 /// 1319 ///
1149 /// Nested functions (from Dart code) are translated to classes by closure 1320 /// Nested functions (from Dart code) are translated to classes by closure
1150 /// conversion, hence they are instantiated with [CreateInstance]. 1321 /// conversion, hence they are instantiated with [CreateInstance].
1151 /// 1322 ///
1152 /// We keep this around for now because it might come in handy when we 1323 /// We keep this around for now because it might come in handy when we
1153 /// handle async/await in the CPS IR. 1324 /// handle async/await in the CPS IR.
1154 /// 1325 ///
1155 /// Instantiates a nested function. [MutableVariable]s are in scope in the 1326 /// Instantiates a nested function. [MutableVariable]s are in scope in the
1156 /// inner function, but primitives are not shared across function boundaries. 1327 /// inner function, but primitives are not shared across function boundaries.
1157 class CreateFunction extends Primitive { 1328 class CreateFunction extends Primitive {
1158 final FunctionDefinition definition; 1329 final FunctionDefinition definition;
1159 1330
1160 CreateFunction(this.definition); 1331 CreateFunction(this.definition);
1161 1332
1162 accept(Visitor visitor) => visitor.visitCreateFunction(this); 1333 accept(Visitor visitor) => visitor.visitCreateFunction(this);
1163 1334
1164 bool get isSafeForElimination => true; 1335 bool get isSafeForElimination => true;
1165 bool get isSafeForReordering => true; 1336 bool get isSafeForReordering => true;
1337
1338 void setParentPointers() {}
1166 } 1339 }
1167 1340
1168 class Parameter extends Primitive { 1341 class Parameter extends Primitive {
1169 Parameter(Entity hint) { 1342 Parameter(Entity hint) {
1170 super.hint = hint; 1343 super.hint = hint;
1171 } 1344 }
1172 1345
1173 // In addition to a parent pointer to the containing Continuation or
1174 // FunctionDefinition, parameters have an index into the list of parameters
1175 // bound by the parent. This gives constant-time access to the continuation
1176 // from the parent.
1177 int parentIndex;
1178
1179 accept(Visitor visitor) => visitor.visitParameter(this); 1346 accept(Visitor visitor) => visitor.visitParameter(this);
1180 1347
1181 String toString() => 'Parameter(${hint == null ? null : hint.name})'; 1348 String toString() => 'Parameter(${hint == null ? null : hint.name})';
1182 1349
1183 bool get isSafeForElimination => true; 1350 bool get isSafeForElimination => true;
1184 bool get isSafeForReordering => true; 1351 bool get isSafeForReordering => true;
1352
1353 void setParentPointers() {}
1185 } 1354 }
1186 1355
1187 /// Continuations are normally bound by 'let cont'. A continuation with one 1356 /// Continuations are normally bound by 'let cont'. A continuation with one
1188 /// parameter and no body is used to represent a function's return continuation. 1357 /// parameter and no body is used to represent a function's return continuation.
1189 /// The return continuation is bound by the function, not by 'let cont'. 1358 /// The return continuation is bound by the function, not by 'let cont'.
1190 class Continuation extends Definition<Continuation> implements InteriorNode { 1359 class Continuation extends Definition<Continuation> implements InteriorNode {
1191 final List<Parameter> parameters; 1360 final List<Parameter> parameters;
1192 Expression body = null; 1361 Expression body = null;
1193 1362
1194 // In addition to a parent pointer to the containing LetCont, continuations
1195 // have an index into the list of continuations bound by the LetCont. This
1196 // gives constant-time access to the continuation from the parent.
1197 int parent_index;
1198
1199 // A continuation is recursive if it has any recursive invocations. 1363 // A continuation is recursive if it has any recursive invocations.
1200 bool isRecursive; 1364 bool isRecursive;
1201 1365
1202 bool get isReturnContinuation => body == null; 1366 bool get isReturnContinuation => body == null;
1203 1367
1204 Continuation(this.parameters, {this.isRecursive: false}); 1368 Continuation(this.parameters, {this.isRecursive: false});
1205 1369
1206 Continuation.retrn() 1370 Continuation.retrn()
1207 : parameters = <Parameter>[new Parameter(null)], 1371 : parameters = <Parameter>[new Parameter(null)],
1208 isRecursive = false; 1372 isRecursive = false;
1209 1373
1210 accept(Visitor visitor) => visitor.visitContinuation(this); 1374 accept(Visitor visitor) => visitor.visitContinuation(this);
1375
1376 void setParentPointers() {
1377 _setParentsOnNodes(parameters, this);
1378 if (body != null) body.parent = this;
1379 }
1211 } 1380 }
1212 1381
1213 /// Common interface for [Primitive] and [MutableVariable]. 1382 /// Common interface for [Primitive] and [MutableVariable].
1214 abstract class Variable<T extends Variable<T>> extends Definition<T> { 1383 abstract class Variable<T extends Variable<T>> extends Definition<T> {
1215 /// Type of value held in the variable. 1384 /// Type of value held in the variable.
1216 /// 1385 ///
1217 /// Is `null` until initialized by type propagation. 1386 /// Is `null` until initialized by type propagation.
1218 TypeMask type; 1387 TypeMask type;
1219 } 1388 }
1220 1389
1221 /// Identifies a mutable variable. 1390 /// Identifies a mutable variable.
1222 class MutableVariable extends Variable<MutableVariable> { 1391 class MutableVariable extends Variable<MutableVariable> {
1223 Entity hint; 1392 Entity hint;
1224 1393
1225 MutableVariable(this.hint); 1394 MutableVariable(this.hint);
1226 1395
1227 accept(Visitor v) => v.visitMutableVariable(this); 1396 accept(Visitor v) => v.visitMutableVariable(this);
1397
1398 void setParentPointers() {}
1228 } 1399 }
1229 1400
1230 /// A function definition, consisting of parameters and a body. 1401 /// A function definition, consisting of parameters and a body.
1231 /// 1402 ///
1232 /// There is an explicit parameter for the `this` argument, and a return 1403 /// There is an explicit parameter for the `this` argument, and a return
1233 /// continuation to invoke when returning from the function. 1404 /// continuation to invoke when returning from the function.
1234 class FunctionDefinition extends InteriorNode { 1405 class FunctionDefinition extends InteriorNode {
1235 final ExecutableElement element; 1406 final ExecutableElement element;
1236 final Parameter thisParameter; 1407 final Parameter thisParameter;
1237 final List<Parameter> parameters; 1408 final List<Parameter> parameters;
1238 final Continuation returnContinuation; 1409 final Continuation returnContinuation;
1239 Expression body; 1410 Expression body;
1240 1411
1241 FunctionDefinition(this.element, 1412 FunctionDefinition(this.element,
1242 this.thisParameter, 1413 this.thisParameter,
1243 this.parameters, 1414 this.parameters,
1244 this.returnContinuation, 1415 this.returnContinuation,
1245 this.body); 1416 this.body);
1246 1417
1247 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); 1418 accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
1419
1420 void setParentPointers() {
1421 if (thisParameter != null) thisParameter.parent = this;
1422 _setParentsOnNodes(parameters, this);
1423 returnContinuation.parent = this;
1424 if (body != null) body.parent = this;
1425 }
1248 } 1426 }
1249 1427
1250 /// Converts the internal representation of a type to a Dart object of type 1428 /// Converts the internal representation of a type to a Dart object of type
1251 /// [Type]. 1429 /// [Type].
1252 class ReifyRuntimeType extends Primitive { 1430 class ReifyRuntimeType extends Primitive {
1253 /// Reference to the internal representation of a type (as produced, for 1431 /// Reference to the internal representation of a type (as produced, for
1254 /// example, by [ReadTypeVariable]). 1432 /// example, by [ReadTypeVariable]).
1255 final Reference<Primitive> value; 1433 final Reference<Primitive> value;
1256 1434
1257 final SourceInformation sourceInformation; 1435 final SourceInformation sourceInformation;
1258 1436
1259 ReifyRuntimeType(Primitive value, this.sourceInformation) 1437 ReifyRuntimeType(Primitive value, this.sourceInformation)
1260 : this.value = new Reference<Primitive>(value); 1438 : this.value = new Reference<Primitive>(value);
1261 1439
1262 @override 1440 @override
1263 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); 1441 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this);
1264 1442
1265 bool get isSafeForElimination => true; 1443 bool get isSafeForElimination => true;
1266 bool get isSafeForReordering => true; 1444 bool get isSafeForReordering => true;
1445
1446 void setParentPointers() {
1447 value.parent = this;
1448 }
1267 } 1449 }
1268 1450
1269 /// Read the value the type variable [variable] from the target object. 1451 /// Read the value the type variable [variable] from the target object.
1270 /// 1452 ///
1271 /// The resulting value is an internal representation (and not neccessarily a 1453 /// The resulting value is an internal representation (and not neccessarily a
1272 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be 1454 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be
1273 /// used as a Dart value. 1455 /// used as a Dart value.
1274 class ReadTypeVariable extends Primitive { 1456 class ReadTypeVariable extends Primitive {
1275 final TypeVariableType variable; 1457 final TypeVariableType variable;
1276 final Reference<Primitive> target; 1458 final Reference<Primitive> target;
1277 final SourceInformation sourceInformation; 1459 final SourceInformation sourceInformation;
1278 1460
1279 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) 1461 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation)
1280 : this.target = new Reference<Primitive>(target); 1462 : this.target = new Reference<Primitive>(target);
1281 1463
1282 @override 1464 @override
1283 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); 1465 accept(Visitor visitor) => visitor.visitReadTypeVariable(this);
1284 1466
1285 bool get isSafeForElimination => true; 1467 bool get isSafeForElimination => true;
1286 bool get isSafeForReordering => true; 1468 bool get isSafeForReordering => true;
1469
1470 void setParentPointers() {
1471 target.parent = this;
1472 }
1287 } 1473 }
1288 1474
1289 /// Representation of a closed type (that is, a type without type variables). 1475 /// Representation of a closed type (that is, a type without type variables).
1290 /// 1476 ///
1291 /// The resulting value is constructed from [dartType] by replacing the type 1477 /// The resulting value is constructed from [dartType] by replacing the type
1292 /// variables with consecutive values from [arguments], in the order generated 1478 /// variables with consecutive values from [arguments], in the order generated
1293 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are 1479 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are
1294 /// treated as 'holes' in the term, which means that it must be ensured at 1480 /// treated as 'holes' in the term, which means that it must be ensured at
1295 /// construction, that duplicate occurences of a type variable in [dartType] 1481 /// construction, that duplicate occurences of a type variable in [dartType]
1296 /// are assigned the same value. 1482 /// are assigned the same value.
1297 class TypeExpression extends Primitive { 1483 class TypeExpression extends Primitive {
1298 final DartType dartType; 1484 final DartType dartType;
1299 final List<Reference<Primitive>> arguments; 1485 final List<Reference<Primitive>> arguments;
1300 1486
1301 TypeExpression(this.dartType, 1487 TypeExpression(this.dartType,
1302 [List<Primitive> arguments = const <Primitive>[]]) 1488 [List<Primitive> arguments = const <Primitive>[]])
1303 : this.arguments = _referenceList(arguments); 1489 : this.arguments = _referenceList(arguments);
1304 1490
1305 @override 1491 @override
1306 accept(Visitor visitor) { 1492 accept(Visitor visitor) {
1307 return visitor.visitTypeExpression(this); 1493 return visitor.visitTypeExpression(this);
1308 } 1494 }
1309 1495
1310 bool get isSafeForElimination => true; 1496 bool get isSafeForElimination => true;
1311 bool get isSafeForReordering => true; 1497 bool get isSafeForReordering => true;
1498
1499 void setParentPointers() {
1500 _setParentsOnList(arguments, this);
1501 }
1312 } 1502 }
1313 1503
1314 class Await extends CallExpression { 1504 class Await extends CallExpression {
1315 final Reference<Primitive> input; 1505 final Reference<Primitive> input;
1316 final Reference<Continuation> continuation; 1506 final Reference<Continuation> continuation;
1317 1507
1318 Await(Primitive input, Continuation continuation) 1508 Await(Primitive input, Continuation continuation)
1319 : this.input = new Reference<Primitive>(input), 1509 : this.input = new Reference<Primitive>(input),
1320 this.continuation = new Reference<Continuation>(continuation); 1510 this.continuation = new Reference<Continuation>(continuation);
1321 1511
1322 @override 1512 @override
1323 accept(Visitor visitor) { 1513 accept(Visitor visitor) {
1324 return visitor.visitAwait(this); 1514 return visitor.visitAwait(this);
1325 } 1515 }
1516
1517 void setParentPointers() {
1518 input.parent = this;
1519 continuation.parent = this;
1520 }
1326 } 1521 }
1327 1522
1328 class Yield extends CallExpression { 1523 class Yield extends CallExpression {
1329 final Reference<Primitive> input; 1524 final Reference<Primitive> input;
1330 final Reference<Continuation> continuation; 1525 final Reference<Continuation> continuation;
1331 final bool hasStar; 1526 final bool hasStar;
1332 1527
1333 Yield(Primitive input, this.hasStar, Continuation continuation) 1528 Yield(Primitive input, this.hasStar, Continuation continuation)
1334 : this.input = new Reference<Primitive>(input), 1529 : this.input = new Reference<Primitive>(input),
1335 this.continuation = new Reference<Continuation>(continuation); 1530 this.continuation = new Reference<Continuation>(continuation);
1336 1531
1337 @override 1532 @override
1338 accept(Visitor visitor) { 1533 accept(Visitor visitor) {
1339 return visitor.visitYield(this); 1534 return visitor.visitYield(this);
1340 } 1535 }
1536
1537 void setParentPointers() {
1538 input.parent = this;
1539 continuation.parent = this;
1540 }
1341 } 1541 }
1342 1542
1343 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { 1543 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
1344 return definitions.map((e) => new Reference<Primitive>(e)).toList(); 1544 return definitions.map((e) => new Reference<Primitive>(e)).toList();
1345 } 1545 }
1346 1546
1547 void _setParentsOnNodes(List<Node> nodes, Node parent) {
1548 for (Node node in nodes) {
1549 node.parent = parent;
1550 }
1551 }
1552
1553 void _setParentsOnList(List<Reference> nodes, Node parent) {
1554 for (Reference node in nodes) {
1555 node.parent = parent;
1556 }
1557 }
1558
1347 abstract class Visitor<T> { 1559 abstract class Visitor<T> {
1348 const Visitor(); 1560 const Visitor();
1349 1561
1350 T visit(Node node); 1562 T visit(Node node);
1351 1563
1352 // Concrete classes. 1564 // Concrete classes.
1353 T visitFunctionDefinition(FunctionDefinition node); 1565 T visitFunctionDefinition(FunctionDefinition node);
1354 1566
1355 // Expressions. 1567 // Expressions.
1356 T visitLetPrim(LetPrim node); 1568 T visitLetPrim(LetPrim node);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1398 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); 1610 T visitApplyBuiltinMethod(ApplyBuiltinMethod node);
1399 T visitGetLength(GetLength node); 1611 T visitGetLength(GetLength node);
1400 T visitGetIndex(GetIndex node); 1612 T visitGetIndex(GetIndex node);
1401 T visitSetIndex(SetIndex node); 1613 T visitSetIndex(SetIndex node);
1402 T visitRefinement(Refinement node); 1614 T visitRefinement(Refinement node);
1403 1615
1404 // Support for literal foreign code. 1616 // Support for literal foreign code.
1405 T visitForeignCode(ForeignCode node); 1617 T visitForeignCode(ForeignCode node);
1406 } 1618 }
1407 1619
1408 /// Visits all non-recursive children of a CPS term, i.e. anything 1620 /// Recursively visits all children of a CPS term.
1409 /// not of type [Expression] or [Continuation]. 1621 ///
1622 /// The user of the class is responsible for avoiding stack overflows from
1623 /// deep recursion, e.g. by overriding methods to cut off recursion at certain
1624 /// points.
1625 ///
1626 /// All recursive invocations occur through the [visit] method, which the
1627 /// subclass may override as a generic way to control the visitor without
1628 /// overriding all visitor methods.
1410 /// 1629 ///
1411 /// The `process*` methods are called in pre-order for every node visited. 1630 /// The `process*` methods are called in pre-order for every node visited.
1412 /// These can be overridden without disrupting the visitor traversal. 1631 /// These can be overridden without disrupting the visitor traversal.
1413 class LeafVisitor implements Visitor { 1632 class DeepRecursiveVisitor implements Visitor {
1414 const LeafVisitor(); 1633 const DeepRecursiveVisitor();
1415 1634
1416 visit(Node node) => node.accept(this); 1635 visit(Node node) => node.accept(this);
1417 1636
1418 processReference(Reference ref) {} 1637 processReference(Reference ref) {}
1419 1638
1420 processFunctionDefinition(FunctionDefinition node) {} 1639 processFunctionDefinition(FunctionDefinition node) {}
1421 visitFunctionDefinition(FunctionDefinition node) { 1640 visitFunctionDefinition(FunctionDefinition node) {
1422 processFunctionDefinition(node); 1641 processFunctionDefinition(node);
1423 if (node.thisParameter != null) visit(node.thisParameter); 1642 if (node.thisParameter != null) visit(node.thisParameter);
1424 node.parameters.forEach(visit); 1643 node.parameters.forEach(visit);
1425 visit(node.returnContinuation); 1644 visit(node.returnContinuation);
1645 visit(node.body);
1646 }
1647
1648 processContinuation(Continuation node) {}
1649 visitContinuation(Continuation node) {
1650 processContinuation(node);
1651 node.parameters.forEach(visit);
1652 if (node.body != null) visit(node.body);
1426 } 1653 }
1427 1654
1428 // Expressions. 1655 // Expressions.
1429
1430 processLetPrim(LetPrim node) {} 1656 processLetPrim(LetPrim node) {}
1431 visitLetPrim(LetPrim node) { 1657 visitLetPrim(LetPrim node) {
1432 processLetPrim(node); 1658 processLetPrim(node);
1433 visit(node.primitive); 1659 visit(node.primitive);
1660 visit(node.body);
1434 } 1661 }
1435 1662
1436 processLetCont(LetCont node) {} 1663 processLetCont(LetCont node) {}
1437 visitLetCont(LetCont node) { 1664 visitLetCont(LetCont node) {
1438 processLetCont(node); 1665 processLetCont(node);
1439 node.continuations.forEach(visit); 1666 node.continuations.forEach(visit);
1667 visit(node.body);
1440 } 1668 }
1441 1669
1442 processLetHandler(LetHandler node) {} 1670 processLetHandler(LetHandler node) {}
1443 visitLetHandler(LetHandler node) { 1671 visitLetHandler(LetHandler node) {
1444 processLetHandler(node); 1672 processLetHandler(node);
1673 visit(node.handler);
1674 visit(node.body);
1445 } 1675 }
1446 1676
1447 processLetMutable(LetMutable node) {} 1677 processLetMutable(LetMutable node) {}
1448 visitLetMutable(LetMutable node) { 1678 visitLetMutable(LetMutable node) {
1449 processLetMutable(node); 1679 processLetMutable(node);
1450 visit(node.variable); 1680 visit(node.variable);
1451 processReference(node.value); 1681 processReference(node.value);
1682 visit(node.body);
1452 } 1683 }
1453 1684
1454 processInvokeStatic(InvokeStatic node) {} 1685 processInvokeStatic(InvokeStatic node) {}
1455 visitInvokeStatic(InvokeStatic node) { 1686 visitInvokeStatic(InvokeStatic node) {
1456 processInvokeStatic(node); 1687 processInvokeStatic(node);
1457 processReference(node.continuation); 1688 processReference(node.continuation);
1458 node.arguments.forEach(processReference); 1689 node.arguments.forEach(processReference);
1459 } 1690 }
1460 1691
1461 processInvokeContinuation(InvokeContinuation node) {} 1692 processInvokeContinuation(InvokeContinuation node) {}
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1577 visitGetMutable(GetMutable node) { 1808 visitGetMutable(GetMutable node) {
1578 processGetMutable(node); 1809 processGetMutable(node);
1579 processReference(node.variable); 1810 processReference(node.variable);
1580 } 1811 }
1581 1812
1582 processParameter(Parameter node) {} 1813 processParameter(Parameter node) {}
1583 visitParameter(Parameter node) { 1814 visitParameter(Parameter node) {
1584 processParameter(node); 1815 processParameter(node);
1585 } 1816 }
1586 1817
1587 processContinuation(Continuation node) {}
1588 visitContinuation(Continuation node) {
1589 processContinuation(node);
1590 node.parameters.forEach(visitParameter);
1591 }
1592
1593 processInterceptor(Interceptor node) {} 1818 processInterceptor(Interceptor node) {}
1594 visitInterceptor(Interceptor node) { 1819 visitInterceptor(Interceptor node) {
1595 processInterceptor(node); 1820 processInterceptor(node);
1596 processReference(node.input); 1821 processReference(node.input);
1597 } 1822 }
1598 1823
1599 processCreateInstance(CreateInstance node) {} 1824 processCreateInstance(CreateInstance node) {}
1600 visitCreateInstance(CreateInstance node) { 1825 visitCreateInstance(CreateInstance node) {
1601 processCreateInstance(node); 1826 processCreateInstance(node);
1602 node.arguments.forEach(processReference); 1827 node.arguments.forEach(processReference);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 /// The `traverse*` methods return the expression to visit next, and may 1968 /// The `traverse*` methods return the expression to visit next, and may
1744 /// push other subterms onto the stack using [push] or [pushAction] to visit 1969 /// push other subterms onto the stack using [push] or [pushAction] to visit
1745 /// them later. Actions pushed onto the stack will be executed after the body 1970 /// them later. Actions pushed onto the stack will be executed after the body
1746 /// has been processed (and the stack actions it pushed have been executed). 1971 /// has been processed (and the stack actions it pushed have been executed).
1747 /// 1972 ///
1748 /// By default, the `traverse` methods visit all non-recursive subterms, 1973 /// By default, the `traverse` methods visit all non-recursive subterms,
1749 /// push all bound continuations on the stack, and return the body of the term. 1974 /// push all bound continuations on the stack, and return the body of the term.
1750 /// 1975 ///
1751 /// Subclasses should not override the `visit` methods for the nodes that have 1976 /// Subclasses should not override the `visit` methods for the nodes that have
1752 /// a `traverse` method. 1977 /// a `traverse` method.
1753 class RecursiveVisitor extends LeafVisitor { 1978 class TrampolineRecursiveVisitor extends DeepRecursiveVisitor {
1754 List<StackAction> _stack = <StackAction>[]; 1979 List<StackAction> _stack = <StackAction>[];
1755 1980
1756 void pushAction(StackAction callback) { 1981 void pushAction(StackAction callback) {
1757 _stack.add(callback); 1982 _stack.add(callback);
1758 } 1983 }
1759 1984
1760 void push(Continuation cont) { 1985 void push(Continuation cont) {
1761 _stack.add(() { 1986 _stack.add(() {
1762 if (cont.isReturnContinuation) { 1987 if (cont.isReturnContinuation) {
1763 traverseContinuation(cont); 1988 traverseContinuation(cont);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1838 node = traverseLetPrim(node); 2063 node = traverseLetPrim(node);
1839 } else { 2064 } else {
1840 node = traverseLetMutable(node); 2065 node = traverseLetMutable(node);
1841 } 2066 }
1842 } 2067 }
1843 visit(node); 2068 visit(node);
1844 } 2069 }
1845 } 2070 }
1846 2071
1847 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 2072 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
1848 class RemovalVisitor extends RecursiveVisitor { 2073 class RemovalVisitor extends TrampolineRecursiveVisitor {
1849 processReference(Reference reference) { 2074 processReference(Reference reference) {
1850 reference.unlink(); 2075 reference.unlink();
1851 } 2076 }
1852 2077
1853 static void remove(Node node) { 2078 static void remove(Node node) {
1854 (new RemovalVisitor()).visit(node); 2079 (new RemovalVisitor()).visit(node);
1855 } 2080 }
1856 } 2081 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart ('k') | pkg/compiler/lib/src/cps_ir/insert_refinements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698