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

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: Fix 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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 /// The bound value is in scope in the body. 314 /// The bound value is in scope in the body.
306 /// 315 ///
307 /// During one-pass construction a LetPrim with an empty body is used to 316 /// During one-pass construction a LetPrim with an empty body is used to
308 /// represent the one-hole context `let val x = V in []`. 317 /// represent the one-hole context `let val x = V in []`.
309 class LetPrim extends InteriorExpression { 318 class LetPrim extends InteriorExpression {
310 Primitive primitive; 319 Primitive primitive;
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) {
Kevin Millikin (Google) 2015/10/05 12:04:37 It seems better to also set the parent pointer her
asgerf 2015/10/12 13:18:31 There are too many explicit setter calls in the bu
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 16 matching lines...) Expand all
605 TypeTest(Primitive value, 660 TypeTest(Primitive value,
606 this.dartType, 661 this.dartType,
607 List<Primitive> typeArguments) 662 List<Primitive> typeArguments)
608 : this.value = new Reference<Primitive>(value), 663 : this.value = new Reference<Primitive>(value),
609 this.typeArguments = _referenceList(typeArguments); 664 this.typeArguments = _referenceList(typeArguments);
610 665
611 accept(Visitor visitor) => visitor.visitTypeTest(this); 666 accept(Visitor visitor) => visitor.visitTypeTest(this);
612 667
613 bool get isSafeForElimination => true; 668 bool get isSafeForElimination => true;
614 bool get isSafeForReordering => true; 669 bool get isSafeForReordering => true;
670
671 void setParentPointers() {
672 value.parent = this;
673 _setParentsOnList(typeArguments, this);
674 }
615 } 675 }
616 676
617 /// An "as" type cast. 677 /// An "as" type cast.
618 /// 678 ///
619 /// If [value] is `null` or is an instance of [type], [continuation] is invoked 679 /// If [value] is `null` or is an instance of [type], [continuation] is invoked
620 /// with [value] as argument. Otherwise, a [CastError] is thrown. 680 /// with [value] as argument. Otherwise, a [CastError] is thrown.
621 /// 681 ///
622 /// Discussion: 682 /// Discussion:
623 /// The parameter to [continuation] is redundant since it will always equal 683 /// The parameter to [continuation] is redundant since it will always equal
624 /// [value], which is typically in scope in the continuation. However, it might 684 /// [value], which is typically in scope in the continuation. However, it might
625 /// simplify type propagation, since a better type can be computed for the 685 /// simplify type propagation, since a better type can be computed for the
626 /// continuation parameter without needing flow-sensitive analysis. 686 /// continuation parameter without needing flow-sensitive analysis.
627 class TypeCast extends CallExpression { 687 class TypeCast extends CallExpression {
628 Reference<Primitive> value; 688 Reference<Primitive> value;
629 final DartType dartType; 689 final DartType dartType;
630 690
631 /// See the corresponding field on [TypeTest]. 691 /// See the corresponding field on [TypeTest].
632 final List<Reference<Primitive>> typeArguments; 692 final List<Reference<Primitive>> typeArguments;
633 final Reference<Continuation> continuation; 693 final Reference<Continuation> continuation;
634 694
635 TypeCast(Primitive value, 695 TypeCast(Primitive value,
636 this.dartType, 696 this.dartType,
637 List<Primitive> typeArguments, 697 List<Primitive> typeArguments,
638 Continuation cont) 698 Continuation cont)
639 : this.value = new Reference<Primitive>(value), 699 : this.value = new Reference<Primitive>(value),
640 this.typeArguments = _referenceList(typeArguments), 700 this.typeArguments = _referenceList(typeArguments),
641 this.continuation = new Reference<Continuation>(cont); 701 this.continuation = new Reference<Continuation>(cont);
642 702
643 accept(Visitor visitor) => visitor.visitTypeCast(this); 703 accept(Visitor visitor) => visitor.visitTypeCast(this);
704
705 void setParentPointers() {
706 value.parent = this;
707 }
644 } 708 }
645 709
646 /// Apply a built-in operator. 710 /// Apply a built-in operator.
647 /// 711 ///
648 /// It must be known that the arguments have the proper types. 712 /// It must be known that the arguments have the proper types.
649 class ApplyBuiltinOperator extends Primitive { 713 class ApplyBuiltinOperator extends Primitive {
650 BuiltinOperator operator; 714 BuiltinOperator operator;
651 List<Reference<Primitive>> arguments; 715 List<Reference<Primitive>> arguments;
652 final SourceInformation sourceInformation; 716 final SourceInformation sourceInformation;
653 717
654 ApplyBuiltinOperator(this.operator, 718 ApplyBuiltinOperator(this.operator,
655 List<Primitive> arguments, 719 List<Primitive> arguments,
656 this.sourceInformation) 720 this.sourceInformation)
657 : this.arguments = _referenceList(arguments); 721 : this.arguments = _referenceList(arguments);
658 722
659 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this); 723 accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);
660 724
661 bool get isSafeForElimination => true; 725 bool get isSafeForElimination => true;
662 bool get isSafeForReordering => true; 726 bool get isSafeForReordering => true;
727
728 void setParentPointers() {
729 _setParentsOnList(arguments, this);
730 }
663 } 731 }
664 732
665 /// Apply a built-in method. 733 /// Apply a built-in method.
666 /// 734 ///
667 /// It must be known that the arguments have the proper types. 735 /// It must be known that the arguments have the proper types.
668 class ApplyBuiltinMethod extends Primitive { 736 class ApplyBuiltinMethod extends Primitive {
669 BuiltinMethod method; 737 BuiltinMethod method;
670 Reference<Primitive> receiver; 738 Reference<Primitive> receiver;
671 List<Reference<Primitive>> arguments; 739 List<Reference<Primitive>> arguments;
672 final SourceInformation sourceInformation; 740 final SourceInformation sourceInformation;
673 741
674 bool receiverIsNotNull; 742 bool receiverIsNotNull;
675 743
676 ApplyBuiltinMethod(this.method, 744 ApplyBuiltinMethod(this.method,
677 Primitive receiver, 745 Primitive receiver,
678 List<Primitive> arguments, 746 List<Primitive> arguments,
679 this.sourceInformation, 747 this.sourceInformation,
680 {this.receiverIsNotNull: false}) 748 {this.receiverIsNotNull: false})
681 : this.receiver = new Reference<Primitive>(receiver), 749 : this.receiver = new Reference<Primitive>(receiver),
682 this.arguments = _referenceList(arguments); 750 this.arguments = _referenceList(arguments);
683 751
684 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this); 752 accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this);
685 753
686 bool get isSafeForElimination => false; 754 bool get isSafeForElimination => false;
687 bool get isSafeForReordering => false; 755 bool get isSafeForReordering => false;
756
757 void setParentPointers() {
758 receiver.parent = this;
759 _setParentsOnList(arguments, this);
760 }
688 } 761 }
689 762
690 /// Throw a value. 763 /// Throw a value.
691 /// 764 ///
692 /// Throw is an expression, i.e., it always occurs in tail position with 765 /// Throw is an expression, i.e., it always occurs in tail position with
693 /// respect to a body or expression. 766 /// respect to a body or expression.
694 class Throw extends TailExpression { 767 class Throw extends TailExpression {
695 Reference<Primitive> value; 768 Reference<Primitive> value;
696 769
697 Throw(Primitive value) : value = new Reference<Primitive>(value); 770 Throw(Primitive value) : value = new Reference<Primitive>(value);
698 771
699 accept(Visitor visitor) => visitor.visitThrow(this); 772 accept(Visitor visitor) => visitor.visitThrow(this);
773
774 void setParentPointers() {
775 value.parent = this;
776 }
700 } 777 }
701 778
702 /// Rethrow 779 /// Rethrow
703 /// 780 ///
704 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It 781 /// Rethrow can only occur inside a continuation bound by [LetHandler]. It
705 /// implicitly throws the exception parameter of the enclosing handler with 782 /// implicitly throws the exception parameter of the enclosing handler with
706 /// the same stack trace as the enclosing handler. 783 /// the same stack trace as the enclosing handler.
707 class Rethrow extends TailExpression { 784 class Rethrow extends TailExpression {
708 accept(Visitor visitor) => visitor.visitRethrow(this); 785 accept(Visitor visitor) => visitor.visitRethrow(this);
786 void setParentPointers() {}
709 } 787 }
710 788
711 /// An expression that is known to be unreachable. 789 /// An expression that is known to be unreachable.
712 /// 790 ///
713 /// This can be placed as the body of a call continuation, when the caller is 791 /// This can be placed as the body of a call continuation, when the caller is
714 /// known never to invoke it, e.g. because the calling expression always throws. 792 /// known never to invoke it, e.g. because the calling expression always throws.
715 class Unreachable extends TailExpression { 793 class Unreachable extends TailExpression {
716 accept(Visitor visitor) => visitor.visitUnreachable(this); 794 accept(Visitor visitor) => visitor.visitUnreachable(this);
795 void setParentPointers() {}
717 } 796 }
718 797
719 /// Gets the value from a [MutableVariable]. 798 /// Gets the value from a [MutableVariable].
720 /// 799 ///
721 /// [MutableVariable]s can be seen as ref cells that are not first-class 800 /// [MutableVariable]s can be seen as ref cells that are not first-class
722 /// values. A [LetPrim] with a [GetMutable] can then be seen as: 801 /// values. A [LetPrim] with a [GetMutable] can then be seen as:
723 /// 802 ///
724 /// let prim p = ![variable] in [body] 803 /// let prim p = ![variable] in [body]
725 /// 804 ///
726 class GetMutable extends Primitive { 805 class GetMutable extends Primitive {
727 final Reference<MutableVariable> variable; 806 final Reference<MutableVariable> variable;
728 807
729 GetMutable(MutableVariable variable) 808 GetMutable(MutableVariable variable)
730 : this.variable = new Reference<MutableVariable>(variable); 809 : this.variable = new Reference<MutableVariable>(variable);
731 810
732 accept(Visitor visitor) => visitor.visitGetMutable(this); 811 accept(Visitor visitor) => visitor.visitGetMutable(this);
733 812
734 bool get isSafeForElimination => true; 813 bool get isSafeForElimination => true;
735 bool get isSafeForReordering => false; 814 bool get isSafeForReordering => false;
815
816 void setParentPointers() {
817 variable.parent = this;
818 }
736 } 819 }
737 820
738 /// Assign a [MutableVariable]. 821 /// Assign a [MutableVariable].
739 /// 822 ///
740 /// [MutableVariable]s can be seen as ref cells that are not first-class 823 /// [MutableVariable]s can be seen as ref cells that are not first-class
741 /// values. This can be seen as a dereferencing assignment: 824 /// values. This can be seen as a dereferencing assignment:
742 /// 825 ///
743 /// { [variable] := [value]; [body] } 826 /// { [variable] := [value]; [body] }
744 class SetMutable extends Primitive { 827 class SetMutable extends Primitive {
745 final Reference<MutableVariable> variable; 828 final Reference<MutableVariable> variable;
746 final Reference<Primitive> value; 829 final Reference<Primitive> value;
747 830
748 SetMutable(MutableVariable variable, Primitive value) 831 SetMutable(MutableVariable variable, Primitive value)
749 : this.variable = new Reference<MutableVariable>(variable), 832 : this.variable = new Reference<MutableVariable>(variable),
750 this.value = new Reference<Primitive>(value); 833 this.value = new Reference<Primitive>(value);
751 834
752 accept(Visitor visitor) => visitor.visitSetMutable(this); 835 accept(Visitor visitor) => visitor.visitSetMutable(this);
753 836
754 bool get isSafeForElimination => false; 837 bool get isSafeForElimination => false;
755 bool get isSafeForReordering => false; 838 bool get isSafeForReordering => false;
839
840 void setParentPointers() {
841 variable.parent = this;
842 value.parent = this;
843 }
756 } 844 }
757 845
758 /// Invoke a continuation in tail position. 846 /// Invoke a continuation in tail position.
759 class InvokeContinuation extends TailExpression { 847 class InvokeContinuation extends TailExpression {
760 Reference<Continuation> continuation; 848 Reference<Continuation> continuation;
761 List<Reference<Primitive>> arguments; 849 List<Reference<Primitive>> arguments;
762 SourceInformation sourceInformation; 850 SourceInformation sourceInformation;
763 851
764 // An invocation of a continuation is recursive if it occurs in the body of 852 // An invocation of a continuation is recursive if it occurs in the body of
765 // the continuation itself. 853 // the continuation itself.
(...skipping 18 matching lines...) Expand all
784 /// 872 ///
785 /// Used as a placeholder for a jump whose target is not yet created 873 /// Used as a placeholder for a jump whose target is not yet created
786 /// (e.g., in the translation of break and continue). 874 /// (e.g., in the translation of break and continue).
787 InvokeContinuation.uninitialized({this.isRecursive: false, 875 InvokeContinuation.uninitialized({this.isRecursive: false,
788 this.isEscapingTry: false}) 876 this.isEscapingTry: false})
789 : continuation = null, 877 : continuation = null,
790 arguments = null, 878 arguments = null,
791 sourceInformation = null; 879 sourceInformation = null;
792 880
793 accept(Visitor visitor) => visitor.visitInvokeContinuation(this); 881 accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
882
883 void setParentPointers() {
884 if (continuation != null) continuation.parent = this;
885 if (arguments != null) _setParentsOnList(arguments, this);
886 }
794 } 887 }
795 888
796 /// Choose between a pair of continuations based on a condition value. 889 /// Choose between a pair of continuations based on a condition value.
797 /// 890 ///
798 /// The two continuations must not declare any parameters. 891 /// The two continuations must not declare any parameters.
799 class Branch extends TailExpression { 892 class Branch extends TailExpression {
800 final Reference<Primitive> condition; 893 final Reference<Primitive> condition;
801 final Reference<Continuation> trueContinuation; 894 final Reference<Continuation> trueContinuation;
802 final Reference<Continuation> falseContinuation; 895 final Reference<Continuation> falseContinuation;
803 896
(...skipping 14 matching lines...) Expand all
818 911
819 Branch.loose(Primitive condition, 912 Branch.loose(Primitive condition,
820 Continuation trueCont, 913 Continuation trueCont,
821 Continuation falseCont) 914 Continuation falseCont)
822 : this.condition = new Reference<Primitive>(condition), 915 : this.condition = new Reference<Primitive>(condition),
823 trueContinuation = new Reference<Continuation>(trueCont), 916 trueContinuation = new Reference<Continuation>(trueCont),
824 falseContinuation = new Reference<Continuation>(falseCont), 917 falseContinuation = new Reference<Continuation>(falseCont),
825 this.isStrictCheck = false; 918 this.isStrictCheck = false;
826 919
827 accept(Visitor visitor) => visitor.visitBranch(this); 920 accept(Visitor visitor) => visitor.visitBranch(this);
921
922 void setParentPointers() {
923 condition.parent = this;
924 trueContinuation.parent = this;
925 falseContinuation.parent = this;
926 }
828 } 927 }
829 928
830 /// Directly assigns to a field on a given object. 929 /// Directly assigns to a field on a given object.
831 class SetField extends Primitive { 930 class SetField extends Primitive {
832 final Reference<Primitive> object; 931 final Reference<Primitive> object;
833 FieldElement field; 932 FieldElement field;
834 final Reference<Primitive> value; 933 final Reference<Primitive> value;
835 934
836 SetField(Primitive object, this.field, Primitive value) 935 SetField(Primitive object, this.field, Primitive value)
837 : this.object = new Reference<Primitive>(object), 936 : this.object = new Reference<Primitive>(object),
838 this.value = new Reference<Primitive>(value); 937 this.value = new Reference<Primitive>(value);
839 938
840 accept(Visitor visitor) => visitor.visitSetField(this); 939 accept(Visitor visitor) => visitor.visitSetField(this);
841 940
842 bool get isSafeForElimination => false; 941 bool get isSafeForElimination => false;
843 bool get isSafeForReordering => false; 942 bool get isSafeForReordering => false;
943
944 void setParentPointers() {
945 object.parent = this;
946 value.parent = this;
947 }
844 } 948 }
845 949
846 /// Directly reads from a field on a given object. 950 /// Directly reads from a field on a given object.
847 /// 951 ///
848 /// The [object] must either be `null` or an object that has [field]. 952 /// The [object] must either be `null` or an object that has [field].
849 class GetField extends Primitive { 953 class GetField extends Primitive {
850 final Reference<Primitive> object; 954 final Reference<Primitive> object;
851 FieldElement field; 955 FieldElement field;
852 956
853 /// True if the object is known not to be null. 957 /// True if the object is known not to be null.
854 // TODO(asgerf): This is a placeholder until we agree on how to track 958 // TODO(asgerf): This is a placeholder until we agree on how to track
855 // side effects. 959 // side effects.
856 bool objectIsNotNull = false; 960 bool objectIsNotNull = false;
857 961
858 GetField(Primitive object, this.field) 962 GetField(Primitive object, this.field)
859 : this.object = new Reference<Primitive>(object); 963 : this.object = new Reference<Primitive>(object);
860 964
861 accept(Visitor visitor) => visitor.visitGetField(this); 965 accept(Visitor visitor) => visitor.visitGetField(this);
862 966
863 bool get isSafeForElimination => objectIsNotNull; 967 bool get isSafeForElimination => objectIsNotNull;
864 bool get isSafeForReordering => false; 968 bool get isSafeForReordering => false;
865 969
866 toString() => 'GetField($field)'; 970 toString() => 'GetField($field)';
971
972 void setParentPointers() {
973 object.parent = this;
974 }
867 } 975 }
868 976
869 /// Get the length of a string or native list. 977 /// Get the length of a string or native list.
870 class GetLength extends Primitive { 978 class GetLength extends Primitive {
871 final Reference<Primitive> object; 979 final Reference<Primitive> object;
872 980
873 /// True if the object is known not to be null. 981 /// True if the object is known not to be null.
874 bool objectIsNotNull = false; 982 bool objectIsNotNull = false;
875 983
876 GetLength(Primitive object) : this.object = new Reference<Primitive>(object); 984 GetLength(Primitive object) : this.object = new Reference<Primitive>(object);
877 985
878 bool get isSafeForElimination => objectIsNotNull; 986 bool get isSafeForElimination => objectIsNotNull;
879 bool get isSafeForReordering => false; 987 bool get isSafeForReordering => false;
880 988
881 accept(Visitor v) => v.visitGetLength(this); 989 accept(Visitor v) => v.visitGetLength(this);
990
991 void setParentPointers() {
992 object.parent = this;
993 }
882 } 994 }
883 995
884 /// Read an entry from a string or native list. 996 /// Read an entry from a string or native list.
885 /// 997 ///
886 /// [object] must be null or a native list or a string, and [index] must be 998 /// [object] must be null or a native list or a string, and [index] must be
887 /// an integer. 999 /// an integer.
888 class GetIndex extends Primitive { 1000 class GetIndex extends Primitive {
889 final Reference<Primitive> object; 1001 final Reference<Primitive> object;
890 final Reference<Primitive> index; 1002 final Reference<Primitive> index;
891 1003
892 /// True if the object is known not to be null. 1004 /// True if the object is known not to be null.
893 bool objectIsNotNull = false; 1005 bool objectIsNotNull = false;
894 1006
895 GetIndex(Primitive object, Primitive index) 1007 GetIndex(Primitive object, Primitive index)
896 : this.object = new Reference<Primitive>(object), 1008 : this.object = new Reference<Primitive>(object),
897 this.index = new Reference<Primitive>(index); 1009 this.index = new Reference<Primitive>(index);
898 1010
899 bool get isSafeForElimination => objectIsNotNull; 1011 bool get isSafeForElimination => objectIsNotNull;
900 bool get isSafeForReordering => false; 1012 bool get isSafeForReordering => false;
901 1013
902 accept(Visitor v) => v.visitGetIndex(this); 1014 accept(Visitor v) => v.visitGetIndex(this);
1015
1016 void setParentPointers() {
1017 object.parent = this;
1018 index.parent = this;
1019 }
903 } 1020 }
904 1021
905 /// Set an entry on a native list. 1022 /// Set an entry on a native list.
906 /// 1023 ///
907 /// [object] must be null or a native list, and [index] must be an integer. 1024 /// [object] must be null or a native list, and [index] must be an integer.
908 /// 1025 ///
909 /// The primitive itself has no value and may not be referenced. 1026 /// The primitive itself has no value and may not be referenced.
910 class SetIndex extends Primitive { 1027 class SetIndex extends Primitive {
911 final Reference<Primitive> object; 1028 final Reference<Primitive> object;
912 final Reference<Primitive> index; 1029 final Reference<Primitive> index;
913 final Reference<Primitive> value; 1030 final Reference<Primitive> value;
914 1031
915 SetIndex(Primitive object, Primitive index, Primitive value) 1032 SetIndex(Primitive object, Primitive index, Primitive value)
916 : this.object = new Reference<Primitive>(object), 1033 : this.object = new Reference<Primitive>(object),
917 this.index = new Reference<Primitive>(index), 1034 this.index = new Reference<Primitive>(index),
918 this.value = new Reference<Primitive>(value); 1035 this.value = new Reference<Primitive>(value);
919 1036
920 bool get isSafeForElimination => false; 1037 bool get isSafeForElimination => false;
921 bool get isSafeForReordering => false; 1038 bool get isSafeForReordering => false;
922 1039
923 accept(Visitor v) => v.visitSetIndex(this); 1040 accept(Visitor v) => v.visitSetIndex(this);
1041
1042 void setParentPointers() {
1043 object.parent = this;
1044 index.parent = this;
1045 value.parent = this;
1046 }
924 } 1047 }
925 1048
926 /// Reads the value of a static field or tears off a static method. 1049 /// Reads the value of a static field or tears off a static method.
927 /// 1050 ///
928 /// Note that lazily initialized fields should be read using GetLazyStatic. 1051 /// Note that lazily initialized fields should be read using GetLazyStatic.
929 class GetStatic extends Primitive { 1052 class GetStatic extends Primitive {
930 /// Can be [FieldElement] or [FunctionElement]. 1053 /// Can be [FieldElement] or [FunctionElement].
931 final Element element; 1054 final Element element;
932 final SourceInformation sourceInformation; 1055 final SourceInformation sourceInformation;
933 1056
934 GetStatic(this.element, [this.sourceInformation]); 1057 GetStatic(this.element, [this.sourceInformation]);
935 1058
936 accept(Visitor visitor) => visitor.visitGetStatic(this); 1059 accept(Visitor visitor) => visitor.visitGetStatic(this);
937 1060
938 bool get isSafeForElimination { 1061 bool get isSafeForElimination {
939 return true; 1062 return true;
940 } 1063 }
941 bool get isSafeForReordering { 1064 bool get isSafeForReordering {
942 return element is FunctionElement || element.isFinal; 1065 return element is FunctionElement || element.isFinal;
943 } 1066 }
1067
1068 void setParentPointers() {}
944 } 1069 }
945 1070
946 /// Sets the value of a static field. 1071 /// Sets the value of a static field.
947 class SetStatic extends Primitive { 1072 class SetStatic extends Primitive {
948 final FieldElement element; 1073 final FieldElement element;
949 final Reference<Primitive> value; 1074 final Reference<Primitive> value;
950 final SourceInformation sourceInformation; 1075 final SourceInformation sourceInformation;
951 1076
952 SetStatic(this.element, Primitive value, [this.sourceInformation]) 1077 SetStatic(this.element, Primitive value, [this.sourceInformation])
953 : this.value = new Reference<Primitive>(value); 1078 : this.value = new Reference<Primitive>(value);
954 1079
955 accept(Visitor visitor) => visitor.visitSetStatic(this); 1080 accept(Visitor visitor) => visitor.visitSetStatic(this);
956 1081
957 bool get isSafeForElimination => false; 1082 bool get isSafeForElimination => false;
958 bool get isSafeForReordering => false; 1083 bool get isSafeForReordering => false;
1084
1085 void setParentPointers() {
1086 value.parent = this;
1087 }
959 } 1088 }
960 1089
961 /// Reads the value of a lazily initialized static field. 1090 /// Reads the value of a lazily initialized static field.
962 /// 1091 ///
963 /// If the field has not yet been initialized, its initializer is evaluated 1092 /// If the field has not yet been initialized, its initializer is evaluated
964 /// and assigned to the field. 1093 /// and assigned to the field.
965 /// 1094 ///
966 /// [continuation] is then invoked with the value of the field as argument. 1095 /// [continuation] is then invoked with the value of the field as argument.
967 class GetLazyStatic extends CallExpression { 1096 class GetLazyStatic extends CallExpression {
968 final FieldElement element; 1097 final FieldElement element;
969 final Reference<Continuation> continuation; 1098 final Reference<Continuation> continuation;
970 final SourceInformation sourceInformation; 1099 final SourceInformation sourceInformation;
971 1100
972 GetLazyStatic(this.element, 1101 GetLazyStatic(this.element,
973 Continuation continuation, 1102 Continuation continuation,
974 [this.sourceInformation]) 1103 [this.sourceInformation])
975 : continuation = new Reference<Continuation>(continuation); 1104 : continuation = new Reference<Continuation>(continuation);
976 1105
977 accept(Visitor visitor) => visitor.visitGetLazyStatic(this); 1106 accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
1107
1108 void setParentPointers() {
1109 continuation.parent = this;
1110 }
978 } 1111 }
979 1112
980 /// Creates an object for holding boxed variables captured by a closure. 1113 /// Creates an object for holding boxed variables captured by a closure.
981 class CreateBox extends Primitive { 1114 class CreateBox extends Primitive {
982 accept(Visitor visitor) => visitor.visitCreateBox(this); 1115 accept(Visitor visitor) => visitor.visitCreateBox(this);
983 1116
984 bool get isSafeForElimination => true; 1117 bool get isSafeForElimination => true;
985 bool get isSafeForReordering => true; 1118 bool get isSafeForReordering => true;
1119
1120 void setParentPointers() {}
986 } 1121 }
987 1122
988 /// Creates an instance of a class and initializes its fields and runtime type 1123 /// Creates an instance of a class and initializes its fields and runtime type
989 /// information. 1124 /// information.
990 class CreateInstance extends Primitive { 1125 class CreateInstance extends Primitive {
991 final ClassElement classElement; 1126 final ClassElement classElement;
992 1127
993 /// Initial values for the fields on the class. 1128 /// Initial values for the fields on the class.
994 /// The order corresponds to the order of fields on the class. 1129 /// The order corresponds to the order of fields on the class.
995 final List<Reference<Primitive>> arguments; 1130 final List<Reference<Primitive>> arguments;
(...skipping 12 matching lines...) Expand all
1008 this.sourceInformation) 1143 this.sourceInformation)
1009 : this.arguments = _referenceList(arguments), 1144 : this.arguments = _referenceList(arguments),
1010 this.typeInformation = _referenceList(typeInformation); 1145 this.typeInformation = _referenceList(typeInformation);
1011 1146
1012 accept(Visitor visitor) => visitor.visitCreateInstance(this); 1147 accept(Visitor visitor) => visitor.visitCreateInstance(this);
1013 1148
1014 bool get isSafeForElimination => true; 1149 bool get isSafeForElimination => true;
1015 bool get isSafeForReordering => true; 1150 bool get isSafeForReordering => true;
1016 1151
1017 toString() => 'CreateInstance($classElement)'; 1152 toString() => 'CreateInstance($classElement)';
1153
1154 void setParentPointers() {
1155 _setParentsOnList(arguments, this);
1156 if (typeInformation != null) _setParentsOnList(typeInformation, this);
1157 }
1018 } 1158 }
1019 1159
1020 class Interceptor extends Primitive { 1160 class Interceptor extends Primitive {
1021 final Reference<Primitive> input; 1161 final Reference<Primitive> input;
1022 final Set<ClassElement> interceptedClasses = new Set<ClassElement>(); 1162 final Set<ClassElement> interceptedClasses = new Set<ClassElement>();
1023 final SourceInformation sourceInformation; 1163 final SourceInformation sourceInformation;
1024 1164
1025 /// If non-null, all uses of this the interceptor call are guaranteed to 1165 /// If non-null, all uses of this the interceptor call are guaranteed to
1026 /// see this value. 1166 /// see this value.
1027 /// 1167 ///
1028 /// The interceptor call is not immediately replaced by the constant, because 1168 /// The interceptor call is not immediately replaced by the constant, because
1029 /// that might prevent the interceptor from being shared. 1169 /// that might prevent the interceptor from being shared.
1030 /// 1170 ///
1031 /// The precise input type is not known when sharing interceptors, because 1171 /// The precise input type is not known when sharing interceptors, because
1032 /// refinement nodes have been removed by then. So this field carries the 1172 /// refinement nodes have been removed by then. So this field carries the
1033 /// known constant until we know if it should be shared or replaced by 1173 /// known constant until we know if it should be shared or replaced by
1034 /// the constant. 1174 /// the constant.
1035 values.InterceptorConstantValue constantValue; 1175 values.InterceptorConstantValue constantValue;
1036 1176
1037 Interceptor(Primitive input, this.sourceInformation) 1177 Interceptor(Primitive input, this.sourceInformation)
1038 : this.input = new Reference<Primitive>(input); 1178 : this.input = new Reference<Primitive>(input);
1039 1179
1040 accept(Visitor visitor) => visitor.visitInterceptor(this); 1180 accept(Visitor visitor) => visitor.visitInterceptor(this);
1041 1181
1042 bool get isSafeForElimination => true; 1182 bool get isSafeForElimination => true;
1043 bool get isSafeForReordering => true; 1183 bool get isSafeForReordering => true;
1184
1185 void setParentPointers() {
1186 input.parent = this;
1187 }
1044 } 1188 }
1045 1189
1046 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`. 1190 /// Create an instance of [Invocation] for use in a call to `noSuchMethod`.
1047 class CreateInvocationMirror extends Primitive { 1191 class CreateInvocationMirror extends Primitive {
1048 final Selector selector; 1192 final Selector selector;
1049 final List<Reference<Primitive>> arguments; 1193 final List<Reference<Primitive>> arguments;
1050 1194
1051 CreateInvocationMirror(this.selector, List<Primitive> arguments) 1195 CreateInvocationMirror(this.selector, List<Primitive> arguments)
1052 : this.arguments = _referenceList(arguments); 1196 : this.arguments = _referenceList(arguments);
1053 1197
1054 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this); 1198 accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
1055 1199
1056 bool get isSafeForElimination => true; 1200 bool get isSafeForElimination => true;
1057 bool get isSafeForReordering => true; 1201 bool get isSafeForReordering => true;
1202
1203 void setParentPointers() {
1204 _setParentsOnList(arguments, this);
1205 }
1058 } 1206 }
1059 1207
1060 class ForeignCode extends CallExpression { 1208 class ForeignCode extends CallExpression {
1061 final js.Template codeTemplate; 1209 final js.Template codeTemplate;
1062 final TypeMask type; 1210 final TypeMask type;
1063 final List<Reference<Primitive>> arguments; 1211 final List<Reference<Primitive>> arguments;
1064 final native.NativeBehavior nativeBehavior; 1212 final native.NativeBehavior nativeBehavior;
1065 final FunctionElement dependency; 1213 final FunctionElement dependency;
1066 final Reference<Continuation> continuation; 1214 final Reference<Continuation> continuation;
1067 1215
1068 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments, 1216 ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
1069 this.nativeBehavior, Continuation continuation, {this.dependency}) 1217 this.nativeBehavior, Continuation continuation, {this.dependency})
1070 : this.arguments = _referenceList(arguments), 1218 : this.arguments = _referenceList(arguments),
1071 this.continuation = new Reference<Continuation>(continuation); 1219 this.continuation = new Reference<Continuation>(continuation);
1072 1220
1073 accept(Visitor visitor) => visitor.visitForeignCode(this); 1221 accept(Visitor visitor) => visitor.visitForeignCode(this);
1222
1223 void setParentPointers() {
1224 _setParentsOnList(arguments, this);
1225 continuation.parent = this;
1226 }
1074 } 1227 }
1075 1228
1076 class Constant extends Primitive { 1229 class Constant extends Primitive {
1077 final values.ConstantValue value; 1230 final values.ConstantValue value;
1078 final SourceInformation sourceInformation; 1231 final SourceInformation sourceInformation;
1079 1232
1080 Constant(this.value, {this.sourceInformation}) { 1233 Constant(this.value, {this.sourceInformation}) {
1081 assert(value != null); 1234 assert(value != null);
1082 } 1235 }
1083 1236
1084 accept(Visitor visitor) => visitor.visitConstant(this); 1237 accept(Visitor visitor) => visitor.visitConstant(this);
1085 1238
1086 bool get isSafeForElimination => true; 1239 bool get isSafeForElimination => true;
1087 bool get isSafeForReordering => true; 1240 bool get isSafeForReordering => true;
1241
1242 void setParentPointers() {}
1088 } 1243 }
1089 1244
1090 class LiteralList extends Primitive { 1245 class LiteralList extends Primitive {
1091 /// The List type being created; this is not the type argument. 1246 /// The List type being created; this is not the type argument.
1092 final InterfaceType dartType; 1247 final InterfaceType dartType;
1093 final List<Reference<Primitive>> values; 1248 final List<Reference<Primitive>> values;
1094 1249
1095 LiteralList(this.dartType, List<Primitive> values) 1250 LiteralList(this.dartType, List<Primitive> values)
1096 : this.values = _referenceList(values); 1251 : this.values = _referenceList(values);
1097 1252
1098 accept(Visitor visitor) => visitor.visitLiteralList(this); 1253 accept(Visitor visitor) => visitor.visitLiteralList(this);
1099 1254
1100 bool get isSafeForElimination => true; 1255 bool get isSafeForElimination => true;
1101 bool get isSafeForReordering => true; 1256 bool get isSafeForReordering => true;
1257
1258 void setParentPointers() {
1259 _setParentsOnList(values, this);
1260 }
1102 } 1261 }
1103 1262
1104 class LiteralMapEntry { 1263 class LiteralMapEntry {
1105 final Reference<Primitive> key; 1264 final Reference<Primitive> key;
1106 final Reference<Primitive> value; 1265 final Reference<Primitive> value;
1107 1266
1108 LiteralMapEntry(Primitive key, Primitive value) 1267 LiteralMapEntry(Primitive key, Primitive value)
1109 : this.key = new Reference<Primitive>(key), 1268 : this.key = new Reference<Primitive>(key),
1110 this.value = new Reference<Primitive>(value); 1269 this.value = new Reference<Primitive>(value);
1111 } 1270 }
1112 1271
1113 class LiteralMap extends Primitive { 1272 class LiteralMap extends Primitive {
1114 final InterfaceType dartType; 1273 final InterfaceType dartType;
1115 final List<LiteralMapEntry> entries; 1274 final List<LiteralMapEntry> entries;
1116 1275
1117 LiteralMap(this.dartType, this.entries); 1276 LiteralMap(this.dartType, this.entries);
1118 1277
1119 accept(Visitor visitor) => visitor.visitLiteralMap(this); 1278 accept(Visitor visitor) => visitor.visitLiteralMap(this);
1120 1279
1121 bool get isSafeForElimination => true; 1280 bool get isSafeForElimination => true;
1122 bool get isSafeForReordering => true; 1281 bool get isSafeForReordering => true;
1282
1283 void setParentPointers() {
1284 for (LiteralMapEntry entry in entries) {
1285 entry.key.parent = this;
1286 entry.value.parent = this;
1287 }
1288 }
1123 } 1289 }
1124 1290
1125 /// Currently unused. 1291 /// Currently unused.
1126 /// 1292 ///
1127 /// Nested functions (from Dart code) are translated to classes by closure 1293 /// Nested functions (from Dart code) are translated to classes by closure
1128 /// conversion, hence they are instantiated with [CreateInstance]. 1294 /// conversion, hence they are instantiated with [CreateInstance].
1129 /// 1295 ///
1130 /// We keep this around for now because it might come in handy when we 1296 /// We keep this around for now because it might come in handy when we
1131 /// handle async/await in the CPS IR. 1297 /// handle async/await in the CPS IR.
1132 /// 1298 ///
1133 /// Instantiates a nested function. [MutableVariable]s are in scope in the 1299 /// Instantiates a nested function. [MutableVariable]s are in scope in the
1134 /// inner function, but primitives are not shared across function boundaries. 1300 /// inner function, but primitives are not shared across function boundaries.
1135 class CreateFunction extends Primitive { 1301 class CreateFunction extends Primitive {
1136 final FunctionDefinition definition; 1302 final FunctionDefinition definition;
1137 1303
1138 CreateFunction(this.definition); 1304 CreateFunction(this.definition);
1139 1305
1140 accept(Visitor visitor) => visitor.visitCreateFunction(this); 1306 accept(Visitor visitor) => visitor.visitCreateFunction(this);
1141 1307
1142 bool get isSafeForElimination => true; 1308 bool get isSafeForElimination => true;
1143 bool get isSafeForReordering => true; 1309 bool get isSafeForReordering => true;
1310
1311 void setParentPointers() {}
1144 } 1312 }
1145 1313
1146 class Parameter extends Primitive { 1314 class Parameter extends Primitive {
1147 Parameter(Entity hint) { 1315 Parameter(Entity hint) {
1148 super.hint = hint; 1316 super.hint = hint;
1149 } 1317 }
1150 1318
1151 // In addition to a parent pointer to the containing Continuation or
1152 // FunctionDefinition, parameters have an index into the list of parameters
1153 // bound by the parent. This gives constant-time access to the continuation
1154 // from the parent.
1155 int parentIndex;
1156
1157 accept(Visitor visitor) => visitor.visitParameter(this); 1319 accept(Visitor visitor) => visitor.visitParameter(this);
1158 1320
1159 String toString() => 'Parameter(${hint == null ? null : hint.name})'; 1321 String toString() => 'Parameter(${hint == null ? null : hint.name})';
1160 1322
1161 bool get isSafeForElimination => true; 1323 bool get isSafeForElimination => true;
1162 bool get isSafeForReordering => true; 1324 bool get isSafeForReordering => true;
1325
1326 void setParentPointers() {}
1163 } 1327 }
1164 1328
1165 /// Continuations are normally bound by 'let cont'. A continuation with one 1329 /// Continuations are normally bound by 'let cont'. A continuation with one
1166 /// parameter and no body is used to represent a function's return continuation. 1330 /// parameter and no body is used to represent a function's return continuation.
1167 /// The return continuation is bound by the function, not by 'let cont'. 1331 /// The return continuation is bound by the function, not by 'let cont'.
1168 class Continuation extends Definition<Continuation> implements InteriorNode { 1332 class Continuation extends Definition<Continuation> implements InteriorNode {
1169 final List<Parameter> parameters; 1333 final List<Parameter> parameters;
1170 Expression body = null; 1334 Expression body = null;
1171 1335
1172 // In addition to a parent pointer to the containing LetCont, continuations
1173 // have an index into the list of continuations bound by the LetCont. This
1174 // gives constant-time access to the continuation from the parent.
1175 int parent_index;
1176
1177 // A continuation is recursive if it has any recursive invocations. 1336 // A continuation is recursive if it has any recursive invocations.
1178 bool isRecursive; 1337 bool isRecursive;
1179 1338
1180 bool get isReturnContinuation => body == null; 1339 bool get isReturnContinuation => body == null;
1181 1340
1182 Continuation(this.parameters, {this.isRecursive: false}); 1341 Continuation(this.parameters, {this.isRecursive: false});
1183 1342
1184 Continuation.retrn() 1343 Continuation.retrn()
1185 : parameters = <Parameter>[new Parameter(null)], 1344 : parameters = <Parameter>[new Parameter(null)],
1186 isRecursive = false; 1345 isRecursive = false;
1187 1346
1188 accept(Visitor visitor) => visitor.visitContinuation(this); 1347 accept(Visitor visitor) => visitor.visitContinuation(this);
1348
1349 void setParentPointers() {
1350 _setParentsOnNodes(parameters, this);
1351 if (body != null) body.parent = this;
1352 }
1189 } 1353 }
1190 1354
1191 /// Common interface for [Primitive] and [MutableVariable]. 1355 /// Common interface for [Primitive] and [MutableVariable].
1192 abstract class Variable<T extends Variable<T>> extends Definition<T> { 1356 abstract class Variable<T extends Variable<T>> extends Definition<T> {
1193 /// Type of value held in the variable. 1357 /// Type of value held in the variable.
1194 /// 1358 ///
1195 /// Is `null` until initialized by type propagation. 1359 /// Is `null` until initialized by type propagation.
1196 TypeMask type; 1360 TypeMask type;
1197 } 1361 }
1198 1362
1199 /// Identifies a mutable variable. 1363 /// Identifies a mutable variable.
1200 class MutableVariable extends Variable<MutableVariable> { 1364 class MutableVariable extends Variable<MutableVariable> {
1201 Entity hint; 1365 Entity hint;
1202 1366
1203 MutableVariable(this.hint); 1367 MutableVariable(this.hint);
1204 1368
1205 accept(Visitor v) => v.visitMutableVariable(this); 1369 accept(Visitor v) => v.visitMutableVariable(this);
1370
1371 void setParentPointers() {}
1206 } 1372 }
1207 1373
1208 /// A function definition, consisting of parameters and a body. 1374 /// A function definition, consisting of parameters and a body.
1209 /// 1375 ///
1210 /// There is an explicit parameter for the `this` argument, and a return 1376 /// There is an explicit parameter for the `this` argument, and a return
1211 /// continuation to invoke when returning from the function. 1377 /// continuation to invoke when returning from the function.
1212 class FunctionDefinition extends InteriorNode { 1378 class FunctionDefinition extends InteriorNode {
1213 final ExecutableElement element; 1379 final ExecutableElement element;
1214 final Parameter thisParameter; 1380 final Parameter thisParameter;
1215 final List<Parameter> parameters; 1381 final List<Parameter> parameters;
1216 final Continuation returnContinuation; 1382 final Continuation returnContinuation;
1217 Expression body; 1383 Expression body;
1218 1384
1219 FunctionDefinition(this.element, 1385 FunctionDefinition(this.element,
1220 this.thisParameter, 1386 this.thisParameter,
1221 this.parameters, 1387 this.parameters,
1222 this.returnContinuation, 1388 this.returnContinuation,
1223 this.body); 1389 this.body);
1224 1390
1225 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); 1391 accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
1392
1393 void setParentPointers() {
1394 if (thisParameter != null) thisParameter.parent = this;
1395 _setParentsOnNodes(parameters, this);
1396 returnContinuation.parent = this;
1397 if (body != null) body.parent = this;
1398 }
1226 } 1399 }
1227 1400
1228 /// Converts the internal representation of a type to a Dart object of type 1401 /// Converts the internal representation of a type to a Dart object of type
1229 /// [Type]. 1402 /// [Type].
1230 class ReifyRuntimeType extends Primitive { 1403 class ReifyRuntimeType extends Primitive {
1231 /// Reference to the internal representation of a type (as produced, for 1404 /// Reference to the internal representation of a type (as produced, for
1232 /// example, by [ReadTypeVariable]). 1405 /// example, by [ReadTypeVariable]).
1233 final Reference<Primitive> value; 1406 final Reference<Primitive> value;
1234 1407
1235 final SourceInformation sourceInformation; 1408 final SourceInformation sourceInformation;
1236 1409
1237 ReifyRuntimeType(Primitive value, this.sourceInformation) 1410 ReifyRuntimeType(Primitive value, this.sourceInformation)
1238 : this.value = new Reference<Primitive>(value); 1411 : this.value = new Reference<Primitive>(value);
1239 1412
1240 @override 1413 @override
1241 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this); 1414 accept(Visitor visitor) => visitor.visitReifyRuntimeType(this);
1242 1415
1243 bool get isSafeForElimination => true; 1416 bool get isSafeForElimination => true;
1244 bool get isSafeForReordering => true; 1417 bool get isSafeForReordering => true;
1418
1419 void setParentPointers() {
1420 value.parent = this;
1421 }
1245 } 1422 }
1246 1423
1247 /// Read the value the type variable [variable] from the target object. 1424 /// Read the value the type variable [variable] from the target object.
1248 /// 1425 ///
1249 /// The resulting value is an internal representation (and not neccessarily a 1426 /// The resulting value is an internal representation (and not neccessarily a
1250 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be 1427 /// Dart object), and must be reified by [ReifyRuntimeType], if it should be
1251 /// used as a Dart value. 1428 /// used as a Dart value.
1252 class ReadTypeVariable extends Primitive { 1429 class ReadTypeVariable extends Primitive {
1253 final TypeVariableType variable; 1430 final TypeVariableType variable;
1254 final Reference<Primitive> target; 1431 final Reference<Primitive> target;
1255 final SourceInformation sourceInformation; 1432 final SourceInformation sourceInformation;
1256 1433
1257 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation) 1434 ReadTypeVariable(this.variable, Primitive target, this.sourceInformation)
1258 : this.target = new Reference<Primitive>(target); 1435 : this.target = new Reference<Primitive>(target);
1259 1436
1260 @override 1437 @override
1261 accept(Visitor visitor) => visitor.visitReadTypeVariable(this); 1438 accept(Visitor visitor) => visitor.visitReadTypeVariable(this);
1262 1439
1263 bool get isSafeForElimination => true; 1440 bool get isSafeForElimination => true;
1264 bool get isSafeForReordering => true; 1441 bool get isSafeForReordering => true;
1442
1443 void setParentPointers() {
1444 target.parent = this;
1445 }
1265 } 1446 }
1266 1447
1267 /// Representation of a closed type (that is, a type without type variables). 1448 /// Representation of a closed type (that is, a type without type variables).
1268 /// 1449 ///
1269 /// The resulting value is constructed from [dartType] by replacing the type 1450 /// The resulting value is constructed from [dartType] by replacing the type
1270 /// variables with consecutive values from [arguments], in the order generated 1451 /// variables with consecutive values from [arguments], in the order generated
1271 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are 1452 /// by [DartType.forEachTypeVariable]. The type variables in [dartType] are
1272 /// treated as 'holes' in the term, which means that it must be ensured at 1453 /// treated as 'holes' in the term, which means that it must be ensured at
1273 /// construction, that duplicate occurences of a type variable in [dartType] 1454 /// construction, that duplicate occurences of a type variable in [dartType]
1274 /// are assigned the same value. 1455 /// are assigned the same value.
1275 class TypeExpression extends Primitive { 1456 class TypeExpression extends Primitive {
1276 final DartType dartType; 1457 final DartType dartType;
1277 final List<Reference<Primitive>> arguments; 1458 final List<Reference<Primitive>> arguments;
1278 1459
1279 TypeExpression(this.dartType, 1460 TypeExpression(this.dartType,
1280 [List<Primitive> arguments = const <Primitive>[]]) 1461 [List<Primitive> arguments = const <Primitive>[]])
1281 : this.arguments = _referenceList(arguments); 1462 : this.arguments = _referenceList(arguments);
1282 1463
1283 @override 1464 @override
1284 accept(Visitor visitor) { 1465 accept(Visitor visitor) {
1285 return visitor.visitTypeExpression(this); 1466 return visitor.visitTypeExpression(this);
1286 } 1467 }
1287 1468
1288 bool get isSafeForElimination => true; 1469 bool get isSafeForElimination => true;
1289 bool get isSafeForReordering => true; 1470 bool get isSafeForReordering => true;
1471
1472 void setParentPointers() {
1473 _setParentsOnList(arguments, this);
1474 }
1290 } 1475 }
1291 1476
1292 class Await extends CallExpression { 1477 class Await extends CallExpression {
1293 final Reference<Primitive> input; 1478 final Reference<Primitive> input;
1294 final Reference<Continuation> continuation; 1479 final Reference<Continuation> continuation;
1295 1480
1296 Await(Primitive input, Continuation continuation) 1481 Await(Primitive input, Continuation continuation)
1297 : this.input = new Reference<Primitive>(input), 1482 : this.input = new Reference<Primitive>(input),
1298 this.continuation = new Reference<Continuation>(continuation); 1483 this.continuation = new Reference<Continuation>(continuation);
1299 1484
1300 @override 1485 @override
1301 accept(Visitor visitor) { 1486 accept(Visitor visitor) {
1302 return visitor.visitAwait(this); 1487 return visitor.visitAwait(this);
1303 } 1488 }
1489
1490 void setParentPointers() {
1491 input.parent = this;
1492 continuation.parent = this;
1493 }
1304 } 1494 }
1305 1495
1306 class Yield extends CallExpression { 1496 class Yield extends CallExpression {
1307 final Reference<Primitive> input; 1497 final Reference<Primitive> input;
1308 final Reference<Continuation> continuation; 1498 final Reference<Continuation> continuation;
1309 final bool hasStar; 1499 final bool hasStar;
1310 1500
1311 Yield(Primitive input, this.hasStar, Continuation continuation) 1501 Yield(Primitive input, this.hasStar, Continuation continuation)
1312 : this.input = new Reference<Primitive>(input), 1502 : this.input = new Reference<Primitive>(input),
1313 this.continuation = new Reference<Continuation>(continuation); 1503 this.continuation = new Reference<Continuation>(continuation);
1314 1504
1315 @override 1505 @override
1316 accept(Visitor visitor) { 1506 accept(Visitor visitor) {
1317 return visitor.visitYield(this); 1507 return visitor.visitYield(this);
1318 } 1508 }
1509
1510 void setParentPointers() {
1511 input.parent = this;
1512 continuation.parent = this;
1513 }
1319 } 1514 }
1320 1515
1321 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { 1516 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
1322 return definitions.map((e) => new Reference<Primitive>(e)).toList(); 1517 return definitions.map((e) => new Reference<Primitive>(e)).toList();
1323 } 1518 }
1324 1519
1520 void _setParentsOnNodes(List<Node> nodes, Node parent) {
1521 for (Node node in nodes) {
1522 node.parent = parent;
1523 }
1524 }
1525
1526 void _setParentsOnList(List<Reference> nodes, Node parent) {
1527 for (Reference node in nodes) {
1528 node.parent = parent;
1529 }
1530 }
1531
1325 abstract class Visitor<T> { 1532 abstract class Visitor<T> {
1326 const Visitor(); 1533 const Visitor();
1327 1534
1328 T visit(Node node); 1535 T visit(Node node);
1329 1536
1330 // Concrete classes. 1537 // Concrete classes.
1331 T visitFunctionDefinition(FunctionDefinition node); 1538 T visitFunctionDefinition(FunctionDefinition node);
1332 1539
1333 // Expressions. 1540 // Expressions.
1334 T visitLetPrim(LetPrim node); 1541 T visitLetPrim(LetPrim node);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 T visitApplyBuiltinMethod(ApplyBuiltinMethod node); 1582 T visitApplyBuiltinMethod(ApplyBuiltinMethod node);
1376 T visitGetLength(GetLength node); 1583 T visitGetLength(GetLength node);
1377 T visitGetIndex(GetIndex node); 1584 T visitGetIndex(GetIndex node);
1378 T visitSetIndex(SetIndex node); 1585 T visitSetIndex(SetIndex node);
1379 T visitRefinement(Refinement node); 1586 T visitRefinement(Refinement node);
1380 1587
1381 // Support for literal foreign code. 1588 // Support for literal foreign code.
1382 T visitForeignCode(ForeignCode node); 1589 T visitForeignCode(ForeignCode node);
1383 } 1590 }
1384 1591
1385 /// Visits all non-recursive children of a CPS term, i.e. anything 1592 /// Recursively visits all children of a CPS term.
1386 /// not of type [Expression] or [Continuation]. 1593 ///
1594 /// The user of the class is responsible for avoiding stack overflows from
1595 /// deep recursion, e.g. by overriding methods to cut off recursion at certain
1596 /// points.
1597 ///
1598 /// All recursive invocations occur through the [visit] method, which the
1599 /// subclass may override as a generic way to control the visitor without
1600 /// overriding all visitor methods.
1387 /// 1601 ///
1388 /// The `process*` methods are called in pre-order for every node visited. 1602 /// The `process*` methods are called in pre-order for every node visited.
1389 /// These can be overridden without disrupting the visitor traversal. 1603 /// These can be overridden without disrupting the visitor traversal.
1390 class LeafVisitor implements Visitor { 1604 class DeepRecursiveVisitor implements Visitor {
1391 const LeafVisitor(); 1605 const DeepRecursiveVisitor();
1392 1606
1393 visit(Node node) => node.accept(this); 1607 visit(Node node) => node.accept(this);
1394 1608
1395 processReference(Reference ref) {} 1609 processReference(Reference ref) {}
1396 1610
1397 processFunctionDefinition(FunctionDefinition node) {} 1611 processFunctionDefinition(FunctionDefinition node) {}
1398 visitFunctionDefinition(FunctionDefinition node) { 1612 visitFunctionDefinition(FunctionDefinition node) {
1399 processFunctionDefinition(node); 1613 processFunctionDefinition(node);
1400 if (node.thisParameter != null) visit(node.thisParameter); 1614 if (node.thisParameter != null) visit(node.thisParameter);
1401 node.parameters.forEach(visit); 1615 node.parameters.forEach(visit);
1402 visit(node.returnContinuation); 1616 visit(node.returnContinuation);
1617 visit(node.body);
1618 }
1619
1620 processContinuation(Continuation node) {}
1621 visitContinuation(Continuation node) {
1622 processContinuation(node);
1623 node.parameters.forEach(visit);
1624 if (node.body != null) visit(node.body);
1403 } 1625 }
1404 1626
1405 // Expressions. 1627 // Expressions.
1406
1407 processLetPrim(LetPrim node) {} 1628 processLetPrim(LetPrim node) {}
1408 visitLetPrim(LetPrim node) { 1629 visitLetPrim(LetPrim node) {
1409 processLetPrim(node); 1630 processLetPrim(node);
1410 visit(node.primitive); 1631 visit(node.primitive);
1632 visit(node.body);
1411 } 1633 }
1412 1634
1413 processLetCont(LetCont node) {} 1635 processLetCont(LetCont node) {}
1414 visitLetCont(LetCont node) { 1636 visitLetCont(LetCont node) {
1415 processLetCont(node); 1637 processLetCont(node);
1416 node.continuations.forEach(visit); 1638 node.continuations.forEach(visit);
1639 visit(node.body);
1417 } 1640 }
1418 1641
1419 processLetHandler(LetHandler node) {} 1642 processLetHandler(LetHandler node) {}
1420 visitLetHandler(LetHandler node) { 1643 visitLetHandler(LetHandler node) {
1421 processLetHandler(node); 1644 processLetHandler(node);
1645 visit(node.handler);
1646 visit(node.body);
1422 } 1647 }
1423 1648
1424 processLetMutable(LetMutable node) {} 1649 processLetMutable(LetMutable node) {}
1425 visitLetMutable(LetMutable node) { 1650 visitLetMutable(LetMutable node) {
1426 processLetMutable(node); 1651 processLetMutable(node);
1427 visit(node.variable); 1652 visit(node.variable);
1428 processReference(node.value); 1653 processReference(node.value);
1654 visit(node.body);
1429 } 1655 }
1430 1656
1431 processInvokeStatic(InvokeStatic node) {} 1657 processInvokeStatic(InvokeStatic node) {}
1432 visitInvokeStatic(InvokeStatic node) { 1658 visitInvokeStatic(InvokeStatic node) {
1433 processInvokeStatic(node); 1659 processInvokeStatic(node);
1434 processReference(node.continuation); 1660 processReference(node.continuation);
1435 node.arguments.forEach(processReference); 1661 node.arguments.forEach(processReference);
1436 } 1662 }
1437 1663
1438 processInvokeContinuation(InvokeContinuation node) {} 1664 processInvokeContinuation(InvokeContinuation node) {}
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 visitGetMutable(GetMutable node) { 1773 visitGetMutable(GetMutable node) {
1548 processGetMutable(node); 1774 processGetMutable(node);
1549 processReference(node.variable); 1775 processReference(node.variable);
1550 } 1776 }
1551 1777
1552 processParameter(Parameter node) {} 1778 processParameter(Parameter node) {}
1553 visitParameter(Parameter node) { 1779 visitParameter(Parameter node) {
1554 processParameter(node); 1780 processParameter(node);
1555 } 1781 }
1556 1782
1557 processContinuation(Continuation node) {}
1558 visitContinuation(Continuation node) {
1559 processContinuation(node);
1560 node.parameters.forEach(visitParameter);
1561 }
1562
1563 processInterceptor(Interceptor node) {} 1783 processInterceptor(Interceptor node) {}
1564 visitInterceptor(Interceptor node) { 1784 visitInterceptor(Interceptor node) {
1565 processInterceptor(node); 1785 processInterceptor(node);
1566 processReference(node.input); 1786 processReference(node.input);
1567 } 1787 }
1568 1788
1569 processCreateInstance(CreateInstance node) {} 1789 processCreateInstance(CreateInstance node) {}
1570 visitCreateInstance(CreateInstance node) { 1790 visitCreateInstance(CreateInstance node) {
1571 processCreateInstance(node); 1791 processCreateInstance(node);
1572 node.arguments.forEach(processReference); 1792 node.arguments.forEach(processReference);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 /// The `traverse*` methods return the expression to visit next, and may 1933 /// The `traverse*` methods return the expression to visit next, and may
1714 /// push other subterms onto the stack using [push] or [pushAction] to visit 1934 /// push other subterms onto the stack using [push] or [pushAction] to visit
1715 /// them later. Actions pushed onto the stack will be executed after the body 1935 /// them later. Actions pushed onto the stack will be executed after the body
1716 /// has been processed (and the stack actions it pushed have been executed). 1936 /// has been processed (and the stack actions it pushed have been executed).
1717 /// 1937 ///
1718 /// By default, the `traverse` methods visit all non-recursive subterms, 1938 /// By default, the `traverse` methods visit all non-recursive subterms,
1719 /// push all bound continuations on the stack, and return the body of the term. 1939 /// push all bound continuations on the stack, and return the body of the term.
1720 /// 1940 ///
1721 /// Subclasses should not override the `visit` methods for the nodes that have 1941 /// Subclasses should not override the `visit` methods for the nodes that have
1722 /// a `traverse` method. 1942 /// a `traverse` method.
1723 class RecursiveVisitor extends LeafVisitor { 1943 class TrampolineRecursiveVisitor extends DeepRecursiveVisitor {
1724 List<StackAction> _stack = <StackAction>[]; 1944 List<StackAction> _stack = <StackAction>[];
1725 1945
1726 void pushAction(StackAction callback) { 1946 void pushAction(StackAction callback) {
1727 _stack.add(callback); 1947 _stack.add(callback);
1728 } 1948 }
1729 1949
1730 void push(Continuation cont) { 1950 void push(Continuation cont) {
1731 _stack.add(() { 1951 _stack.add(() {
1732 if (cont.isReturnContinuation) { 1952 if (cont.isReturnContinuation) {
1733 traverseContinuation(cont); 1953 traverseContinuation(cont);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 node = traverseLetPrim(node); 2028 node = traverseLetPrim(node);
1809 } else { 2029 } else {
1810 node = traverseLetMutable(node); 2030 node = traverseLetMutable(node);
1811 } 2031 }
1812 } 2032 }
1813 visit(node); 2033 visit(node);
1814 } 2034 }
1815 } 2035 }
1816 2036
1817 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 2037 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
1818 class RemovalVisitor extends RecursiveVisitor { 2038 class RemovalVisitor extends TrampolineRecursiveVisitor {
1819 processReference(Reference reference) { 2039 processReference(Reference reference) {
1820 reference.unlink(); 2040 reference.unlink();
1821 } 2041 }
1822 2042
1823 static void remove(Node node) { 2043 static void remove(Node node) {
1824 (new RemovalVisitor()).visit(node); 2044 (new RemovalVisitor()).visit(node);
1825 } 2045 }
1826 } 2046 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698