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

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

Issue 831133004: Use closure conversion in new dart2js backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed redundant null-check Created 5 years, 11 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 | 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;
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 import '../cps_ir/optimizers.dart';
16 import '../closure.dart' show ClosureClassElement;
16 17
17 abstract class Node { 18 abstract class Node {
18 /// A pointer to the parent node. Is null until set by optimization passes. 19 /// A pointer to the parent node. Is null until set by optimization passes.
19 Node parent; 20 Node parent;
20 21
21 accept(Visitor visitor); 22 accept(Visitor visitor);
22 } 23 }
23 24
24 abstract class Expression extends Node { 25 abstract class Expression extends Node {
25 Expression plug(Expression expr) => throw 'impossible'; 26 Expression plug(Expression expr) => throw 'impossible';
(...skipping 26 matching lines...) Expand all
52 53
53 /// An expression that cannot throw or diverge and has no side-effects. 54 /// An expression that cannot throw or diverge and has no side-effects.
54 /// All primitives are named using the identity of the [Primitive] object. 55 /// All primitives are named using the identity of the [Primitive] object.
55 /// 56 ///
56 /// Primitives may allocate objects, this is not considered side-effect here. 57 /// Primitives may allocate objects, this is not considered side-effect here.
57 /// 58 ///
58 /// Although primitives may not mutate state, they may depend on state. 59 /// Although primitives may not mutate state, they may depend on state.
59 abstract class Primitive extends Definition<Primitive> { 60 abstract class Primitive extends Definition<Primitive> {
60 /// The [VariableElement] or [ParameterElement] from which the primitive 61 /// The [VariableElement] or [ParameterElement] from which the primitive
61 /// binding originated. 62 /// binding originated.
62 Element hint; 63 Entity hint;
63 64
64 /// Register in which the variable binding this primitive can be allocated. 65 /// Register in which the variable binding this primitive can be allocated.
65 /// Separate register spaces are used for primitives with different [element]. 66 /// Separate register spaces are used for primitives with different [element].
66 /// Assigned by [RegisterAllocator], is null before that phase. 67 /// Assigned by [RegisterAllocator], is null before that phase.
67 int registerIndex; 68 int registerIndex;
68 69
69 /// Use the given element as a hint for naming this primitive. 70 /// Use the given element as a hint for naming this primitive.
70 /// 71 ///
71 /// Has no effect if this primitive already has a non-null [element]. 72 /// Has no effect if this primitive already has a non-null [element].
72 void useElementAsHint(Element hint) { 73 void useElementAsHint(Entity hint) {
73 if (this.hint == null) { 74 if (this.hint == null) {
74 this.hint = hint; 75 this.hint = hint;
75 } 76 }
76 } 77 }
77 } 78 }
78 79
79 /// Operands to invocations and primitives are always variables. They point to 80 /// Operands to invocations and primitives are always variables. They point to
80 /// their definition and are doubly-linked into a list of occurrences. 81 /// their definition and are doubly-linked into a list of occurrences.
81 class Reference<T extends Definition<T>> { 82 class Reference<T extends Definition<T>> {
82 T definition; 83 T definition;
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 454
454 accept(Visitor visitor) => visitor.visitBranch(this); 455 accept(Visitor visitor) => visitor.visitBranch(this);
455 } 456 }
456 457
457 /// Marker interface for nodes that are only handled in the JavaScript backend. 458 /// Marker interface for nodes that are only handled in the JavaScript backend.
458 /// 459 ///
459 /// These nodes are generated by the unsugar step and need special translation 460 /// These nodes are generated by the unsugar step and need special translation
460 /// to the Tree IR, which is implemented in JsTreeBuilder. 461 /// to the Tree IR, which is implemented in JsTreeBuilder.
461 abstract class JsSpecificNode {} 462 abstract class JsSpecificNode {}
462 463
464 /// Directly assigns to a field on a given object.
465 class SetField extends Expression implements InteriorNode, JsSpecificNode {
466 final Reference<Primitive> object;
467 Element field;
468 final Reference<Primitive> value;
469 Expression body;
470
471 SetField(Primitive object, this.field, Primitive value)
472 : this.object = new Reference<Primitive>(object),
473 this.value = new Reference<Primitive>(value);
474
475 Expression plug(Expression expr) {
476 assert(body == null);
477 return body = expr;
478 }
479
480 accept(Visitor visitor) => visitor.visitSetField(this);
481 }
482
483 /// Directly reads from a field on a given object.
484 class GetField extends Primitive implements JsSpecificNode {
485 final Reference<Primitive> object;
486 Element field;
487
488 GetField(Primitive object, this.field)
489 : this.object = new Reference<Primitive>(object);
490
491 accept(Visitor visitor) => visitor.visitGetField(this);
492 }
493
494 /// Creates an object for holding boxed variables captured by a closure.
495 class CreateBox extends Primitive implements JsSpecificNode {
496 accept(Visitor visitor) => visitor.visitCreateBox(this);
497 }
498
499 /// Instantiates a synthetic class created by closure conversion.
500 class CreateClosureClass extends Primitive implements JsSpecificNode {
501 final ClosureClassElement classElement;
502
503 /// Values and boxes for locals captured by the closure.
504 /// The order corresponds to [ClosureClassElement.closureFields].
505 final List<Reference<Primitive>> arguments;
506
507 CreateClosureClass(this.classElement, List<Primitive> arguments)
508 : this.arguments = _referenceList(arguments);
509
510 accept(Visitor visitor) => visitor.visitCreateClosureClass(this);
511 }
512
463 class Identical extends Primitive implements JsSpecificNode { 513 class Identical extends Primitive implements JsSpecificNode {
464 final Reference<Primitive> left; 514 final Reference<Primitive> left;
465 final Reference<Primitive> right; 515 final Reference<Primitive> right;
466 Identical(Primitive left, Primitive right) 516 Identical(Primitive left, Primitive right)
467 : left = new Reference<Primitive>(left), 517 : left = new Reference<Primitive>(left),
468 right = new Reference<Primitive>(right); 518 right = new Reference<Primitive>(right);
469 accept(Visitor visitor) => visitor.visitIdentical(this); 519 accept(Visitor visitor) => visitor.visitIdentical(this);
470 } 520 }
471 521
472 class Interceptor extends Primitive implements JsSpecificNode { 522 class Interceptor extends Primitive implements JsSpecificNode {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 /// Create a non-recursive function. 587 /// Create a non-recursive function.
538 class CreateFunction extends Primitive { 588 class CreateFunction extends Primitive {
539 final FunctionDefinition definition; 589 final FunctionDefinition definition;
540 590
541 CreateFunction(this.definition); 591 CreateFunction(this.definition);
542 592
543 accept(Visitor visitor) => visitor.visitCreateFunction(this); 593 accept(Visitor visitor) => visitor.visitCreateFunction(this);
544 } 594 }
545 595
546 class Parameter extends Primitive { 596 class Parameter extends Primitive {
547 Parameter(Element element) { 597 Parameter(Entity hint) {
548 super.hint = element; 598 super.hint = hint;
549 } 599 }
550 600
551 accept(Visitor visitor) => visitor.visitParameter(this); 601 accept(Visitor visitor) => visitor.visitParameter(this);
552 } 602 }
553 603
554 /// Continuations are normally bound by 'let cont'. A continuation with one 604 /// Continuations are normally bound by 'let cont'. A continuation with one
555 /// parameter and no body is used to represent a function's return continuation. 605 /// parameter and no body is used to represent a function's return continuation.
556 /// The return continuation is bound by the Function, not by 'let cont'. 606 /// The return continuation is bound by the Function, not by 'let cont'.
557 class Continuation extends Definition<Continuation> implements InteriorNode { 607 class Continuation extends Definition<Continuation> implements InteriorNode {
558 final List<Parameter> parameters; 608 final List<Parameter> parameters;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 T visitInvokeStatic(InvokeStatic node) => visitExpression(node); 800 T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
751 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); 801 T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node);
752 T visitInvokeMethod(InvokeMethod node) => visitExpression(node); 802 T visitInvokeMethod(InvokeMethod node) => visitExpression(node);
753 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node); 803 T visitInvokeSuperMethod(InvokeSuperMethod node) => visitExpression(node);
754 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node); 804 T visitInvokeConstructor(InvokeConstructor node) => visitExpression(node);
755 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); 805 T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node);
756 T visitBranch(Branch node) => visitExpression(node); 806 T visitBranch(Branch node) => visitExpression(node);
757 T visitTypeOperator(TypeOperator node) => visitExpression(node); 807 T visitTypeOperator(TypeOperator node) => visitExpression(node);
758 T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node); 808 T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node);
759 T visitDeclareFunction(DeclareFunction node) => visitExpression(node); 809 T visitDeclareFunction(DeclareFunction node) => visitExpression(node);
810 T visitSetField(SetField node) => visitExpression(node);
760 811
761 // Definitions. 812 // Definitions.
762 T visitLiteralList(LiteralList node) => visitPrimitive(node); 813 T visitLiteralList(LiteralList node) => visitPrimitive(node);
763 T visitLiteralMap(LiteralMap node) => visitPrimitive(node); 814 T visitLiteralMap(LiteralMap node) => visitPrimitive(node);
764 T visitConstant(Constant node) => visitPrimitive(node); 815 T visitConstant(Constant node) => visitPrimitive(node);
765 T visitThis(This node) => visitPrimitive(node); 816 T visitThis(This node) => visitPrimitive(node);
766 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); 817 T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node);
767 T visitCreateFunction(CreateFunction node) => visitPrimitive(node); 818 T visitCreateFunction(CreateFunction node) => visitPrimitive(node);
768 T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); 819 T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node);
769 T visitParameter(Parameter node) => visitPrimitive(node); 820 T visitParameter(Parameter node) => visitPrimitive(node);
770 T visitContinuation(Continuation node) => visitDefinition(node); 821 T visitContinuation(Continuation node) => visitDefinition(node);
771 T visitClosureVariable(ClosureVariable node) => visitDefinition(node); 822 T visitClosureVariable(ClosureVariable node) => visitDefinition(node);
823 T visitGetField(GetField node) => visitDefinition(node);
824 T visitCreateBox(CreateBox node) => visitDefinition(node);
825 T visitCreateClosureClass(CreateClosureClass node) => visitDefinition(node);
772 826
773 // Conditions. 827 // Conditions.
774 T visitIsTrue(IsTrue node) => visitCondition(node); 828 T visitIsTrue(IsTrue node) => visitCondition(node);
775 829
776 // JavaScript specific nodes. 830 // JavaScript specific nodes.
777 T visitIdentical(Identical node) => visitPrimitive(node); 831 T visitIdentical(Identical node) => visitPrimitive(node);
778 T visitInterceptor(Interceptor node) => visitPrimitive(node); 832 T visitInterceptor(Interceptor node) => visitPrimitive(node);
779 } 833 }
780 834
781 /// Recursively visits the entire CPS term, and calls abstract `process*` 835 /// Recursively visits the entire CPS term, and calls abstract `process*`
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 processIdentical(node); 1045 processIdentical(node);
992 processReference(node.left); 1046 processReference(node.left);
993 processReference(node.right); 1047 processReference(node.right);
994 } 1048 }
995 1049
996 processInterceptor(Interceptor node) {} 1050 processInterceptor(Interceptor node) {}
997 visitInterceptor(Interceptor node) { 1051 visitInterceptor(Interceptor node) {
998 processInterceptor(node); 1052 processInterceptor(node);
999 processReference(node.input); 1053 processReference(node.input);
1000 } 1054 }
1055
1056 processCreateClosureClass(CreateClosureClass node) {}
1057 visitCreateClosureClass(CreateClosureClass node) {
1058 processCreateClosureClass(node);
1059 node.arguments.forEach(processReference);
1060 }
1061
1062 processSetField(SetField node) {}
1063 visitSetField(SetField node) {
1064 processSetField(node);
1065 processReference(node.object);
1066 processReference(node.value);
1067 visit(node.body);
1068 }
1069
1070 processGetField(GetField node) {}
1071 visitGetField(GetField node) {
1072 processGetField(node);
1073 processReference(node.object);
1074 }
1075
1076 processCreateBox(CreateBox node) {}
1077 visitCreateBox(CreateBox node) {
1078 processCreateBox(node);
1079 }
1001 } 1080 }
1002 1081
1003 /// Keeps track of currently unused register indices. 1082 /// Keeps track of currently unused register indices.
1004 class RegisterArray { 1083 class RegisterArray {
1005 int nextIndex = 0; 1084 int nextIndex = 0;
1006 final List<int> freeStack = <int>[]; 1085 final List<int> freeStack = <int>[];
1007 1086
1008 /// Returns an index that is currently unused. 1087 /// Returns an index that is currently unused.
1009 int makeIndex() { 1088 int makeIndex() {
1010 if (freeStack.isEmpty) { 1089 if (freeStack.isEmpty) {
1011 return nextIndex++; 1090 return nextIndex++;
1012 } else { 1091 } else {
1013 return freeStack.removeLast(); 1092 return freeStack.removeLast();
1014 } 1093 }
1015 } 1094 }
1016 1095
1017 void releaseIndex(int index) { 1096 void releaseIndex(int index) {
1018 freeStack.add(index); 1097 freeStack.add(index);
1019 } 1098 }
1020 } 1099 }
1021 1100
1022 /// Assigns indices to each primitive in the IR such that primitives that are 1101 /// Assigns indices to each primitive in the IR such that primitives that are
1023 /// live simultaneously never get assigned the same index. 1102 /// live simultaneously never get assigned the same index.
1024 /// This information is used by the dart tree builder to generate fewer 1103 /// This information is used by the dart tree builder to generate fewer
1025 /// redundant variables. 1104 /// redundant variables.
1026 /// Currently, the liveness analysis is very simple and is often inadequate 1105 /// Currently, the liveness analysis is very simple and is often inadequate
1027 /// for removing all of the redundant variables. 1106 /// for removing all of the redundant variables.
1028 class RegisterAllocator extends Visitor { 1107 class RegisterAllocator extends Visitor {
1029 /// Separate register spaces for each source-level variable/parameter. 1108 /// Separate register spaces for each source-level variable/parameter.
1030 /// Note that null is used as key for primitives without elements. 1109 /// Note that null is used as key for primitives without hints.
1031 final Map<Element, RegisterArray> elementRegisters = 1110 final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{};
1032 <Element, RegisterArray>{};
1033 1111
1034 RegisterArray getRegisterArray(Element element) { 1112 RegisterArray getRegisterArray(Local local) {
1035 RegisterArray registers = elementRegisters[element]; 1113 RegisterArray registers = elementRegisters[local];
1036 if (registers == null) { 1114 if (registers == null) {
1037 registers = new RegisterArray(); 1115 registers = new RegisterArray();
1038 elementRegisters[element] = registers; 1116 elementRegisters[local] = registers;
1039 } 1117 }
1040 return registers; 1118 return registers;
1041 } 1119 }
1042 1120
1043 void allocate(Primitive primitive) { 1121 void allocate(Primitive primitive) {
1044 if (primitive.registerIndex == null) { 1122 if (primitive.registerIndex == null) {
1045 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex(); 1123 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex();
1046 } 1124 }
1047 } 1125 }
1048 1126
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 release(node.parameters[i]); 1274 release(node.parameters[i]);
1197 } 1275 }
1198 } 1276 }
1199 1277
1200 void visitIsTrue(IsTrue node) { 1278 void visitIsTrue(IsTrue node) {
1201 visitReference(node.value); 1279 visitReference(node.value);
1202 } 1280 }
1203 1281
1204 // JavaScript specific nodes. 1282 // JavaScript specific nodes.
1205 1283
1284 void visitSetField(SetField node) {
1285 visit(node.body);
1286 visitReference(node.value);
1287 visitReference(node.object);
1288 }
1289
1290 void visitGetField(GetField node) {
1291 visitReference(node.object);
1292 }
1293
1294 void visitCreateBox(CreateBox node) {
1295 }
1296
1297 void visitCreateClosureClass(CreateClosureClass node) {
1298 node.arguments.forEach(visitReference);
1299 }
1300
1206 void visitIdentical(Identical node) { 1301 void visitIdentical(Identical node) {
1207 visitReference(node.left); 1302 visitReference(node.left);
1208 visitReference(node.right); 1303 visitReference(node.right);
1209 } 1304 }
1210 1305
1211 void visitInterceptor(Interceptor node) { 1306 void visitInterceptor(Interceptor node) {
1212 visitReference(node.input); 1307 visitReference(node.input);
1213 } 1308 }
1214 } 1309 }
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