OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // IrNodes are kept in a separate library to have precise control over their | 5 // IrNodes are kept in a separate library to have precise control over their |
6 // dependencies on other parts of the system. | 6 // dependencies on other parts of the system. |
7 library dart2js.ir_nodes; | 7 library dart2js.ir_nodes; |
8 | 8 |
9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
10 import '../constants/values.dart' as values show ConstantValue; | 10 import '../constants/values.dart' as values show ConstantValue; |
11 import '../dart2jslib.dart' as dart2js show invariant; | 11 import '../dart2jslib.dart' as dart2js show invariant; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../universe/universe.dart' show Selector, SelectorKind; | 13 import '../universe/universe.dart' show Selector, SelectorKind; |
14 import '../dart_types.dart' show DartType, GenericType; | 14 import '../dart_types.dart' show DartType, GenericType; |
| 15 import '../cps_ir/optimizers.dart'; |
15 | 16 |
16 abstract class Node { | 17 abstract class Node { |
17 /// A pointer to the parent node. Is null until set by optimization passes. | 18 /// A pointer to the parent node. Is null until set by optimization passes. |
18 Node parent; | 19 Node parent; |
19 | 20 |
20 accept(Visitor visitor); | 21 accept(Visitor visitor); |
21 } | 22 } |
22 | 23 |
23 abstract class Expression extends Node { | 24 abstract class Expression extends Node { |
24 Expression plug(Expression expr) => throw 'impossible'; | 25 Expression plug(Expression expr) => throw 'impossible'; |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 | 544 |
544 bool get isReturnContinuation => body == null; | 545 bool get isReturnContinuation => body == null; |
545 | 546 |
546 Continuation(this.parameters); | 547 Continuation(this.parameters); |
547 | 548 |
548 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; | 549 Continuation.retrn() : parameters = <Parameter>[new Parameter(null)]; |
549 | 550 |
550 accept(Visitor visitor) => visitor.visitContinuation(this); | 551 accept(Visitor visitor) => visitor.visitContinuation(this); |
551 } | 552 } |
552 | 553 |
| 554 abstract class ExecutableDefinition implements Node { |
| 555 Expression get body; |
| 556 |
| 557 applyPass(Pass pass); |
| 558 } |
| 559 |
| 560 // This is basically a function definition with an empty parameter list and a |
| 561 // field element instead of a function element and no const declarations, and |
| 562 // never a getter or setter, though that's less important. |
| 563 class FieldDefinition extends Node |
| 564 implements InteriorNode, ExecutableDefinition { |
| 565 final FieldElement element; |
| 566 final Continuation returnContinuation; |
| 567 Expression body; |
| 568 |
| 569 FieldDefinition(this.element, this.returnContinuation, this.body); |
| 570 accept(Visitor visitor) => visitor.visitFieldDefinition(this); |
| 571 applyPass(Pass pass) => pass.rewriteFieldDefinition(this); |
| 572 } |
| 573 |
553 /// A function definition, consisting of parameters and a body. The parameters | 574 /// A function definition, consisting of parameters and a body. The parameters |
554 /// include a distinguished continuation parameter. | 575 /// include a distinguished continuation parameter. |
555 class FunctionDefinition extends Node implements InteriorNode { | 576 class FunctionDefinition extends Node |
| 577 implements InteriorNode, ExecutableDefinition { |
556 final FunctionElement element; | 578 final FunctionElement element; |
557 final Continuation returnContinuation; | 579 final Continuation returnContinuation; |
558 final List<Parameter> parameters; | 580 final List<Parameter> parameters; |
559 Expression body; | 581 Expression body; |
560 final List<ConstDeclaration> localConstants; | 582 final List<ConstDeclaration> localConstants; |
561 | 583 |
562 /// Values for optional parameters. | 584 /// Values for optional parameters. |
563 final List<ConstantExpression> defaultParameterValues; | 585 final List<ConstantExpression> defaultParameterValues; |
564 | 586 |
565 FunctionDefinition(this.element, this.returnContinuation, | 587 FunctionDefinition(this.element, this.returnContinuation, |
566 this.parameters, this.body, this.localConstants, | 588 this.parameters, this.body, this.localConstants, |
567 this.defaultParameterValues); | 589 this.defaultParameterValues); |
568 | 590 |
569 FunctionDefinition.abstract(this.element, | 591 FunctionDefinition.abstract(this.element, |
570 this.parameters, | 592 this.parameters, |
571 this.defaultParameterValues) | 593 this.defaultParameterValues) |
572 : this.returnContinuation = null, | 594 : this.returnContinuation = null, |
573 this.localConstants = const <ConstDeclaration>[]; | 595 this.localConstants = const <ConstDeclaration>[]; |
574 | 596 |
575 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 597 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 598 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
576 | 599 |
577 /// Returns `true` if this function is abstract or external. | 600 /// Returns `true` if this function is abstract or external. |
578 /// | 601 /// |
579 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] | 602 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] |
580 /// is empty. | 603 /// is empty. |
581 bool get isAbstract => body == null; | 604 bool get isAbstract => body == null; |
582 } | 605 } |
583 | 606 |
584 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { | 607 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) { |
585 return definitions.map((e) => new Reference<Primitive>(e)).toList(); | 608 return definitions.map((e) => new Reference<Primitive>(e)).toList(); |
586 } | 609 } |
587 | 610 |
588 abstract class Visitor<T> { | 611 abstract class Visitor<T> { |
589 const Visitor(); | 612 const Visitor(); |
590 | 613 |
591 T visit(Node node) => node.accept(this); | 614 T visit(Node node) => node.accept(this); |
592 // Abstract classes. | 615 // Abstract classes. |
593 T visitNode(Node node) => null; | 616 T visitNode(Node node) => null; |
594 T visitExpression(Expression node) => visitNode(node); | 617 T visitExpression(Expression node) => visitNode(node); |
595 T visitDefinition(Definition node) => visitNode(node); | 618 T visitDefinition(Definition node) => visitNode(node); |
596 T visitPrimitive(Primitive node) => visitDefinition(node); | 619 T visitPrimitive(Primitive node) => visitDefinition(node); |
597 T visitCondition(Condition node) => visitNode(node); | 620 T visitCondition(Condition node) => visitNode(node); |
598 | 621 |
599 // Concrete classes. | 622 // Concrete classes. |
| 623 T visitFieldDefinition(FieldDefinition node) => visitNode(node); |
600 T visitFunctionDefinition(FunctionDefinition node) => visitNode(node); | 624 T visitFunctionDefinition(FunctionDefinition node) => visitNode(node); |
601 | 625 |
602 // Expressions. | 626 // Expressions. |
603 T visitLetPrim(LetPrim node) => visitExpression(node); | 627 T visitLetPrim(LetPrim node) => visitExpression(node); |
604 T visitLetCont(LetCont node) => visitExpression(node); | 628 T visitLetCont(LetCont node) => visitExpression(node); |
605 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); | 629 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); |
606 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); | 630 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); |
607 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); | 631 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); |
608 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); | 632 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); |
609 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); | 633 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); |
(...skipping 29 matching lines...) Expand all Loading... |
639 // Ensures that RecursiveVisitor contains overrides for all relevant nodes. | 663 // Ensures that RecursiveVisitor contains overrides for all relevant nodes. |
640 // As a rule of thumb, nodes with structure to traverse should be overridden | 664 // As a rule of thumb, nodes with structure to traverse should be overridden |
641 // with the appropriate visits in this class (for example, visitLetCont), | 665 // with the appropriate visits in this class (for example, visitLetCont), |
642 // while leaving other nodes for subclasses (i.e., visitLiteralList). | 666 // while leaving other nodes for subclasses (i.e., visitLiteralList). |
643 visitNode(Node node) { | 667 visitNode(Node node) { |
644 throw "RecursiveVisitor is stale, add missing visit overrides"; | 668 throw "RecursiveVisitor is stale, add missing visit overrides"; |
645 } | 669 } |
646 | 670 |
647 processReference(Reference ref) {} | 671 processReference(Reference ref) {} |
648 | 672 |
| 673 processFieldDefinition(FieldDefinition node) {} |
| 674 visitFieldDefinition(FieldDefinition node) { |
| 675 processFieldDefinition(node); |
| 676 visit(node.body); |
| 677 } |
| 678 |
649 processFunctionDefinition(FunctionDefinition node) {} | 679 processFunctionDefinition(FunctionDefinition node) {} |
650 visitFunctionDefinition(FunctionDefinition node) { | 680 visitFunctionDefinition(FunctionDefinition node) { |
651 processFunctionDefinition(node); | 681 processFunctionDefinition(node); |
652 node.parameters.forEach(visitParameter); | 682 node.parameters.forEach(visitParameter); |
653 visit(node.body); | 683 visit(node.body); |
654 } | 684 } |
655 | 685 |
656 // Expressions. | 686 // Expressions. |
657 | 687 |
658 processLetPrim(LetPrim node) {} | 688 processLetPrim(LetPrim node) {} |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 node.arguments.forEach(processReference); | 735 node.arguments.forEach(processReference); |
706 } | 736 } |
707 | 737 |
708 processConcatenateStrings(ConcatenateStrings node) {} | 738 processConcatenateStrings(ConcatenateStrings node) {} |
709 visitConcatenateStrings(ConcatenateStrings node) { | 739 visitConcatenateStrings(ConcatenateStrings node) { |
710 processConcatenateStrings(node); | 740 processConcatenateStrings(node); |
711 processReference(node.continuation); | 741 processReference(node.continuation); |
712 node.arguments.forEach(processReference); | 742 node.arguments.forEach(processReference); |
713 } | 743 } |
714 | 744 |
715 | |
716 processBranch(Branch node) {} | 745 processBranch(Branch node) {} |
717 visitBranch(Branch node) { | 746 visitBranch(Branch node) { |
718 processBranch(node); | 747 processBranch(node); |
719 processReference(node.trueContinuation); | 748 processReference(node.trueContinuation); |
720 processReference(node.falseContinuation); | 749 processReference(node.falseContinuation); |
721 visit(node.condition); | 750 visit(node.condition); |
722 } | 751 } |
723 | 752 |
724 processTypeOperator(TypeOperator node) {} | 753 processTypeOperator(TypeOperator node) {} |
725 visitTypeOperator(TypeOperator node) { | 754 visitTypeOperator(TypeOperator node) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 if (primitive.hint == null) return; | 885 if (primitive.hint == null) return; |
857 if (primitive.registerIndex != null) { | 886 if (primitive.registerIndex != null) { |
858 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex); | 887 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex); |
859 } | 888 } |
860 } | 889 } |
861 | 890 |
862 void visitReference(Reference reference) { | 891 void visitReference(Reference reference) { |
863 allocate(reference.definition); | 892 allocate(reference.definition); |
864 } | 893 } |
865 | 894 |
| 895 void visitFieldDefinition(FieldDefinition node) { |
| 896 visit(node.body); |
| 897 } |
| 898 |
866 void visitFunctionDefinition(FunctionDefinition node) { | 899 void visitFunctionDefinition(FunctionDefinition node) { |
867 if (!node.isAbstract) { | 900 if (!node.isAbstract) { |
868 visit(node.body); | 901 visit(node.body); |
869 } | 902 } |
870 node.parameters.forEach(allocate); // Assign indices to unused parameters. | 903 node.parameters.forEach(allocate); // Assign indices to unused parameters. |
871 elementRegisters.clear(); | |
872 } | 904 } |
873 | 905 |
874 void visitLetPrim(LetPrim node) { | 906 void visitLetPrim(LetPrim node) { |
875 visit(node.body); | 907 visit(node.body); |
876 release(node.primitive); | 908 release(node.primitive); |
877 visit(node.primitive); | 909 visit(node.primitive); |
878 } | 910 } |
879 | 911 |
880 void visitLetCont(LetCont node) { | 912 void visitLetCont(LetCont node) { |
881 visit(node.continuation); | 913 visit(node.continuation); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 } | 1004 } |
973 | 1005 |
974 // JavaScript specific nodes. | 1006 // JavaScript specific nodes. |
975 | 1007 |
976 void visitIdentical(Identical node) { | 1008 void visitIdentical(Identical node) { |
977 visitReference(node.left); | 1009 visitReference(node.left); |
978 visitReference(node.right); | 1010 visitReference(node.right); |
979 } | 1011 } |
980 } | 1012 } |
981 | 1013 |
OLD | NEW |