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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 extends cps_ir.Visitor<Node> { | 46 class Builder extends 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 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 50 final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{}; | 50 final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{}; |
| 51 | 51 |
| 52 /// Like [local2variables], except for closure variables. | 52 /// Like [local2variables], except for mutable variables. |
| 53 final Map<cps_ir.ClosureVariable, Variable> local2closure = | 53 final Map<cps_ir.MutableVariable, Variable> local2mutable = |
|
karlklose
2015/02/03 09:56:16
I would really like to get rid of this naming conv
Kevin Millikin (Google)
2015/02/03 14:11:49
Concrete suggestions for naming maps? Name them a
| |
| 54 <cps_ir.ClosureVariable, Variable>{}; | 54 <cps_ir.MutableVariable, Variable>{}; |
| 55 | 55 |
| 56 // Continuations with more than one use are replaced with Tree labels. This | 56 // Continuations with more than one use are replaced with Tree labels. This |
| 57 // is the mapping from continuations to labels. | 57 // is the mapping from continuations to labels. |
| 58 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; | 58 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; |
| 59 | 59 |
| 60 ExecutableElement currentElement; | 60 ExecutableElement currentElement; |
| 61 cps_ir.Continuation returnContinuation; | 61 cps_ir.Continuation returnContinuation; |
| 62 | 62 |
| 63 Builder parent; | 63 Builder parent; |
| 64 | 64 |
| 65 Builder(this.internalError, [this.parent]); | 65 Builder(this.internalError, [this.parent]); |
| 66 | 66 |
| 67 Builder createInnerBuilder() { | 67 Builder createInnerBuilder() { |
| 68 return new Builder(internalError, this); | 68 return new Builder(internalError, this); |
| 69 } | 69 } |
| 70 | 70 |
| 71 /// Variable used in [buildPhiAssignments] as a temporary when swapping | 71 /// Variable used in [buildPhiAssignments] as a temporary when swapping |
| 72 /// variables. | 72 /// variables. |
| 73 Variable phiTempVar; | 73 Variable phiTempVar; |
| 74 | 74 |
| 75 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { | 75 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { |
| 76 if (irVariable.host != currentElement) { | 76 if (irVariable.host != currentElement) { |
| 77 return parent.getClosureVariable(irVariable); | 77 return parent.addMutableVariable(irVariable); |
| 78 } | 78 } |
| 79 return local2closure.putIfAbsent(irVariable, | 79 assert(!local2mutable.containsKey(irVariable)); |
| 80 () => new Variable(currentElement, irVariable.hint)); | 80 Variable variable = new Variable(currentElement, irVariable.hint); |
| 81 local2mutable[irVariable] = variable; | |
| 82 return variable; | |
| 83 } | |
| 84 | |
| 85 Variable getMutableVariableReference( | |
| 86 cps_ir.Reference<cps_ir.MutableVariable> reference) { | |
| 87 if (reference.definition.host != currentElement) { | |
| 88 return parent.getMutableVariableReference(reference); | |
| 89 } | |
| 90 return local2mutable[reference.definition]; | |
| 81 } | 91 } |
| 82 | 92 |
| 83 /// Obtains the variable representing the given primitive. Returns null for | 93 /// Obtains the variable representing the given primitive. Returns null for |
| 84 /// primitives that have no reference and do not need a variable. | 94 /// primitives that have no reference and do not need a variable. |
| 85 Variable getVariable(cps_ir.Primitive primitive) { | 95 Variable getVariable(cps_ir.Primitive primitive) { |
| 86 if (primitive.registerIndex == null) { | 96 if (primitive.registerIndex == null) { |
| 87 return null; // variable is unused | 97 return null; // variable is unused |
| 88 } | 98 } |
| 89 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, | 99 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, |
| 90 () => <Variable>[]); | 100 () => <Variable>[]); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 currentElement = node.element; | 140 currentElement = node.element; |
| 131 returnContinuation = node.body.returnContinuation; | 141 returnContinuation = node.body.returnContinuation; |
| 132 | 142 |
| 133 phiTempVar = new Variable(node.element, null); | 143 phiTempVar = new Variable(node.element, null); |
| 134 | 144 |
| 135 body = visit(node.body); | 145 body = visit(node.body); |
| 136 } | 146 } |
| 137 return new FieldDefinition(node.element, body); | 147 return new FieldDefinition(node.element, body); |
| 138 } | 148 } |
| 139 | 149 |
| 140 Variable getFunctionParameter(cps_ir.Definition variable) { | 150 Variable addFunctionParameter(cps_ir.Definition variable) { |
| 141 if (variable is cps_ir.Parameter) { | 151 if (variable is cps_ir.Parameter) { |
| 142 return getVariable(variable); | 152 return getVariable(variable); |
| 143 } else { | 153 } else { |
| 144 return getClosureVariable(variable as cps_ir.ClosureVariable); | 154 return addMutableVariable(variable as cps_ir.MutableVariable); |
| 145 } | 155 } |
| 146 } | 156 } |
| 147 | 157 |
| 148 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { | 158 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { |
| 149 currentElement = node.element; | 159 currentElement = node.element; |
| 150 List<Variable> parameters = <Variable>[]; | 160 List<Variable> parameters = <Variable>[]; |
| 151 for (cps_ir.Definition p in node.parameters) { | 161 for (cps_ir.Definition p in node.parameters) { |
| 152 Variable parameter = getFunctionParameter(p); | 162 Variable parameter = addFunctionParameter(p); |
| 153 assert(parameter != null); | 163 assert(parameter != null); |
| 154 ++parameter.writeCount; // Being a parameter counts as a write. | 164 ++parameter.writeCount; // Being a parameter counts as a write. |
| 155 parameters.add(parameter); | 165 parameters.add(parameter); |
| 156 } | 166 } |
| 157 | 167 |
| 158 Statement body; | 168 Statement body; |
| 159 if (!node.isAbstract) { | 169 if (!node.isAbstract) { |
| 160 returnContinuation = node.body.returnContinuation; | 170 returnContinuation = node.body.returnContinuation; |
| 161 phiTempVar = new Variable(node.element, null); | 171 phiTempVar = new Variable(node.element, null); |
| 162 body = visit(node.body); | 172 body = visit(node.body); |
| 163 } | 173 } |
| 164 | 174 |
| 165 return new FunctionDefinition(node.element, parameters, | 175 return new FunctionDefinition(node.element, parameters, |
| 166 body, node.localConstants, node.defaultParameterValues); | 176 body, node.localConstants, node.defaultParameterValues); |
| 167 } | 177 } |
| 168 | 178 |
| 169 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { | 179 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { |
| 170 currentElement = node.element; | 180 currentElement = node.element; |
| 171 List<Variable> parameters = <Variable>[]; | 181 List<Variable> parameters = <Variable>[]; |
| 172 for (cps_ir.Definition p in node.parameters) { | 182 for (cps_ir.Definition p in node.parameters) { |
| 173 Variable parameter = getFunctionParameter(p); | 183 Variable parameter = addFunctionParameter(p); |
| 174 assert(parameter != null); | 184 assert(parameter != null); |
| 175 ++parameter.writeCount; // Being a parameter counts as a write. | 185 ++parameter.writeCount; // Being a parameter counts as a write. |
| 176 parameters.add(parameter); | 186 parameters.add(parameter); |
| 177 } | 187 } |
| 178 List<Initializer> initializers; | 188 List<Initializer> initializers; |
| 179 Statement body; | 189 Statement body; |
| 180 if (!node.isAbstract) { | 190 if (!node.isAbstract) { |
| 181 initializers = node.initializers.map(visit).toList(); | 191 initializers = node.initializers.map(visit).toList(); |
| 182 returnContinuation = node.body.returnContinuation; | 192 returnContinuation = node.body.returnContinuation; |
| 183 | 193 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 return new Return(expression); | 434 return new Return(expression); |
| 425 } else { | 435 } else { |
| 426 assert(cont.parameters.length == 1); | 436 assert(cont.parameters.length == 1); |
| 427 Function nextBuilder = cont.hasExactlyOneUse ? | 437 Function nextBuilder = cont.hasExactlyOneUse ? |
| 428 () => visit(cont.body) : () => new Break(labels[cont]); | 438 () => visit(cont.body) : () => new Break(labels[cont]); |
| 429 return buildContinuationAssignment(cont.parameters.single, expression, | 439 return buildContinuationAssignment(cont.parameters.single, expression, |
| 430 nextBuilder); | 440 nextBuilder); |
| 431 } | 441 } |
| 432 } | 442 } |
| 433 | 443 |
| 434 Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) { | 444 Statement visitLetMutable(cps_ir.LetMutable node) { |
| 435 return getClosureVariable(node.variable.definition); | 445 Variable variable = addMutableVariable(node.variable); |
| 446 Expression value = getVariableReference(node.value); | |
| 447 return new Assign(variable, value, visit(node.body), isDeclaration: true); | |
| 436 } | 448 } |
| 437 | 449 |
| 438 Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) { | 450 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 439 Variable variable = getClosureVariable(node.variable.definition); | 451 return getMutableVariableReference(node.variable); |
| 452 } | |
| 453 | |
| 454 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { | |
| 455 Variable variable = getMutableVariableReference(node.variable); | |
| 440 Expression value = getVariableReference(node.value); | 456 Expression value = getVariableReference(node.value); |
| 441 return new Assign(variable, value, visit(node.body), | 457 return new Assign(variable, value, visit(node.body)); |
| 442 isDeclaration: node.isDeclaration); | |
| 443 } | 458 } |
| 444 | 459 |
| 445 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { | 460 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { |
| 446 Variable variable = getClosureVariable(node.variable.definition); | 461 Variable variable = addMutableVariable(node.variable); |
| 447 FunctionDefinition function = makeSubFunction(node.definition); | 462 FunctionDefinition function = makeSubFunction(node.definition); |
| 448 return new FunctionDeclaration(variable, function, visit(node.body)); | 463 return new FunctionDeclaration(variable, function, visit(node.body)); |
| 449 } | 464 } |
| 450 | 465 |
| 451 Statement visitTypeOperator(cps_ir.TypeOperator node) { | 466 Statement visitTypeOperator(cps_ir.TypeOperator node) { |
| 452 Expression receiver = getVariableReference(node.receiver); | 467 Expression receiver = getVariableReference(node.receiver); |
| 453 Expression concat = | 468 Expression concat = |
| 454 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); | 469 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); |
| 455 return continueWithExpression(node.continuation, concat); | 470 return continueWithExpression(node.continuation, concat); |
| 456 } | 471 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 // visited. | 587 // visited. |
| 573 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); | 588 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); |
| 574 return null; | 589 return null; |
| 575 } | 590 } |
| 576 | 591 |
| 577 Expression visitIsTrue(cps_ir.IsTrue node) { | 592 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 578 return getVariableReference(node.value); | 593 return getVariableReference(node.value); |
| 579 } | 594 } |
| 580 } | 595 } |
| 581 | 596 |
| OLD | NEW |