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 * particular, intermediate values and blocks used for local control flow are | 42 * particular, intermediate values and blocks used for local control flow are |
| 43 * still all named. | 43 * still all named. |
| 44 */ | 44 */ |
| 45 class Builder extends cps_ir.Visitor<Node> { | 45 class Builder extends cps_ir.Visitor<Node> { |
| 46 final dart2js.Compiler compiler; | 46 final dart2js.Compiler compiler; |
| 47 | 47 |
| 48 /// Maps variable/parameter elements to the Tree variables that represent it. | 48 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 49 final Map<Element, List<Variable>> element2variables = | 49 final Map<Element, List<Variable>> element2variables = |
| 50 <Element,List<Variable>>{}; | 50 <Element,List<Variable>>{}; |
| 51 | 51 |
| 52 /// Like [element2variables], except for closure variables. Closure variables | 52 /// Like [element2variables], except for closure variables. |
| 53 /// are not subject to SSA, so at most one variable is used per local. | 53 final Map<cps_ir.ClosureVariable, Variable> local2closure = |
| 54 final Map<Local, Variable> local2closure = <Local, Variable>{}; | 54 <cps_ir.ClosureVariable, 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.compiler); | 65 Builder(this.compiler); |
| 66 | 66 |
| 67 Builder.inner(Builder parent) | 67 Builder.inner(Builder parent) |
| 68 : this.parent = parent, | 68 : this.parent = parent, |
| 69 compiler = parent.compiler; | 69 compiler = parent.compiler; |
| 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(Local local) { | 75 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { |
| 76 if (local.executableContext != currentElement) { | 76 if (irVariable.host != currentElement) { |
| 77 return parent.getClosureVariable(local); | 77 return parent.getClosureVariable(irVariable); |
| 78 } | 78 } |
| 79 Variable variable = local2closure[local]; | 79 Variable variable = local2closure[irVariable]; |
|
Johnni Winther
2014/12/08 13:15:13
This could be rewritten as a putIfAbsent.
asgerf
2014/12/08 13:44:00
Done.
| |
| 80 if (variable == null) { | 80 if (variable == null) { |
| 81 variable = new Variable(currentElement, local); | 81 variable = new Variable(currentElement, irVariable.hint); |
| 82 local2closure[local] = variable; | 82 local2closure[irVariable] = variable; |
| 83 } | 83 } |
| 84 return variable; | 84 return variable; |
| 85 } | 85 } |
| 86 | 86 |
| 87 /// Obtains the variable representing the given primitive. Returns null for | 87 /// Obtains the variable representing the given primitive. Returns null for |
| 88 /// primitives that have no reference and do not need a variable. | 88 /// primitives that have no reference and do not need a variable. |
| 89 Variable getVariable(cps_ir.Primitive primitive) { | 89 Variable getVariable(cps_ir.Primitive primitive) { |
| 90 if (primitive.registerIndex == null) { | 90 if (primitive.registerIndex == null) { |
| 91 return null; // variable is unused | 91 return null; // variable is unused |
| 92 } | 92 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 currentElement = node.element; | 131 currentElement = node.element; |
| 132 returnContinuation = node.returnContinuation; | 132 returnContinuation = node.returnContinuation; |
| 133 | 133 |
| 134 phiTempVar = new Variable(node.element, null); | 134 phiTempVar = new Variable(node.element, null); |
| 135 | 135 |
| 136 body = visit(node.body); | 136 body = visit(node.body); |
| 137 } | 137 } |
| 138 return new FieldDefinition(node.element, body); | 138 return new FieldDefinition(node.element, body); |
| 139 } | 139 } |
| 140 | 140 |
| 141 Variable getFunctionParameter(cps_ir.Definition variable) { | |
| 142 if (variable is cps_ir.Parameter) { | |
| 143 return getVariable(variable); | |
| 144 } else { | |
| 145 return getClosureVariable(variable as cps_ir.ClosureVariable); | |
| 146 } | |
| 147 } | |
| 148 | |
| 141 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { | 149 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { |
| 142 currentElement = node.element; | 150 currentElement = node.element; |
| 143 List<Variable> parameters = <Variable>[]; | 151 List<Variable> parameters = <Variable>[]; |
| 144 for (cps_ir.Parameter p in node.parameters) { | 152 for (cps_ir.Definition p in node.parameters) { |
| 145 Variable parameter = getVariable(p); | 153 Variable parameter = getFunctionParameter(p); |
| 146 assert(parameter != null); | 154 assert(parameter != null); |
| 147 ++parameter.writeCount; // Being a parameter counts as a write. | 155 ++parameter.writeCount; // Being a parameter counts as a write. |
| 148 parameters.add(parameter); | 156 parameters.add(parameter); |
| 149 } | 157 } |
| 150 returnContinuation = node.returnContinuation; | 158 returnContinuation = node.returnContinuation; |
| 151 | 159 |
| 152 Statement body; | 160 Statement body; |
| 153 if (!node.isAbstract) { | 161 if (!node.isAbstract) { |
| 154 phiTempVar = new Variable(node.element, null); | 162 phiTempVar = new Variable(node.element, null); |
| 155 body = visit(node.body); | 163 body = visit(node.body); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 } else { | 349 } else { |
| 342 assert(cont.parameters.length == 1); | 350 assert(cont.parameters.length == 1); |
| 343 Function nextBuilder = cont.hasExactlyOneUse ? | 351 Function nextBuilder = cont.hasExactlyOneUse ? |
| 344 () => visit(cont.body) : () => new Break(labels[cont]); | 352 () => visit(cont.body) : () => new Break(labels[cont]); |
| 345 return buildContinuationAssignment(cont.parameters.single, expression, | 353 return buildContinuationAssignment(cont.parameters.single, expression, |
| 346 nextBuilder); | 354 nextBuilder); |
| 347 } | 355 } |
| 348 } | 356 } |
| 349 | 357 |
| 350 Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) { | 358 Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) { |
| 351 return getClosureVariable(node.variable); | 359 return getClosureVariable(node.variable.definition); |
| 352 } | 360 } |
| 353 | 361 |
| 354 Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) { | 362 Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) { |
| 355 Variable variable = getClosureVariable(node.variable); | 363 Variable variable = getClosureVariable(node.variable.definition); |
| 356 Expression value = getVariableReference(node.value); | 364 Expression value = getVariableReference(node.value); |
| 357 return new Assign(variable, value, visit(node.body), | 365 return new Assign(variable, value, visit(node.body), |
| 358 isDeclaration: node.isDeclaration); | 366 isDeclaration: node.isDeclaration); |
| 359 } | 367 } |
| 360 | 368 |
| 361 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { | 369 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { |
| 362 Variable variable = getClosureVariable(node.variable); | 370 Variable variable = getClosureVariable(node.variable.definition); |
| 363 FunctionDefinition function = makeSubFunction(node.definition); | 371 FunctionDefinition function = makeSubFunction(node.definition); |
| 364 return new FunctionDeclaration(variable, function, visit(node.body)); | 372 return new FunctionDeclaration(variable, function, visit(node.body)); |
| 365 } | 373 } |
| 366 | 374 |
| 367 Statement visitTypeOperator(cps_ir.TypeOperator node) { | 375 Statement visitTypeOperator(cps_ir.TypeOperator node) { |
| 368 Expression receiver = getVariableReference(node.receiver); | 376 Expression receiver = getVariableReference(node.receiver); |
| 369 Expression concat = | 377 Expression concat = |
| 370 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); | 378 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); |
| 371 return continueWithExpression(node.continuation, concat); | 379 return continueWithExpression(node.continuation, concat); |
| 372 } | 380 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 | 508 |
| 501 Expression visitIdentical(cps_ir.Identical node) { | 509 Expression visitIdentical(cps_ir.Identical node) { |
| 502 return new InvokeStatic( | 510 return new InvokeStatic( |
| 503 compiler.identicalFunction, | 511 compiler.identicalFunction, |
| 504 identicalSelector, | 512 identicalSelector, |
| 505 <Expression>[getVariableReference(node.left), | 513 <Expression>[getVariableReference(node.left), |
| 506 getVariableReference(node.right)]); | 514 getVariableReference(node.right)]); |
| 507 } | 515 } |
| 508 } | 516 } |
| 509 | 517 |
| OLD | NEW |