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 |