| 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; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 final Reference<Continuation> continuation; | 303 final Reference<Continuation> continuation; |
| 304 final List<Reference<Primitive>> arguments; | 304 final List<Reference<Primitive>> arguments; |
| 305 | 305 |
| 306 ConcatenateStrings(Continuation cont, List<Primitive> args) | 306 ConcatenateStrings(Continuation cont, List<Primitive> args) |
| 307 : continuation = new Reference<Continuation>(cont), | 307 : continuation = new Reference<Continuation>(cont), |
| 308 arguments = _referenceList(args); | 308 arguments = _referenceList(args); |
| 309 | 309 |
| 310 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); | 310 accept(Visitor visitor) => visitor.visitConcatenateStrings(this); |
| 311 } | 311 } |
| 312 | 312 |
| 313 /// Gets the value from a closure variable. The identity of the variable is | 313 /// Gets the value from a closure variable. |
| 314 /// determined by a [Local]. | |
| 315 /// | 314 /// |
| 316 /// Closure variables can be seen as ref cells that are not first-class values. | 315 /// Closure variables can be seen as ref cells that are not first-class values. |
| 317 /// A [LetPrim] with a [GetClosureVariable] can then be seen as: | 316 /// A [LetPrim] with a [GetClosureVariable] can then be seen as: |
| 318 /// | 317 /// |
| 319 /// let prim p = ![variable] in [body] | 318 /// let prim p = ![variable] in [body] |
| 320 /// | 319 /// |
| 321 class GetClosureVariable extends Primitive { | 320 class GetClosureVariable extends Primitive { |
| 322 final Local variable; | 321 final Reference<ClosureVariable> variable; |
| 323 | 322 |
| 324 GetClosureVariable(this.variable) { | 323 GetClosureVariable(ClosureVariable variable) |
| 325 assert(variable != null); | 324 : this.variable = new Reference<ClosureVariable>(variable); |
| 326 } | |
| 327 | 325 |
| 328 accept(Visitor visitor) => visitor.visitGetClosureVariable(this); | 326 accept(Visitor visitor) => visitor.visitGetClosureVariable(this); |
| 329 } | 327 } |
| 330 | 328 |
| 331 /// Assign or declare a closure variable. The identity of the variable is | 329 /// Assign or declare a closure variable. |
| 332 /// determined by a [Local]. | |
| 333 /// | 330 /// |
| 334 /// Closure variables can be seen as ref cells that are not first-class values. | 331 /// Closure variables can be seen as ref cells that are not first-class values. |
| 335 /// If [isDeclaration], this can seen as a let binding: | 332 /// If [isDeclaration], this can seen as a let binding: |
| 336 /// | 333 /// |
| 337 /// let [variable] = ref [value] in [body] | 334 /// let [variable] = ref [value] in [body] |
| 338 /// | 335 /// |
| 339 /// And otherwise, it can be seen as a dereferencing assignment: | 336 /// And otherwise, it can be seen as a dereferencing assignment: |
| 340 /// | 337 /// |
| 341 /// { ![variable] := [value]; [body] } | 338 /// { ![variable] := [value]; [body] } |
| 342 /// | 339 /// |
| 343 /// Closure variables without a declaring [SetClosureVariable] are implicitly | 340 /// Closure variables without a declaring [SetClosureVariable] are implicitly |
| 344 /// declared at the entry to the [variable]'s enclosing function. | 341 /// declared at the entry to the [variable]'s enclosing function. |
| 345 class SetClosureVariable extends Expression implements InteriorNode { | 342 class SetClosureVariable extends Expression implements InteriorNode { |
| 346 final Local variable; | 343 final Reference<ClosureVariable> variable; |
| 347 final Reference<Primitive> value; | 344 final Reference<Primitive> value; |
| 348 Expression body; | 345 Expression body; |
| 349 | 346 |
| 350 /// If true, this declares a new copy of the closure variable. If so, all | 347 /// If true, this declares a new copy of the closure variable. If so, all |
| 351 /// uses of the closure variable must occur in the [body]. | 348 /// uses of the closure variable must occur in the [body]. |
| 352 /// | 349 /// |
| 353 /// There can be at most one declaration per closure variable. If there is no | 350 /// There can be at most one declaration per closure variable. If there is no |
| 354 /// declaration, only one copy exists (per function execution). It is best to | 351 /// declaration, only one copy exists (per function execution). It is best to |
| 355 /// avoid declaring closure variables if it is not necessary. | 352 /// avoid declaring closure variables if it is not necessary. |
| 356 final bool isDeclaration; | 353 final bool isDeclaration; |
| 357 | 354 |
| 358 SetClosureVariable(this.variable, Primitive value, | 355 SetClosureVariable(ClosureVariable variable, Primitive value, |
| 359 {this.isDeclaration : false }) | 356 {this.isDeclaration : false }) |
| 360 : this.value = new Reference<Primitive>(value) { | 357 : this.value = new Reference<Primitive>(value), |
| 361 assert(variable != null); | 358 this.variable = new Reference<ClosureVariable>(variable); |
| 362 } | |
| 363 | 359 |
| 364 accept(Visitor visitor) => visitor.visitSetClosureVariable(this); | 360 accept(Visitor visitor) => visitor.visitSetClosureVariable(this); |
| 365 | 361 |
| 366 Expression plug(Expression expr) { | 362 Expression plug(Expression expr) { |
| 367 assert(body == null); | 363 assert(body == null); |
| 368 return body = expr; | 364 return body = expr; |
| 369 } | 365 } |
| 370 } | 366 } |
| 371 | 367 |
| 372 /// Create a potentially recursive function and store it in a closure variable. | 368 /// Create a potentially recursive function and store it in a closure variable. |
| 373 /// The function can access itself using [GetClosureVariable] on [variable]. | 369 /// The function can access itself using [GetClosureVariable] on [variable]. |
| 374 /// There must not exist a [SetClosureVariable] to [variable]. | 370 /// There must not exist a [SetClosureVariable] to [variable]. |
| 375 /// | 371 /// |
| 376 /// This can be seen as a let rec binding: | 372 /// This can be seen as a let rec binding: |
| 377 /// | 373 /// |
| 378 /// let rec [variable] = [definition] in [body] | 374 /// let rec [variable] = [definition] in [body] |
| 379 /// | 375 /// |
| 380 class DeclareFunction extends Expression implements InteriorNode { | 376 class DeclareFunction extends Expression implements InteriorNode { |
| 381 final Local variable; | 377 final Reference<ClosureVariable> variable; |
| 382 final FunctionDefinition definition; | 378 final FunctionDefinition definition; |
| 383 Expression body; | 379 Expression body; |
| 384 | 380 |
| 385 DeclareFunction(this.variable, this.definition); | 381 DeclareFunction(ClosureVariable variable, this.definition) |
| 382 : this.variable = new Reference<ClosureVariable>(variable); |
| 386 | 383 |
| 387 Expression plug(Expression expr) { | 384 Expression plug(Expression expr) { |
| 388 assert(body == null); | 385 assert(body == null); |
| 389 return body = expr; | 386 return body = expr; |
| 390 } | 387 } |
| 391 | 388 |
| 392 accept(Visitor visitor) => visitor.visitDeclareFunction(this); | 389 accept(Visitor visitor) => visitor.visitDeclareFunction(this); |
| 393 } | 390 } |
| 394 | 391 |
| 395 /// Invoke a continuation in tail position. | 392 /// Invoke a continuation in tail position. |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 /// Class.c(); | 584 /// Class.c(); |
| 588 /// } | 585 /// } |
| 589 /// | 586 /// |
| 590 /// If `field` had an initializer, possibly `null`, constructors `Class.a` and | 587 /// If `field` had an initializer, possibly `null`, constructors `Class.a` and |
| 591 /// `Class.b` would be invalid, and since `field` has no initializer | 588 /// `Class.b` would be invalid, and since `field` has no initializer |
| 592 /// constructor `Class.c` is invalid. We therefore need to distinguish the two | 589 /// constructor `Class.c` is invalid. We therefore need to distinguish the two |
| 593 /// cases. | 590 /// cases. |
| 594 bool get hasInitializer => body != null; | 591 bool get hasInitializer => body != null; |
| 595 } | 592 } |
| 596 | 593 |
| 594 /// Identifies a closure variable. |
| 595 class ClosureVariable extends Definition { |
| 596 /// Body of code that declares this closure variable. |
| 597 ExecutableElement host; |
| 598 Entity hint; |
| 599 |
| 600 ClosureVariable(this.host, this.hint); |
| 601 |
| 602 accept(Visitor v) => v.visitClosureVariable(this); |
| 603 } |
| 604 |
| 597 /// A function definition, consisting of parameters and a body. The parameters | 605 /// A function definition, consisting of parameters and a body. The parameters |
| 598 /// include a distinguished continuation parameter. | 606 /// include a distinguished continuation parameter. |
| 599 class FunctionDefinition extends Node | 607 class FunctionDefinition extends Node |
| 600 implements InteriorNode, ExecutableDefinition { | 608 implements InteriorNode, ExecutableDefinition { |
| 601 final FunctionElement element; | 609 final FunctionElement element; |
| 602 final Continuation returnContinuation; | 610 final Continuation returnContinuation; |
| 603 final List<Parameter> parameters; | 611 /// Mixed list of [Parameter]s and [ClosureVariable]s. |
| 612 final List<Definition> parameters; |
| 604 Expression body; | 613 Expression body; |
| 605 final List<ConstDeclaration> localConstants; | 614 final List<ConstDeclaration> localConstants; |
| 606 | 615 |
| 607 /// Values for optional parameters. | 616 /// Values for optional parameters. |
| 608 final List<ConstantExpression> defaultParameterValues; | 617 final List<ConstantExpression> defaultParameterValues; |
| 609 | 618 |
| 619 /// Closure variables declared by this function. |
| 620 final List<ClosureVariable> closureVariables; |
| 621 |
| 610 FunctionDefinition(this.element, this.returnContinuation, | 622 FunctionDefinition(this.element, this.returnContinuation, |
| 611 this.parameters, this.body, this.localConstants, | 623 this.parameters, this.body, this.localConstants, |
| 612 this.defaultParameterValues); | 624 this.defaultParameterValues, this.closureVariables); |
| 613 | 625 |
| 614 FunctionDefinition.abstract(this.element, | 626 FunctionDefinition.abstract(this.element, |
| 615 this.parameters, | 627 this.parameters, |
| 616 this.defaultParameterValues) | 628 this.defaultParameterValues) |
| 617 : this.returnContinuation = null, | 629 : this.returnContinuation = null, |
| 618 this.localConstants = const <ConstDeclaration>[]; | 630 this.localConstants = const <ConstDeclaration>[], |
| 631 this.closureVariables = const <ClosureVariable>[]; |
| 619 | 632 |
| 620 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); | 633 accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
| 621 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); | 634 applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
| 622 | 635 |
| 623 /// Returns `true` if this function is abstract or external. | 636 /// Returns `true` if this function is abstract or external. |
| 624 /// | 637 /// |
| 625 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] | 638 /// If `true`, [body] and [returnContinuation] are `null` and [localConstants] |
| 626 /// is empty. | 639 /// is empty. |
| 627 bool get isAbstract => body == null; | 640 bool get isAbstract => body == null; |
| 628 } | 641 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 // Definitions. | 676 // Definitions. |
| 664 T visitLiteralList(LiteralList node) => visitPrimitive(node); | 677 T visitLiteralList(LiteralList node) => visitPrimitive(node); |
| 665 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); | 678 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); |
| 666 T visitConstant(Constant node) => visitPrimitive(node); | 679 T visitConstant(Constant node) => visitPrimitive(node); |
| 667 T visitThis(This node) => visitPrimitive(node); | 680 T visitThis(This node) => visitPrimitive(node); |
| 668 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); | 681 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); |
| 669 T visitCreateFunction(CreateFunction node) => visitPrimitive(node); | 682 T visitCreateFunction(CreateFunction node) => visitPrimitive(node); |
| 670 T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); | 683 T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); |
| 671 T visitParameter(Parameter node) => visitPrimitive(node); | 684 T visitParameter(Parameter node) => visitPrimitive(node); |
| 672 T visitContinuation(Continuation node) => visitDefinition(node); | 685 T visitContinuation(Continuation node) => visitDefinition(node); |
| 686 T visitClosureVariable(ClosureVariable node) => visitDefinition(node); |
| 673 | 687 |
| 674 // Conditions. | 688 // Conditions. |
| 675 T visitIsTrue(IsTrue node) => visitCondition(node); | 689 T visitIsTrue(IsTrue node) => visitCondition(node); |
| 676 | 690 |
| 677 // JavaScript specific nodes. | 691 // JavaScript specific nodes. |
| 678 T visitIdentical(Identical node) => visitPrimitive(node); | 692 T visitIdentical(Identical node) => visitPrimitive(node); |
| 679 } | 693 } |
| 680 | 694 |
| 681 /// Recursively visits the entire CPS term, and calls abstract `process*` | 695 /// Recursively visits the entire CPS term, and calls abstract `process*` |
| 682 /// (i.e. `processLetPrim`) functions in pre-order. | 696 /// (i.e. `processLetPrim`) functions in pre-order. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 697 visitFieldDefinition(FieldDefinition node) { | 711 visitFieldDefinition(FieldDefinition node) { |
| 698 processFieldDefinition(node); | 712 processFieldDefinition(node); |
| 699 if (node.hasInitializer) { | 713 if (node.hasInitializer) { |
| 700 visit(node.body); | 714 visit(node.body); |
| 701 } | 715 } |
| 702 } | 716 } |
| 703 | 717 |
| 704 processFunctionDefinition(FunctionDefinition node) {} | 718 processFunctionDefinition(FunctionDefinition node) {} |
| 705 visitFunctionDefinition(FunctionDefinition node) { | 719 visitFunctionDefinition(FunctionDefinition node) { |
| 706 processFunctionDefinition(node); | 720 processFunctionDefinition(node); |
| 707 node.parameters.forEach(visitParameter); | 721 node.parameters.forEach(visit); |
| 708 if (!node.isAbstract) { | 722 if (!node.isAbstract) { |
| 709 visit(node.body); | 723 visit(node.body); |
| 710 } | 724 } |
| 711 } | 725 } |
| 712 | 726 |
| 713 // Expressions. | 727 // Expressions. |
| 714 | 728 |
| 715 processLetPrim(LetPrim node) {} | 729 processLetPrim(LetPrim node) {} |
| 716 visitLetPrim(LetPrim node) { | 730 visitLetPrim(LetPrim node) { |
| 717 processLetPrim(node); | 731 processLetPrim(node); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 | 837 |
| 824 processReifyTypeVar(ReifyTypeVar node) {} | 838 processReifyTypeVar(ReifyTypeVar node) {} |
| 825 visitReifyTypeVar(ReifyTypeVar node) => processReifyTypeVar(node); | 839 visitReifyTypeVar(ReifyTypeVar node) => processReifyTypeVar(node); |
| 826 | 840 |
| 827 processCreateFunction(CreateFunction node) {} | 841 processCreateFunction(CreateFunction node) {} |
| 828 visitCreateFunction(CreateFunction node) { | 842 visitCreateFunction(CreateFunction node) { |
| 829 processCreateFunction(node); | 843 processCreateFunction(node); |
| 830 visit(node.definition); | 844 visit(node.definition); |
| 831 } | 845 } |
| 832 | 846 |
| 847 processClosureVariable(node) {} |
| 848 visitClosureVariable(ClosureVariable node) { |
| 849 processClosureVariable(node); |
| 850 } |
| 851 |
| 833 processGetClosureVariable(GetClosureVariable node) {} | 852 processGetClosureVariable(GetClosureVariable node) {} |
| 834 visitGetClosureVariable(GetClosureVariable node) => | 853 visitGetClosureVariable(GetClosureVariable node) { |
| 835 processGetClosureVariable(node); | 854 processGetClosureVariable(node); |
| 855 } |
| 836 | 856 |
| 837 processParameter(Parameter node) {} | 857 processParameter(Parameter node) {} |
| 838 visitParameter(Parameter node) => processParameter(node); | 858 visitParameter(Parameter node) => processParameter(node); |
| 839 | 859 |
| 840 processContinuation(Continuation node) {} | 860 processContinuation(Continuation node) {} |
| 841 visitContinuation(Continuation node) { | 861 visitContinuation(Continuation node) { |
| 842 processContinuation(node); | 862 processContinuation(node); |
| 843 node.parameters.forEach(visitParameter); | 863 node.parameters.forEach(visitParameter); |
| 844 visit(node.body); | 864 visit(node.body); |
| 845 } | 865 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 void visitFieldDefinition(FieldDefinition node) { | 942 void visitFieldDefinition(FieldDefinition node) { |
| 923 if (node.hasInitializer) { | 943 if (node.hasInitializer) { |
| 924 visit(node.body); | 944 visit(node.body); |
| 925 } | 945 } |
| 926 } | 946 } |
| 927 | 947 |
| 928 void visitFunctionDefinition(FunctionDefinition node) { | 948 void visitFunctionDefinition(FunctionDefinition node) { |
| 929 if (!node.isAbstract) { | 949 if (!node.isAbstract) { |
| 930 visit(node.body); | 950 visit(node.body); |
| 931 } | 951 } |
| 932 node.parameters.forEach(allocate); // Assign indices to unused parameters. | 952 // Assign indices to unused parameters. |
| 953 for (Definition param in node.parameters) { |
| 954 if (param is Primitive) { |
| 955 allocate(param); |
| 956 } |
| 957 } |
| 933 } | 958 } |
| 934 | 959 |
| 935 void visitLetPrim(LetPrim node) { | 960 void visitLetPrim(LetPrim node) { |
| 936 visit(node.body); | 961 visit(node.body); |
| 937 release(node.primitive); | 962 release(node.primitive); |
| 938 visit(node.primitive); | 963 visit(node.primitive); |
| 939 } | 964 } |
| 940 | 965 |
| 941 void visitLetCont(LetCont node) { | 966 void visitLetCont(LetCont node) { |
| 942 visit(node.continuation); | 967 visit(node.continuation); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 } | 1058 } |
| 1034 | 1059 |
| 1035 // JavaScript specific nodes. | 1060 // JavaScript specific nodes. |
| 1036 | 1061 |
| 1037 void visitIdentical(Identical node) { | 1062 void visitIdentical(Identical node) { |
| 1038 visitReference(node.left); | 1063 visitReference(node.left); |
| 1039 visitReference(node.right); | 1064 visitReference(node.right); |
| 1040 } | 1065 } |
| 1041 } | 1066 } |
| 1042 | 1067 |
| OLD | NEW |