Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { | 75 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { |
| 76 if (irVariable.host != currentElement) { | 76 if (irVariable.host != currentElement) { |
| 77 return parent.addMutableVariable(irVariable); | 77 return parent.addMutableVariable(irVariable); |
| 78 } | 78 } |
| 79 assert(!local2mutable.containsKey(irVariable)); | 79 assert(!local2mutable.containsKey(irVariable)); |
| 80 Variable variable = new Variable(currentElement, irVariable.hint); | 80 Variable variable = new Variable(currentElement, irVariable.hint); |
| 81 local2mutable[irVariable] = variable; | 81 local2mutable[irVariable] = variable; |
| 82 return variable; | 82 return variable; |
| 83 } | 83 } |
| 84 | 84 |
| 85 Variable getMutableVariableReference( | 85 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) { |
| 86 if (mutableVariable.host != currentElement) { | |
| 87 return parent.getMutableVariable(mutableVariable); | |
| 88 } | |
| 89 return local2mutable[mutableVariable]; | |
| 90 } | |
| 91 | |
| 92 VariableUse getMutableVariableReference( | |
|
Kevin Millikin (Google)
2015/02/26 12:43:18
There's probably no good reason to use Reference i
asgerf
2015/02/27 12:05:19
Done.
| |
| 86 cps_ir.Reference<cps_ir.MutableVariable> reference) { | 93 cps_ir.Reference<cps_ir.MutableVariable> reference) { |
| 87 if (reference.definition.host != currentElement) { | 94 Variable variable = getMutableVariable(reference.definition); |
| 88 return parent.getMutableVariableReference(reference); | 95 return new VariableUse(variable); |
| 89 } | |
| 90 Variable variable = local2mutable[reference.definition]; | |
| 91 ++variable.readCount; | |
| 92 return variable; | |
| 93 } | 96 } |
| 94 | 97 |
| 95 /// Obtains the variable representing the given primitive. Returns null for | 98 /// Obtains the variable representing the given primitive. Returns null for |
| 96 /// primitives that have no reference and do not need a variable. | 99 /// primitives that have no reference and do not need a variable. |
| 97 Variable getVariable(cps_ir.Primitive primitive) { | 100 Variable getVariable(cps_ir.Primitive primitive) { |
| 98 if (primitive.registerIndex == null) { | 101 if (primitive.registerIndex == null) { |
| 99 return null; // variable is unused | 102 return null; // variable is unused |
| 100 } | 103 } |
| 101 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, | 104 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, |
| 102 () => <Variable>[]); | 105 () => <Variable>[]); |
| 103 while (variables.length <= primitive.registerIndex) { | 106 while (variables.length <= primitive.registerIndex) { |
| 104 variables.add(new Variable(currentElement, primitive.hint)); | 107 variables.add(new Variable(currentElement, primitive.hint)); |
| 105 } | 108 } |
| 106 return variables[primitive.registerIndex]; | 109 return variables[primitive.registerIndex]; |
| 107 } | 110 } |
| 108 | 111 |
| 109 /// 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 |
| 110 /// referred to by [reference]. | 113 /// referred to by [reference]. |
| 111 /// This increments the reference count for the given variable, so the | 114 /// This increments the reference count for the given variable, so the |
| 112 /// returned expression must be used in the tree. | 115 /// returned expression must be used in the tree. |
| 113 Expression getVariableReference(cps_ir.Reference reference) { | 116 Expression getVariableReference(cps_ir.Reference reference) { |
| 114 Variable variable = getVariable(reference.definition); | 117 Variable variable = getVariable(reference.definition); |
| 115 if (variable == null) { | 118 if (variable == null) { |
| 116 internalError( | 119 internalError( |
| 117 CURRENT_ELEMENT_SPANNABLE, | 120 CURRENT_ELEMENT_SPANNABLE, |
| 118 "Reference to ${reference.definition} has no register"); | 121 "Reference to ${reference.definition} has no register"); |
| 119 } | 122 } |
| 120 ++variable.readCount; | 123 return new VariableUse(variable); |
| 121 return variable; | |
| 122 } | 124 } |
| 123 | 125 |
| 124 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { | 126 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { |
| 125 if (node is cps_ir.FieldDefinition) { | 127 if (node is cps_ir.FieldDefinition) { |
| 126 return buildField(node); | 128 return buildField(node); |
| 127 } else if (node is cps_ir.ConstructorDefinition) { | 129 } else if (node is cps_ir.ConstructorDefinition) { |
| 128 return buildConstructor(node); | 130 return buildConstructor(node); |
| 129 } else { | 131 } else { |
| 130 assert(dart2js.invariant( | 132 assert(dart2js.invariant( |
| 131 CURRENT_ELEMENT_SPANNABLE, | 133 CURRENT_ELEMENT_SPANNABLE, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 152 Variable addFunctionParameter(cps_ir.Definition variable) { | 154 Variable addFunctionParameter(cps_ir.Definition variable) { |
| 153 if (variable is cps_ir.Parameter) { | 155 if (variable is cps_ir.Parameter) { |
| 154 return getVariable(variable); | 156 return getVariable(variable); |
| 155 } else { | 157 } else { |
| 156 return addMutableVariable(variable as cps_ir.MutableVariable); | 158 return addMutableVariable(variable as cps_ir.MutableVariable); |
| 157 } | 159 } |
| 158 } | 160 } |
| 159 | 161 |
| 160 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { | 162 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { |
| 161 currentElement = node.element; | 163 currentElement = node.element; |
| 162 List<Variable> parameters = <Variable>[]; | 164 List<Variable> parameters = |
| 163 for (cps_ir.Definition p in node.parameters) { | 165 node.parameters.map(addFunctionParameter).toList(); |
| 164 Variable parameter = addFunctionParameter(p); | |
| 165 assert(parameter != null); | |
| 166 ++parameter.writeCount; // Being a parameter counts as a write. | |
| 167 parameters.add(parameter); | |
| 168 } | |
| 169 | |
| 170 Statement body; | 166 Statement body; |
| 171 if (!node.isAbstract) { | 167 if (!node.isAbstract) { |
| 172 returnContinuation = node.body.returnContinuation; | 168 returnContinuation = node.body.returnContinuation; |
| 173 phiTempVar = new Variable(node.element, null); | 169 phiTempVar = new Variable(node.element, null); |
| 174 body = visit(node.body); | 170 body = visit(node.body); |
| 175 } | 171 } |
| 176 | 172 |
| 177 return new FunctionDefinition(node.element, parameters, | 173 return new FunctionDefinition(node.element, parameters, |
| 178 body, node.localConstants, node.defaultParameterValues); | 174 body, node.localConstants, node.defaultParameterValues); |
| 179 } | 175 } |
| 180 | 176 |
| 181 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { | 177 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { |
| 182 currentElement = node.element; | 178 currentElement = node.element; |
| 183 List<Variable> parameters = <Variable>[]; | 179 List<Variable> parameters = |
| 184 for (cps_ir.Definition p in node.parameters) { | 180 node.parameters.map(addFunctionParameter).toList(); |
| 185 Variable parameter = addFunctionParameter(p); | |
| 186 assert(parameter != null); | |
| 187 ++parameter.writeCount; // Being a parameter counts as a write. | |
| 188 parameters.add(parameter); | |
| 189 } | |
| 190 List<Initializer> initializers; | 181 List<Initializer> initializers; |
| 191 Statement body; | 182 Statement body; |
| 192 if (!node.isAbstract) { | 183 if (!node.isAbstract) { |
| 193 initializers = node.initializers.map(visit).toList(); | 184 initializers = node.initializers.map(visit).toList(); |
| 194 returnContinuation = node.body.returnContinuation; | 185 returnContinuation = node.body.returnContinuation; |
| 195 | 186 |
| 196 phiTempVar = new Variable(node.element, null); | 187 phiTempVar = new Variable(node.element, null); |
| 197 body = visit(node.body); | 188 body = visit(node.body); |
| 198 } | 189 } |
| 199 | 190 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 } | 255 } |
| 265 List<int> list = rightHand[arg]; | 256 List<int> list = rightHand[arg]; |
| 266 if (list == null) { | 257 if (list == null) { |
| 267 rightHand[arg] = list = <int>[]; | 258 rightHand[arg] = list = <int>[]; |
| 268 } | 259 } |
| 269 list.add(i); | 260 list.add(i); |
| 270 } | 261 } |
| 271 | 262 |
| 272 Statement first, current; | 263 Statement first, current; |
| 273 void addAssignment(Variable dst, Variable src) { | 264 void addAssignment(Variable dst, Variable src) { |
| 274 ++src.readCount; | |
| 275 // `dst.writeCount` will be updated by the Assign constructor. | |
| 276 if (first == null) { | 265 if (first == null) { |
| 277 first = current = new Assign(dst, src, null); | 266 first = current = new Assign(dst, new VariableUse(src), null); |
| 278 } else { | 267 } else { |
| 279 current = current.next = new Assign(dst, src, null); | 268 current = current.next = new Assign(dst, new VariableUse(src), null); |
| 280 } | 269 } |
| 281 } | 270 } |
| 282 | 271 |
| 283 List<Variable> assignmentSrc = new List<Variable>(parameters.length); | 272 List<Variable> assignmentSrc = new List<Variable>(parameters.length); |
| 284 List<bool> done = new List<bool>(parameters.length); | 273 List<bool> done = new List<bool>(parameters.length); |
| 285 void visitAssignment(int i) { | 274 void visitAssignment(int i) { |
| 286 if (done[i] == true) { | 275 if (done[i] == true) { |
| 287 return; | 276 return; |
| 288 } | 277 } |
| 289 Variable param = getVariable(parameters[i]); | 278 Variable param = getVariable(parameters[i]); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 Variable variable = addMutableVariable(node.variable); | 436 Variable variable = addMutableVariable(node.variable); |
| 448 Expression value = getVariableReference(node.value); | 437 Expression value = getVariableReference(node.value); |
| 449 return new Assign(variable, value, visit(node.body), isDeclaration: true); | 438 return new Assign(variable, value, visit(node.body), isDeclaration: true); |
| 450 } | 439 } |
| 451 | 440 |
| 452 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 441 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 453 return getMutableVariableReference(node.variable); | 442 return getMutableVariableReference(node.variable); |
| 454 } | 443 } |
| 455 | 444 |
| 456 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { | 445 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { |
| 457 Variable variable = getMutableVariableReference(node.variable); | 446 Variable variable = getMutableVariable(node.variable.definition); |
| 458 Expression value = getVariableReference(node.value); | 447 Expression value = getVariableReference(node.value); |
| 459 return new Assign(variable, value, visit(node.body)); | 448 return new Assign(variable, value, visit(node.body)); |
| 460 } | 449 } |
| 461 | 450 |
| 462 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { | 451 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { |
| 463 Variable variable = addMutableVariable(node.variable); | 452 Variable variable = addMutableVariable(node.variable); |
| 464 FunctionDefinition function = makeSubFunction(node.definition); | 453 FunctionDefinition function = makeSubFunction(node.definition); |
| 465 return new FunctionDeclaration(variable, function, visit(node.body)); | 454 return new FunctionDeclaration(variable, function, visit(node.body)); |
| 466 } | 455 } |
| 467 | 456 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 483 // Invocations of the return continuation are translated to returns. | 472 // Invocations of the return continuation are translated to returns. |
| 484 // Other continuation invocations are replaced with assignments of the | 473 // Other continuation invocations are replaced with assignments of the |
| 485 // arguments to formal parameter variables, followed by the body if | 474 // arguments to formal parameter variables, followed by the body if |
| 486 // the continuation is singly reference or a break if it is multiply | 475 // the continuation is singly reference or a break if it is multiply |
| 487 // referenced. | 476 // referenced. |
| 488 cps_ir.Continuation cont = node.continuation.definition; | 477 cps_ir.Continuation cont = node.continuation.definition; |
| 489 if (cont == returnContinuation) { | 478 if (cont == returnContinuation) { |
| 490 assert(node.arguments.length == 1); | 479 assert(node.arguments.length == 1); |
| 491 return new Return(getVariableReference(node.arguments.single)); | 480 return new Return(getVariableReference(node.arguments.single)); |
| 492 } else { | 481 } else { |
| 493 List<Expression> arguments = translatePhiArguments(node.arguments); | 482 List<Variable> arguments = translatePhiArguments(node.arguments); |
| 494 return buildPhiAssignments(cont.parameters, arguments, | 483 return buildPhiAssignments(cont.parameters, arguments, |
| 495 () { | 484 () { |
| 496 // Translate invocations of recursive and non-recursive | 485 // Translate invocations of recursive and non-recursive |
| 497 // continuations differently. | 486 // continuations differently. |
| 498 // * Non-recursive continuations | 487 // * Non-recursive continuations |
| 499 // - If there is one use, translate the continuation body | 488 // - If there is one use, translate the continuation body |
| 500 // inline at the invocation site. | 489 // inline at the invocation site. |
| 501 // - If there are multiple uses, translate to Break. | 490 // - If there are multiple uses, translate to Break. |
| 502 // * Recursive continuations | 491 // * Recursive continuations |
| 503 // - There is a single non-recursive invocation. Translate | 492 // - There is a single non-recursive invocation. Translate |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 589 // visited. | 578 // visited. |
| 590 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); | 579 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); |
| 591 return null; | 580 return null; |
| 592 } | 581 } |
| 593 | 582 |
| 594 Expression visitIsTrue(cps_ir.IsTrue node) { | 583 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 595 return getVariableReference(node.value); | 584 return getVariableReference(node.value); |
| 596 } | 585 } |
| 597 } | 586 } |
| 598 | 587 |
| OLD | NEW |