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

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

Issue 958603002: Added VariableUse expression to tree IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated docs regarding catch parameters 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { 84 Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
85 if (irVariable.host != currentElement) { 85 if (irVariable.host != currentElement) {
86 return parent.addMutableVariable(irVariable); 86 return parent.addMutableVariable(irVariable);
87 } 87 }
88 assert(!local2mutable.containsKey(irVariable)); 88 assert(!local2mutable.containsKey(irVariable));
89 Variable variable = new Variable(currentElement, irVariable.hint); 89 Variable variable = new Variable(currentElement, irVariable.hint);
90 local2mutable[irVariable] = variable; 90 local2mutable[irVariable] = variable;
91 return variable; 91 return variable;
92 } 92 }
93 93
94 Variable getMutableVariableReference( 94 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) {
95 if (mutableVariable.host != currentElement) {
96 return parent.getMutableVariable(mutableVariable);
97 }
98 return local2mutable[mutableVariable];
99 }
100
101 VariableUse getMutableVariableUse(
95 cps_ir.Reference<cps_ir.MutableVariable> reference) { 102 cps_ir.Reference<cps_ir.MutableVariable> reference) {
96 if (reference.definition.host != currentElement) { 103 Variable variable = getMutableVariable(reference.definition);
97 return parent.getMutableVariableReference(reference); 104 return new VariableUse(variable);
98 }
99 Variable variable = local2mutable[reference.definition];
100 ++variable.readCount;
101 return variable;
102 } 105 }
103 106
104 /// Obtains the variable representing the given primitive. Returns null for 107 /// Obtains the variable representing the given primitive. Returns null for
105 /// primitives that have no reference and do not need a variable. 108 /// primitives that have no reference and do not need a variable.
106 Variable getVariable(cps_ir.Primitive primitive) { 109 Variable getVariable(cps_ir.Primitive primitive) {
107 if (primitive.registerIndex == null) { 110 if (primitive.registerIndex == null) {
108 return null; // variable is unused 111 return null; // variable is unused
109 } 112 }
110 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, 113 List<Variable> variables = local2variables.putIfAbsent(primitive.hint,
111 () => <Variable>[]); 114 () => <Variable>[]);
112 while (variables.length <= primitive.registerIndex) { 115 while (variables.length <= primitive.registerIndex) {
113 variables.add(new Variable(currentElement, primitive.hint)); 116 variables.add(new Variable(currentElement, primitive.hint));
114 } 117 }
115 return variables[primitive.registerIndex]; 118 return variables[primitive.registerIndex];
116 } 119 }
117 120
118 /// 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
119 /// referred to by [reference]. 122 /// referred to by [reference].
120 /// This increments the reference count for the given variable, so the 123 /// This increments the reference count for the given variable, so the
121 /// returned expression must be used in the tree. 124 /// returned expression must be used in the tree.
122 Expression getVariableReference(cps_ir.Reference reference) { 125 VariableUse getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
123 Variable variable = getVariable(reference.definition); 126 Variable variable = getVariable(reference.definition);
124 if (variable == null) { 127 if (variable == null) {
125 internalError( 128 internalError(
126 CURRENT_ELEMENT_SPANNABLE, 129 CURRENT_ELEMENT_SPANNABLE,
127 "Reference to ${reference.definition} has no register"); 130 "Reference to ${reference.definition} has no register");
128 } 131 }
129 ++variable.readCount; 132 return new VariableUse(variable);
130 return variable;
131 } 133 }
132 134
133 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { 135 ExecutableDefinition build(cps_ir.ExecutableDefinition node) {
134 if (node is cps_ir.FieldDefinition) { 136 if (node is cps_ir.FieldDefinition) {
135 return buildField(node); 137 return buildField(node);
136 } else if (node is cps_ir.ConstructorDefinition) { 138 } else if (node is cps_ir.ConstructorDefinition) {
137 return buildConstructor(node); 139 return buildConstructor(node);
138 } else { 140 } else {
139 assert(dart2js.invariant( 141 assert(dart2js.invariant(
140 CURRENT_ELEMENT_SPANNABLE, 142 CURRENT_ELEMENT_SPANNABLE,
(...skipping 20 matching lines...) Expand all
161 Variable addFunctionParameter(cps_ir.Definition variable) { 163 Variable addFunctionParameter(cps_ir.Definition variable) {
162 if (variable is cps_ir.Parameter) { 164 if (variable is cps_ir.Parameter) {
163 return getVariable(variable); 165 return getVariable(variable);
164 } else { 166 } else {
165 return addMutableVariable(variable as cps_ir.MutableVariable); 167 return addMutableVariable(variable as cps_ir.MutableVariable);
166 } 168 }
167 } 169 }
168 170
169 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { 171 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) {
170 currentElement = node.element; 172 currentElement = node.element;
171 List<Variable> parameters = <Variable>[]; 173 List<Variable> parameters =
172 for (cps_ir.Definition p in node.parameters) { 174 node.parameters.map(addFunctionParameter).toList();
173 Variable parameter = addFunctionParameter(p);
174 assert(parameter != null);
175 ++parameter.writeCount; // Being a parameter counts as a write.
176 parameters.add(parameter);
177 }
178
179 Statement body; 175 Statement body;
180 if (!node.isAbstract) { 176 if (!node.isAbstract) {
181 returnContinuation = node.body.returnContinuation; 177 returnContinuation = node.body.returnContinuation;
182 phiTempVar = new Variable(node.element, null); 178 phiTempVar = new Variable(node.element, null);
183 body = visit(node.body); 179 body = visit(node.body);
184 } 180 }
185 181
186 return new FunctionDefinition(node.element, parameters, 182 return new FunctionDefinition(node.element, parameters,
187 body, node.localConstants, node.defaultParameterValues); 183 body, node.localConstants, node.defaultParameterValues);
188 } 184 }
189 185
190 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { 186 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) {
191 currentElement = node.element; 187 currentElement = node.element;
192 List<Variable> parameters = <Variable>[]; 188 List<Variable> parameters =
193 for (cps_ir.Definition p in node.parameters) { 189 node.parameters.map(addFunctionParameter).toList();
194 Variable parameter = addFunctionParameter(p);
195 assert(parameter != null);
196 ++parameter.writeCount; // Being a parameter counts as a write.
197 parameters.add(parameter);
198 }
199 List<Initializer> initializers; 190 List<Initializer> initializers;
200 Statement body; 191 Statement body;
201 if (!node.isAbstract) { 192 if (!node.isAbstract) {
202 initializers = node.initializers.map(visit).toList(); 193 initializers = node.initializers.map(visit).toList();
203 returnContinuation = node.body.returnContinuation; 194 returnContinuation = node.body.returnContinuation;
204 195
205 phiTempVar = new Variable(node.element, null); 196 phiTempVar = new Variable(node.element, null);
206 body = visit(node.body); 197 body = visit(node.body);
207 } 198 }
208 199
209 return new ConstructorDefinition(node.element, parameters, 200 return new ConstructorDefinition(node.element, parameters,
210 body, initializers, node.localConstants, node.defaultParameterValues); 201 body, initializers, node.localConstants, node.defaultParameterValues);
211 } 202 }
212 203
213 /// Returns a list of variables corresponding to the arguments to a method 204 /// Returns a list of variables corresponding to the arguments to a method
214 /// call or similar construct. 205 /// call or similar construct.
215 /// 206 ///
216 /// The `readCount` for these variables will be incremented. 207 /// The `readCount` for these variables will be incremented.
217 /// 208 ///
218 /// The list will be typed as a list of [Expression] to allow inplace updates 209 /// The list will be typed as a list of [Expression] to allow inplace updates
219 /// on the list during the rewrite phases. 210 /// on the list during the rewrite phases.
220 List<Expression> translateArguments(List<cps_ir.Reference> args) { 211 List<Expression> translateArguments(List<cps_ir.Reference> args) {
221 return new List<Expression>.generate(args.length, 212 return new List<Expression>.generate(args.length,
222 (int index) => getVariableReference(args[index]), 213 (int index) => getVariableUse(args[index]),
223 growable: false); 214 growable: false);
224 } 215 }
225 216
226 /// Returns the list of variables corresponding to the arguments to a join 217 /// Returns the list of variables corresponding to the arguments to a join
227 /// continuation. 218 /// continuation.
228 /// 219 ///
229 /// The `readCount` of these variables will not be incremented. Instead, 220 /// The `readCount` of these variables will not be incremented. Instead,
230 /// [buildPhiAssignments] will handle the increment, if necessary. 221 /// [buildPhiAssignments] will handle the increment, if necessary.
231 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { 222 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) {
232 return new List<Variable>.generate(args.length, 223 return new List<Variable>.generate(args.length,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 264 }
274 List<int> list = rightHand[arg]; 265 List<int> list = rightHand[arg];
275 if (list == null) { 266 if (list == null) {
276 rightHand[arg] = list = <int>[]; 267 rightHand[arg] = list = <int>[];
277 } 268 }
278 list.add(i); 269 list.add(i);
279 } 270 }
280 271
281 Statement first, current; 272 Statement first, current;
282 void addAssignment(Variable dst, Variable src) { 273 void addAssignment(Variable dst, Variable src) {
283 ++src.readCount;
284 // `dst.writeCount` will be updated by the Assign constructor.
285 if (first == null) { 274 if (first == null) {
286 first = current = new Assign(dst, src, null); 275 first = current = new Assign(dst, new VariableUse(src), null);
287 } else { 276 } else {
288 current = current.next = new Assign(dst, src, null); 277 current = current.next = new Assign(dst, new VariableUse(src), null);
289 } 278 }
290 } 279 }
291 280
292 List<Variable> assignmentSrc = new List<Variable>(parameters.length); 281 List<Variable> assignmentSrc = new List<Variable>(parameters.length);
293 List<bool> done = new List<bool>(parameters.length); 282 List<bool> done = new List<bool>(parameters.length);
294 void visitAssignment(int i) { 283 void visitAssignment(int i) {
295 if (done[i] == true) { 284 if (done[i] == true) {
296 return; 285 return;
297 } 286 }
298 Variable param = getVariable(parameters[i]); 287 Variable param = getVariable(parameters[i]);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 } 415 }
427 416
428 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { 417 Statement visitInvokeStatic(cps_ir.InvokeStatic node) {
429 // Calls are translated to direct style. 418 // Calls are translated to direct style.
430 List<Expression> arguments = translateArguments(node.arguments); 419 List<Expression> arguments = translateArguments(node.arguments);
431 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); 420 Expression invoke = new InvokeStatic(node.target, node.selector, arguments);
432 return continueWithExpression(node.continuation, invoke); 421 return continueWithExpression(node.continuation, invoke);
433 } 422 }
434 423
435 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { 424 Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
436 Expression invoke = new InvokeMethod(getVariableReference(node.receiver), 425 Expression invoke = new InvokeMethod(getVariableUse(node.receiver),
437 node.selector, 426 node.selector,
438 translateArguments(node.arguments)); 427 translateArguments(node.arguments));
439 return continueWithExpression(node.continuation, invoke); 428 return continueWithExpression(node.continuation, invoke);
440 } 429 }
441 430
442 Statement visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { 431 Statement visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
443 Expression receiver = getVariableReference(node.receiver); 432 Expression receiver = getVariableUse(node.receiver);
444 List<Expression> arguments = translateArguments(node.arguments); 433 List<Expression> arguments = translateArguments(node.arguments);
445 Expression invoke = new InvokeMethodDirectly(receiver, node.target, 434 Expression invoke = new InvokeMethodDirectly(receiver, node.target,
446 node.selector, arguments); 435 node.selector, arguments);
447 return continueWithExpression(node.continuation, invoke); 436 return continueWithExpression(node.continuation, invoke);
448 } 437 }
449 438
450 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { 439 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) {
451 List<Expression> arguments = translateArguments(node.arguments); 440 List<Expression> arguments = translateArguments(node.arguments);
452 Expression concat = new ConcatenateStrings(arguments); 441 Expression concat = new ConcatenateStrings(arguments);
453 return continueWithExpression(node.continuation, concat); 442 return continueWithExpression(node.continuation, concat);
454 } 443 }
455 444
456 Statement continueWithExpression(cps_ir.Reference continuation, 445 Statement continueWithExpression(cps_ir.Reference continuation,
457 Expression expression) { 446 Expression expression) {
458 cps_ir.Continuation cont = continuation.definition; 447 cps_ir.Continuation cont = continuation.definition;
459 if (cont == returnContinuation) { 448 if (cont == returnContinuation) {
460 return new Return(expression); 449 return new Return(expression);
461 } else { 450 } else {
462 assert(cont.parameters.length == 1); 451 assert(cont.parameters.length == 1);
463 Function nextBuilder = cont.hasExactlyOneUse ? 452 Function nextBuilder = cont.hasExactlyOneUse ?
464 () => visit(cont.body) : () => new Break(labels[cont]); 453 () => visit(cont.body) : () => new Break(labels[cont]);
465 return buildContinuationAssignment(cont.parameters.single, expression, 454 return buildContinuationAssignment(cont.parameters.single, expression,
466 nextBuilder); 455 nextBuilder);
467 } 456 }
468 } 457 }
469 458
470 Statement visitLetMutable(cps_ir.LetMutable node) { 459 Statement visitLetMutable(cps_ir.LetMutable node) {
471 Variable variable = addMutableVariable(node.variable); 460 Variable variable = addMutableVariable(node.variable);
472 Expression value = getVariableReference(node.value); 461 Expression value = getVariableUse(node.value);
473 return new Assign(variable, value, visit(node.body), isDeclaration: true); 462 return new Assign(variable, value, visit(node.body), isDeclaration: true);
474 } 463 }
475 464
476 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { 465 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) {
477 return getMutableVariableReference(node.variable); 466 return getMutableVariableUse(node.variable);
478 } 467 }
479 468
480 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { 469 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) {
481 Variable variable = getMutableVariableReference(node.variable); 470 Variable variable = getMutableVariable(node.variable.definition);
482 Expression value = getVariableReference(node.value); 471 Expression value = getVariableUse(node.value);
483 return new Assign(variable, value, visit(node.body)); 472 return new Assign(variable, value, visit(node.body));
484 } 473 }
485 474
486 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { 475 Statement visitDeclareFunction(cps_ir.DeclareFunction node) {
487 Variable variable = addMutableVariable(node.variable); 476 Variable variable = addMutableVariable(node.variable);
488 FunctionDefinition function = makeSubFunction(node.definition); 477 FunctionDefinition function = makeSubFunction(node.definition);
489 return new FunctionDeclaration(variable, function, visit(node.body)); 478 return new FunctionDeclaration(variable, function, visit(node.body));
490 } 479 }
491 480
492 Statement visitTypeOperator(cps_ir.TypeOperator node) { 481 Statement visitTypeOperator(cps_ir.TypeOperator node) {
493 Expression receiver = getVariableReference(node.receiver); 482 Expression receiver = getVariableUse(node.receiver);
494 Expression concat = 483 Expression concat =
495 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); 484 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest);
496 return continueWithExpression(node.continuation, concat); 485 return continueWithExpression(node.continuation, concat);
497 } 486 }
498 487
499 Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) { 488 Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) {
500 List<Expression> arguments = translateArguments(node.arguments); 489 List<Expression> arguments = translateArguments(node.arguments);
501 Expression invoke = 490 Expression invoke =
502 new InvokeConstructor(node.type, node.target, node.selector, arguments); 491 new InvokeConstructor(node.type, node.target, node.selector, arguments);
503 return continueWithExpression(node.continuation, invoke); 492 return continueWithExpression(node.continuation, invoke);
504 } 493 }
505 494
506 Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) { 495 Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) {
507 // Invocations of the return continuation are translated to returns. 496 // Invocations of the return continuation are translated to returns.
508 // Other continuation invocations are replaced with assignments of the 497 // Other continuation invocations are replaced with assignments of the
509 // arguments to formal parameter variables, followed by the body if 498 // arguments to formal parameter variables, followed by the body if
510 // the continuation is singly reference or a break if it is multiply 499 // the continuation is singly reference or a break if it is multiply
511 // referenced. 500 // referenced.
512 cps_ir.Continuation cont = node.continuation.definition; 501 cps_ir.Continuation cont = node.continuation.definition;
513 if (cont == returnContinuation) { 502 if (cont == returnContinuation) {
514 assert(node.arguments.length == 1); 503 assert(node.arguments.length == 1);
515 return new Return(getVariableReference(node.arguments.single)); 504 return new Return(getVariableUse(node.arguments.single));
516 } else { 505 } else {
517 List<Expression> arguments = translatePhiArguments(node.arguments); 506 List<Variable> arguments = translatePhiArguments(node.arguments);
518 return buildPhiAssignments(cont.parameters, arguments, 507 return buildPhiAssignments(cont.parameters, arguments,
519 () { 508 () {
520 // Translate invocations of recursive and non-recursive 509 // Translate invocations of recursive and non-recursive
521 // continuations differently. 510 // continuations differently.
522 // * Non-recursive continuations 511 // * Non-recursive continuations
523 // - If there is one use, translate the continuation body 512 // - If there is one use, translate the continuation body
524 // inline at the invocation site. 513 // inline at the invocation site.
525 // - If there are multiple uses, translate to Break. 514 // - If there are multiple uses, translate to Break.
526 // * Recursive continuations 515 // * Recursive continuations
527 // - There is a single non-recursive invocation. Translate 516 // - There is a single non-recursive invocation. Translate
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 return new LiteralList( 564 return new LiteralList(
576 node.type, 565 node.type,
577 translateArguments(node.values)); 566 translateArguments(node.values));
578 } 567 }
579 568
580 Expression visitLiteralMap(cps_ir.LiteralMap node) { 569 Expression visitLiteralMap(cps_ir.LiteralMap node) {
581 return new LiteralMap( 570 return new LiteralMap(
582 node.type, 571 node.type,
583 new List<LiteralMapEntry>.generate(node.entries.length, (int index) { 572 new List<LiteralMapEntry>.generate(node.entries.length, (int index) {
584 return new LiteralMapEntry( 573 return new LiteralMapEntry(
585 getVariableReference(node.entries[index].key), 574 getVariableUse(node.entries[index].key),
586 getVariableReference(node.entries[index].value)); 575 getVariableUse(node.entries[index].value));
587 }) 576 })
588 ); 577 );
589 } 578 }
590 579
591 FunctionDefinition makeSubFunction(cps_ir.FunctionDefinition function) { 580 FunctionDefinition makeSubFunction(cps_ir.FunctionDefinition function) {
592 return createInnerBuilder().buildFunction(function); 581 return createInnerBuilder().buildFunction(function);
593 } 582 }
594 583
595 Node visitCreateFunction(cps_ir.CreateFunction node) { 584 Node visitCreateFunction(cps_ir.CreateFunction node) {
596 FunctionDefinition def = makeSubFunction(node.definition); 585 FunctionDefinition def = makeSubFunction(node.definition);
(...skipping 16 matching lines...) Expand all
613 } 602 }
614 603
615 Expression visitContinuation(cps_ir.Continuation node) { 604 Expression visitContinuation(cps_ir.Continuation node) {
616 // Until continuations with multiple uses are supported, they are not 605 // Until continuations with multiple uses are supported, they are not
617 // visited. 606 // visited.
618 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); 607 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.');
619 return null; 608 return null;
620 } 609 }
621 610
622 Expression visitIsTrue(cps_ir.IsTrue node) { 611 Expression visitIsTrue(cps_ir.IsTrue node) {
623 return getVariableReference(node.value); 612 return getVariableUse(node.value);
624 } 613 }
625 } 614 }
626 615
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698