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

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

Issue 1021813002: Redo "Use an explicit 'this' parameter instead of 'This' nodes." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 /// A stack of singly-used labels that can be safely inlined at their use 60 /// A stack of singly-used labels that can be safely inlined at their use
61 /// site. 61 /// site.
62 /// 62 ///
63 /// Code for continuations with exactly one use is inlined at the use site. 63 /// Code for continuations with exactly one use is inlined at the use site.
64 /// This is not safe if the code is moved inside the scope of an exception 64 /// This is not safe if the code is moved inside the scope of an exception
65 /// handler (i.e., into a try block). We keep a stack of singly-referenced 65 /// handler (i.e., into a try block). We keep a stack of singly-referenced
66 /// continuations that are in scope without crossing a binding for a handler. 66 /// continuations that are in scope without crossing a binding for a handler.
67 List<cps_ir.Continuation> safeForInlining = <cps_ir.Continuation>[]; 67 List<cps_ir.Continuation> safeForInlining = <cps_ir.Continuation>[];
68 68
69 ExecutableElement currentElement; 69 ExecutableElement currentElement;
70 /// The 'this' Parameter for currentElement or the enclosing method.
71 cps_ir.Parameter thisParameter;
70 cps_ir.Continuation returnContinuation; 72 cps_ir.Continuation returnContinuation;
71 73
72 Builder parent; 74 Builder parent;
73 75
74 Builder(this.internalError, [this.parent]); 76 Builder(this.internalError, [this.parent]);
75 77
76 Builder createInnerBuilder() { 78 Builder createInnerBuilder() {
77 return new Builder(internalError, this); 79 return new Builder(internalError, this);
78 } 80 }
79 81
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 while (variables.length <= primitive.registerIndex) { 115 while (variables.length <= primitive.registerIndex) {
114 variables.add(new Variable(currentElement, primitive.hint)); 116 variables.add(new Variable(currentElement, primitive.hint));
115 } 117 }
116 return variables[primitive.registerIndex]; 118 return variables[primitive.registerIndex];
117 } 119 }
118 120
119 /// Obtains a reference to the tree Variable corresponding to the IR primitive 121 /// Obtains a reference to the tree Variable corresponding to the IR primitive
120 /// referred to by [reference]. 122 /// referred to by [reference].
121 /// This increments the reference count for the given variable, so the 123 /// This increments the reference count for the given variable, so the
122 /// returned expression must be used in the tree. 124 /// returned expression must be used in the tree.
123 VariableUse getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) { 125 Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
126 if (thisParameter != null && reference.definition == thisParameter) {
127 return new This();
128 }
124 Variable variable = getVariable(reference.definition); 129 Variable variable = getVariable(reference.definition);
125 if (variable == null) { 130 if (variable == null) {
126 // Note: this may fail because you forgot to implement a visit-function 131 // Note: this may fail because you forgot to implement a visit-function
127 // in the RegisterAllocator. 132 // in the RegisterAllocator.
128 internalError( 133 internalError(
129 CURRENT_ELEMENT_SPANNABLE, 134 CURRENT_ELEMENT_SPANNABLE,
130 "Reference to ${reference.definition} has no register"); 135 "Reference to ${reference.definition} has no register");
131 } 136 }
132 return new VariableUse(variable); 137 return new VariableUse(variable);
133 } 138 }
(...skipping 29 matching lines...) Expand all
163 Variable addFunctionParameter(cps_ir.Definition variable) { 168 Variable addFunctionParameter(cps_ir.Definition variable) {
164 if (variable is cps_ir.Parameter) { 169 if (variable is cps_ir.Parameter) {
165 return getVariable(variable); 170 return getVariable(variable);
166 } else { 171 } else {
167 return addMutableVariable(variable as cps_ir.MutableVariable); 172 return addMutableVariable(variable as cps_ir.MutableVariable);
168 } 173 }
169 } 174 }
170 175
171 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { 176 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) {
172 currentElement = node.element; 177 currentElement = node.element;
178 if (parent != null) {
179 // Local function's 'this' refers to enclosing method's 'this'
180 thisParameter = parent.thisParameter;
181 } else {
182 thisParameter = node.thisParameter;
183 }
173 List<Variable> parameters = 184 List<Variable> parameters =
174 node.parameters.map(addFunctionParameter).toList(); 185 node.parameters.map(addFunctionParameter).toList();
175 Statement body; 186 Statement body;
176 if (!node.isAbstract) { 187 if (!node.isAbstract) {
177 returnContinuation = node.body.returnContinuation; 188 returnContinuation = node.body.returnContinuation;
178 phiTempVar = new Variable(node.element, null); 189 phiTempVar = new Variable(node.element, null);
179 body = visit(node.body); 190 body = visit(node.body);
180 } 191 }
181 192
182 return new FunctionDefinition(node.element, parameters, 193 return new FunctionDefinition(node.element, parameters,
183 body, node.localConstants, node.defaultParameterValues); 194 body, node.localConstants, node.defaultParameterValues);
184 } 195 }
185 196
186 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { 197 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) {
187 currentElement = node.element; 198 currentElement = node.element;
199 thisParameter = node.thisParameter;
188 List<Variable> parameters = 200 List<Variable> parameters =
189 node.parameters.map(addFunctionParameter).toList(); 201 node.parameters.map(addFunctionParameter).toList();
190 List<Initializer> initializers; 202 List<Initializer> initializers;
191 Statement body; 203 Statement body;
192 if (!node.isAbstract) { 204 if (!node.isAbstract) {
193 initializers = node.initializers.map(visit).toList(); 205 initializers = node.initializers.map(visit).toList();
194 returnContinuation = node.body.returnContinuation; 206 returnContinuation = node.body.returnContinuation;
195 207
196 phiTempVar = new Variable(node.element, null); 208 phiTempVar = new Variable(node.element, null);
197 body = visit(node.body); 209 body = visit(node.body);
(...skipping 14 matching lines...) Expand all
212 return new List<Expression>.generate(args.length, 224 return new List<Expression>.generate(args.length,
213 (int index) => getVariableUse(args[index]), 225 (int index) => getVariableUse(args[index]),
214 growable: false); 226 growable: false);
215 } 227 }
216 228
217 /// Returns the list of variables corresponding to the arguments to a join 229 /// Returns the list of variables corresponding to the arguments to a join
218 /// continuation. 230 /// continuation.
219 /// 231 ///
220 /// The `readCount` of these variables will not be incremented. Instead, 232 /// The `readCount` of these variables will not be incremented. Instead,
221 /// [buildPhiAssignments] will handle the increment, if necessary. 233 /// [buildPhiAssignments] will handle the increment, if necessary.
222 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { 234 /* List<Variable> translatePhiArguments(List<cps_ir.Reference> args) {
223 return new List<Variable>.generate(args.length, 235 return new List<Variable>.generate(args.length,
224 (int index) => getVariable(args[index].definition), 236 (int index) => getVariable(args[index].definition),
225 growable: false); 237 growable: false);
226 } 238 }*/
227 239
228 Statement buildContinuationAssignment( 240 Statement buildContinuationAssignment(
229 cps_ir.Parameter parameter, 241 cps_ir.Parameter parameter,
230 Expression argument, 242 Expression argument,
231 Statement buildRest()) { 243 Statement buildRest()) {
232 Variable variable = getVariable(parameter); 244 Variable variable = getVariable(parameter);
233 Statement assignment; 245 Statement assignment;
234 if (variable == null) { 246 if (variable == null) {
235 assignment = new ExpressionStatement(argument, null); 247 assignment = new ExpressionStatement(argument, null);
236 } else { 248 } else {
237 assignment = new Assign(variable, argument, null); 249 assignment = new Assign(variable, argument, null);
238 } 250 }
239 assignment.next = buildRest(); 251 assignment.next = buildRest();
240 return assignment; 252 return assignment;
241 } 253 }
242 254
243 /// Simultaneously assigns each argument to the corresponding parameter, 255 /// Simultaneously assigns each argument to the corresponding parameter,
244 /// then continues at the statement created by [buildRest]. 256 /// then continues at the statement created by [buildRest].
245 Statement buildPhiAssignments( 257 Statement buildPhiAssignments(
246 List<cps_ir.Parameter> parameters, 258 List<cps_ir.Parameter> parameters,
247 List<Variable> arguments, 259 List<Expression> arguments,
248 Statement buildRest()) { 260 Statement buildRest()) {
249 assert(parameters.length == arguments.length); 261 assert(parameters.length == arguments.length);
250 // We want a parallel assignment to all parameters simultaneously. 262 // We want a parallel assignment to all parameters simultaneously.
251 // Since we do not have parallel assignments in dart_tree, we must linearize 263 // Since we do not have parallel assignments in dart_tree, we must linearize
252 // the assignments without attempting to read a previously-overwritten 264 // the assignments without attempting to read a previously-overwritten
253 // value. For example {x,y = y,x} cannot be linearized to {x = y; y = x}, 265 // value. For example {x,y = y,x} cannot be linearized to {x = y; y = x},
254 // for this we must introduce a temporary variable: {t = x; x = y; y = t}. 266 // for this we must introduce a temporary variable: {t = x; x = y; y = t}.
255 267
256 // [rightHand] is the inverse of [arguments], that is, it maps variables 268 // [rightHand] is the inverse of [arguments], that is, it maps variables
257 // to the assignments on which is occurs as the right-hand side. 269 // to the assignments on which is occurs as the right-hand side.
258 Map<Variable, List<int>> rightHand = <Variable, List<int>>{}; 270 Map<Variable, List<int>> rightHand = <Variable, List<int>>{};
259 for (int i = 0; i < parameters.length; i++) { 271 for (int i = 0; i < parameters.length; i++) {
260 Variable param = getVariable(parameters[i]); 272 Variable param = getVariable(parameters[i]);
261 Variable arg = arguments[i]; 273 Expression arg = arguments[i];
262 if (param == null || param == arg) { 274 if (arg is VariableUse) {
263 continue; // No assignment necessary. 275 if (param == null || param == arg.variable) {
276 // No assignment necessary.
277 --arg.variable.readCount;
278 continue;
279 }
280 // v1 = v0
281 List<int> list = rightHand[arg.variable];
282 if (list == null) {
283 rightHand[arg.variable] = list = <int>[];
284 }
285 list.add(i);
286 } else {
287 // v1 = this;
264 } 288 }
265 List<int> list = rightHand[arg];
266 if (list == null) {
267 rightHand[arg] = list = <int>[];
268 }
269 list.add(i);
270 } 289 }
271 290
272 Statement first, current; 291 Statement first, current;
273 void addAssignment(Variable dst, Variable src) { 292 void addAssignment(Variable dst, Expression src) {
274 if (first == null) { 293 if (first == null) {
275 first = current = new Assign(dst, new VariableUse(src), null); 294 first = current = new Assign(dst, src, null);
276 } else { 295 } else {
277 current = current.next = new Assign(dst, new VariableUse(src), null); 296 current = current.next = new Assign(dst, src, null);
278 } 297 }
279 } 298 }
280 299
281 List<Variable> assignmentSrc = new List<Variable>(parameters.length); 300 List<Expression> assignmentSrc = new List<Expression>(parameters.length);
282 List<bool> done = new List<bool>(parameters.length); 301 List<bool> done = new List<bool>.filled(parameters.length, false);
283 void visitAssignment(int i) { 302 void visitAssignment(int i) {
284 if (done[i] == true) { 303 if (done[i]) {
285 return; 304 return;
286 } 305 }
287 Variable param = getVariable(parameters[i]); 306 Variable param = getVariable(parameters[i]);
288 Variable arg = arguments[i]; 307 Expression arg = arguments[i];
289 if (param == null || param == arg) { 308 if (param == null || (arg is VariableUse && param == arg.variable)) {
290 return; // No assignment necessary. 309 return; // No assignment necessary.
291 } 310 }
292 if (assignmentSrc[i] != null) { 311 if (assignmentSrc[i] != null) {
293 // Cycle found; store argument in a temporary variable. 312 // Cycle found; store argument in a temporary variable.
294 // The temporary will then be used as right-hand side when the 313 // The temporary will then be used as right-hand side when the
295 // assignment gets added. 314 // assignment gets added.
296 if (assignmentSrc[i] != phiTempVar) { // Only move to temporary once. 315 VariableUse source = assignmentSrc[i];
297 assignmentSrc[i] = phiTempVar; 316 if (source.variable != phiTempVar) { // Only move to temporary once.
317 assignmentSrc[i] = new VariableUse(phiTempVar);
298 addAssignment(phiTempVar, arg); 318 addAssignment(phiTempVar, arg);
299 } 319 }
300 return; 320 return;
301 } 321 }
302 assignmentSrc[i] = arg; 322 assignmentSrc[i] = arg;
303 List<int> paramUses = rightHand[param]; 323 List<int> paramUses = rightHand[param];
304 if (paramUses != null) { 324 if (paramUses != null) {
305 for (int useIndex in paramUses) { 325 for (int useIndex in paramUses) {
306 visitAssignment(useIndex); 326 visitAssignment(useIndex);
307 } 327 }
308 } 328 }
309 addAssignment(param, assignmentSrc[i]); 329 addAssignment(param, assignmentSrc[i]);
310 done[i] = true; 330 done[i] = true;
311 } 331 }
312 332
313 for (int i = 0; i < parameters.length; i++) { 333 for (int i = 0; i < parameters.length; i++) {
314 if (done[i] == null) { 334 if (!done[i]) {
315 visitAssignment(i); 335 visitAssignment(i);
316 } 336 }
317 } 337 }
318 338
319 if (first == null) { 339 if (first == null) {
320 first = buildRest(); 340 first = buildRest();
321 } else { 341 } else {
322 current.next = buildRest(); 342 current.next = buildRest();
323 } 343 }
324 return first; 344 return first;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 // Invocations of the return continuation are translated to returns. 539 // Invocations of the return continuation are translated to returns.
520 // Other continuation invocations are replaced with assignments of the 540 // Other continuation invocations are replaced with assignments of the
521 // arguments to formal parameter variables, followed by the body if 541 // arguments to formal parameter variables, followed by the body if
522 // the continuation is singly reference or a break if it is multiply 542 // the continuation is singly reference or a break if it is multiply
523 // referenced. 543 // referenced.
524 cps_ir.Continuation cont = node.continuation.definition; 544 cps_ir.Continuation cont = node.continuation.definition;
525 if (cont == returnContinuation) { 545 if (cont == returnContinuation) {
526 assert(node.arguments.length == 1); 546 assert(node.arguments.length == 1);
527 return new Return(getVariableUse(node.arguments.single)); 547 return new Return(getVariableUse(node.arguments.single));
528 } else { 548 } else {
529 List<Variable> arguments = translatePhiArguments(node.arguments); 549 List<Expression> arguments = translateArguments(node.arguments);
530 return buildPhiAssignments(cont.parameters, arguments, 550 return buildPhiAssignments(cont.parameters, arguments,
531 () { 551 () {
532 // Translate invocations of recursive and non-recursive 552 // Translate invocations of recursive and non-recursive
533 // continuations differently. 553 // continuations differently.
534 // * Non-recursive continuations 554 // * Non-recursive continuations
535 // - If there is one use, translate the continuation body 555 // - If there is one use, translate the continuation body
536 // inline at the invocation site. 556 // inline at the invocation site.
537 // - If there are multiple uses, translate to Break. 557 // - If there are multiple uses, translate to Break.
538 // * Recursive continuations 558 // * Recursive continuations
539 // - There is a single non-recursive invocation. Translate 559 // - There is a single non-recursive invocation. Translate
(...skipping 28 matching lines...) Expand all
568 assert(cont.parameters.isEmpty); 588 assert(cont.parameters.isEmpty);
569 elseStatement = 589 elseStatement =
570 cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]); 590 cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]);
571 return new If(condition, thenStatement, elseStatement); 591 return new If(condition, thenStatement, elseStatement);
572 } 592 }
573 593
574 Expression visitConstant(cps_ir.Constant node) { 594 Expression visitConstant(cps_ir.Constant node) {
575 return new Constant(node.expression); 595 return new Constant(node.expression);
576 } 596 }
577 597
578 Expression visitThis(cps_ir.This node) {
579 return new This();
580 }
581
582 Expression visitReifyTypeVar(cps_ir.ReifyTypeVar node) { 598 Expression visitReifyTypeVar(cps_ir.ReifyTypeVar node) {
583 return new ReifyTypeVar(node.typeVariable); 599 return new ReifyTypeVar(node.typeVariable);
584 } 600 }
585 601
586 Expression visitLiteralList(cps_ir.LiteralList node) { 602 Expression visitLiteralList(cps_ir.LiteralList node) {
587 return new LiteralList( 603 return new LiteralList(
588 node.type, 604 node.type,
589 translateArguments(node.values)); 605 translateArguments(node.values));
590 } 606 }
591 607
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 } 656 }
641 657
642 Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) { 658 Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
643 return new ReifyRuntimeType(getVariableUse(node.value)); 659 return new ReifyRuntimeType(getVariableUse(node.value));
644 } 660 }
645 661
646 Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) { 662 Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) {
647 return new ReadTypeVariable(node.variable, getVariableUse(node.target)); 663 return new ReadTypeVariable(node.variable, getVariableUse(node.target));
648 } 664 }
649 } 665 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/dart_backend.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698