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

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

Issue 756383004: Refactored treatment of closure variables in dart2js CPS. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Comments Created 6 years 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 | Annotate | Revision Log
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 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698