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

Side by Side Diff: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart

Issue 1007103003: cps-ir: Merge variables based on set-based liveness and graph coloring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 5 years, 8 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library tree_ir_builder; 5 library tree_ir_builder;
6 6
7 import '../dart2jslib.dart' as dart2js; 7 import '../dart2jslib.dart' as dart2js;
8 import '../dart_types.dart'; 8 import '../dart_types.dart';
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; 10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
(...skipping 28 matching lines...) Expand all
39 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree 39 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree
40 * control-flow recognition. 40 * control-flow recognition.
41 * 41 *
42 * Otherwise, the output of Builder looks very much like the input. In 42 * Otherwise, the output of Builder looks very much like the input. In
43 * particular, intermediate values and blocks used for local control flow are 43 * particular, intermediate values and blocks used for local control flow are
44 * still all named. 44 * still all named.
45 */ 45 */
46 class Builder implements cps_ir.Visitor<Node> { 46 class Builder implements cps_ir.Visitor<Node> {
47 final dart2js.InternalErrorFunction internalError; 47 final dart2js.InternalErrorFunction internalError;
48 48
49 /// Maps variable/parameter elements to the Tree variables that represent it. 49 final Map<cps_ir.Primitive, Variable> primitive2variable =
50 final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{}; 50 <cps_ir.Primitive, Variable>{};
51 51 final Map<cps_ir.MutableVariable, Variable> mutable2variable =
52 /// Like [local2variables], except for mutable variables.
53 final Map<cps_ir.MutableVariable, Variable> local2mutable =
54 <cps_ir.MutableVariable, Variable>{}; 52 <cps_ir.MutableVariable, Variable>{};
55 53
56 // Continuations with more than one use are replaced with Tree labels. This 54 // Continuations with more than one use are replaced with Tree labels. This
57 // is the mapping from continuations to labels. 55 // is the mapping from continuations to labels.
58 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; 56 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{};
59 57
60 /// A stack of singly-used labels that can be safely inlined at their use 58 /// A stack of singly-used labels that can be safely inlined at their use
61 /// site. 59 /// site.
62 /// 60 ///
63 /// Code for continuations with exactly one use is inlined at the use site. 61 /// Code for continuations with exactly one use is inlined at the use site.
(...skipping 14 matching lines...) Expand all
78 Builder createInnerBuilder() { 76 Builder createInnerBuilder() {
79 return new Builder(internalError, this); 77 return new Builder(internalError, this);
80 } 78 }
81 79
82 /// Variable used in [buildPhiAssignments] as a temporary when swapping 80 /// Variable used in [buildPhiAssignments] as a temporary when swapping
83 /// variables. 81 /// variables.
84 Variable phiTempVar; 82 Variable phiTempVar;
85 83
86 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { 84 Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
87 assert(irVariable.host == currentElement); 85 assert(irVariable.host == currentElement);
88 assert(!local2mutable.containsKey(irVariable)); 86 assert(!mutable2variable.containsKey(irVariable));
89 Variable variable = new Variable(currentElement, irVariable.hint); 87 Variable variable = new Variable(currentElement, irVariable.hint);
90 local2mutable[irVariable] = variable; 88 mutable2variable[irVariable] = variable;
91 return variable; 89 return variable;
92 } 90 }
93 91
94 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) { 92 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) {
95 if (mutableVariable.host != currentElement) { 93 if (mutableVariable.host != currentElement) {
96 return parent.getMutableVariable(mutableVariable)..isCaptured = true; 94 return parent.getMutableVariable(mutableVariable)..isCaptured = true;
97 } 95 }
98 return local2mutable[mutableVariable]; 96 return mutable2variable[mutableVariable];
99 } 97 }
100 98
101 VariableUse getMutableVariableUse( 99 VariableUse getMutableVariableUse(
102 cps_ir.Reference<cps_ir.MutableVariable> reference) { 100 cps_ir.Reference<cps_ir.MutableVariable> reference) {
103 Variable variable = getMutableVariable(reference.definition); 101 Variable variable = getMutableVariable(reference.definition);
104 return new VariableUse(variable); 102 return new VariableUse(variable);
105 } 103 }
106 104
107 /// Obtains the variable representing the given primitive. Returns null for 105 /// Obtains the variable representing the given primitive. Returns null for
108 /// primitives that have no reference and do not need a variable. 106 /// primitives that have no reference and do not need a variable.
109 Variable getVariable(cps_ir.Primitive primitive) { 107 Variable getVariable(cps_ir.Primitive primitive) {
110 if (primitive.registerIndex == null) { 108 return primitive2variable.putIfAbsent(primitive,
111 return null; // variable is unused 109 () => new Variable(currentElement, primitive.hint));
112 }
113 List<Variable> variables = local2variables.putIfAbsent(primitive.hint,
114 () => <Variable>[]);
115 while (variables.length <= primitive.registerIndex) {
116 variables.add(new Variable(currentElement, primitive.hint));
117 }
118 return variables[primitive.registerIndex];
119 } 110 }
120 111
121 /// Obtains a reference to the tree Variable corresponding to the IR primitive 112 /// Obtains a reference to the tree Variable corresponding to the IR primitive
122 /// referred to by [reference]. 113 /// referred to by [reference].
123 /// This increments the reference count for the given variable, so the 114 /// This increments the reference count for the given variable, so the
124 /// returned expression must be used in the tree. 115 /// returned expression must be used in the tree.
125 Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) { 116 Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
126 if (thisParameter != null && reference.definition == thisParameter) { 117 if (thisParameter != null && reference.definition == thisParameter) {
127 return new This(); 118 return new This();
128 } 119 }
129 Variable variable = getVariable(reference.definition); 120 return new VariableUse(getVariable(reference.definition));
130 if (variable == null) {
131 // Note: this may fail because you forgot to implement a visit-function
132 // in the RegisterAllocator.
133 internalError(
134 CURRENT_ELEMENT_SPANNABLE,
135 "Reference to ${reference.definition} has no register");
136 }
137 return new VariableUse(variable);
138 } 121 }
139 122
140 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { 123 ExecutableDefinition build(cps_ir.ExecutableDefinition node) {
124 // TODO(asgerf): Don't have build AND buildXXX as public API.
141 if (node is cps_ir.FieldDefinition) { 125 if (node is cps_ir.FieldDefinition) {
142 return buildField(node); 126 return buildField(node);
143 } else if (node is cps_ir.ConstructorDefinition) { 127 } else if (node is cps_ir.ConstructorDefinition) {
144 return buildConstructor(node); 128 return buildConstructor(node);
145 } else { 129 } else {
146 assert(dart2js.invariant( 130 assert(dart2js.invariant(
147 CURRENT_ELEMENT_SPANNABLE, 131 CURRENT_ELEMENT_SPANNABLE,
148 node is cps_ir.FunctionDefinition, 132 node is cps_ir.FunctionDefinition,
149 message: 'expected FunctionDefinition or FieldDefinition, ' 133 message: 'expected FunctionDefinition or FieldDefinition, '
150 ' found $node')); 134 ' found $node'));
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 List<Expression> translateArguments(List<cps_ir.Reference> args) { 207 List<Expression> translateArguments(List<cps_ir.Reference> args) {
224 return new List<Expression>.generate(args.length, 208 return new List<Expression>.generate(args.length,
225 (int index) => getVariableUse(args[index]), 209 (int index) => getVariableUse(args[index]),
226 growable: false); 210 growable: false);
227 } 211 }
228 212
229 Statement buildContinuationAssignment( 213 Statement buildContinuationAssignment(
230 cps_ir.Parameter parameter, 214 cps_ir.Parameter parameter,
231 Expression argument, 215 Expression argument,
232 Statement buildRest()) { 216 Statement buildRest()) {
233 Variable variable = getVariable(parameter);
234 Statement assignment; 217 Statement assignment;
235 if (variable == null) { 218 if (parameter.hasAtLeastOneUse) {
219 Variable variable = getVariable(parameter);
220 assignment = new Assign(variable, argument, null);
221 } else {
236 assignment = new ExpressionStatement(argument, null); 222 assignment = new ExpressionStatement(argument, null);
237 } else {
238 assignment = new Assign(variable, argument, null);
239 } 223 }
240 assignment.next = buildRest(); 224 assignment.next = buildRest();
241 return assignment; 225 return assignment;
242 } 226 }
243 227
244 /// Simultaneously assigns each argument to the corresponding parameter, 228 /// Simultaneously assigns each argument to the corresponding parameter,
245 /// then continues at the statement created by [buildRest]. 229 /// then continues at the statement created by [buildRest].
246 Statement buildPhiAssignments( 230 Statement buildPhiAssignments(
247 List<cps_ir.Parameter> parameters, 231 List<cps_ir.Parameter> parameters,
248 List<Expression> arguments, 232 List<Expression> arguments,
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 return new ReadTypeVariable(node.variable, getVariableUse(node.target)); 639 return new ReadTypeVariable(node.variable, getVariableUse(node.target));
656 } 640 }
657 641
658 @override 642 @override
659 Node visitTypeExpression(cps_ir.TypeExpression node) { 643 Node visitTypeExpression(cps_ir.TypeExpression node) {
660 return new TypeExpression( 644 return new TypeExpression(
661 node.dartType, 645 node.dartType,
662 node.arguments.map(getVariableUse).toList()); 646 node.arguments.map(getVariableUse).toList());
663 } 647 }
664 } 648 }
649
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698