| 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 return local2closure.putIfAbsent(irVariable, |
| 80 if (variable == null) { | 80 () => new Variable(currentElement, irVariable.hint)); |
| 81 variable = new Variable(currentElement, local); | |
| 82 local2closure[local] = variable; | |
| 83 } | |
| 84 return variable; | |
| 85 } | 81 } |
| 86 | 82 |
| 87 /// Obtains the variable representing the given primitive. Returns null for | 83 /// Obtains the variable representing the given primitive. Returns null for |
| 88 /// primitives that have no reference and do not need a variable. | 84 /// primitives that have no reference and do not need a variable. |
| 89 Variable getVariable(cps_ir.Primitive primitive) { | 85 Variable getVariable(cps_ir.Primitive primitive) { |
| 90 if (primitive.registerIndex == null) { | 86 if (primitive.registerIndex == null) { |
| 91 return null; // variable is unused | 87 return null; // variable is unused |
| 92 } | 88 } |
| 93 List<Variable> variables = element2variables[primitive.hint]; | 89 List<Variable> variables = element2variables.putIfAbsent(primitive.hint, |
| 94 if (variables == null) { | 90 () => <Variable>[]); |
| 95 variables = <Variable>[]; | |
| 96 element2variables[primitive.hint] = variables; | |
| 97 } | |
| 98 while (variables.length <= primitive.registerIndex) { | 91 while (variables.length <= primitive.registerIndex) { |
| 99 variables.add(new Variable(currentElement, primitive.hint)); | 92 variables.add(new Variable(currentElement, primitive.hint)); |
| 100 } | 93 } |
| 101 return variables[primitive.registerIndex]; | 94 return variables[primitive.registerIndex]; |
| 102 } | 95 } |
| 103 | 96 |
| 104 /// Obtains a reference to the tree Variable corresponding to the IR primitive | 97 /// Obtains a reference to the tree Variable corresponding to the IR primitive |
| 105 /// referred to by [reference]. | 98 /// referred to by [reference]. |
| 106 /// This increments the reference count for the given variable, so the | 99 /// This increments the reference count for the given variable, so the |
| 107 /// returned expression must be used in the tree. | 100 /// returned expression must be used in the tree. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 131 currentElement = node.element; | 124 currentElement = node.element; |
| 132 returnContinuation = node.returnContinuation; | 125 returnContinuation = node.returnContinuation; |
| 133 | 126 |
| 134 phiTempVar = new Variable(node.element, null); | 127 phiTempVar = new Variable(node.element, null); |
| 135 | 128 |
| 136 body = visit(node.body); | 129 body = visit(node.body); |
| 137 } | 130 } |
| 138 return new FieldDefinition(node.element, body); | 131 return new FieldDefinition(node.element, body); |
| 139 } | 132 } |
| 140 | 133 |
| 134 Variable getFunctionParameter(cps_ir.Definition variable) { |
| 135 if (variable is cps_ir.Parameter) { |
| 136 return getVariable(variable); |
| 137 } else { |
| 138 return getClosureVariable(variable as cps_ir.ClosureVariable); |
| 139 } |
| 140 } |
| 141 |
| 141 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { | 142 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { |
| 142 currentElement = node.element; | 143 currentElement = node.element; |
| 143 List<Variable> parameters = <Variable>[]; | 144 List<Variable> parameters = <Variable>[]; |
| 144 for (cps_ir.Parameter p in node.parameters) { | 145 for (cps_ir.Definition p in node.parameters) { |
| 145 Variable parameter = getVariable(p); | 146 Variable parameter = getFunctionParameter(p); |
| 146 assert(parameter != null); | 147 assert(parameter != null); |
| 147 ++parameter.writeCount; // Being a parameter counts as a write. | 148 ++parameter.writeCount; // Being a parameter counts as a write. |
| 148 parameters.add(parameter); | 149 parameters.add(parameter); |
| 149 } | 150 } |
| 150 returnContinuation = node.returnContinuation; | 151 returnContinuation = node.returnContinuation; |
| 151 | 152 |
| 152 Statement body; | 153 Statement body; |
| 153 if (!node.isAbstract) { | 154 if (!node.isAbstract) { |
| 154 phiTempVar = new Variable(node.element, null); | 155 phiTempVar = new Variable(node.element, null); |
| 155 body = visit(node.body); | 156 body = visit(node.body); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 } else { | 342 } else { |
| 342 assert(cont.parameters.length == 1); | 343 assert(cont.parameters.length == 1); |
| 343 Function nextBuilder = cont.hasExactlyOneUse ? | 344 Function nextBuilder = cont.hasExactlyOneUse ? |
| 344 () => visit(cont.body) : () => new Break(labels[cont]); | 345 () => visit(cont.body) : () => new Break(labels[cont]); |
| 345 return buildContinuationAssignment(cont.parameters.single, expression, | 346 return buildContinuationAssignment(cont.parameters.single, expression, |
| 346 nextBuilder); | 347 nextBuilder); |
| 347 } | 348 } |
| 348 } | 349 } |
| 349 | 350 |
| 350 Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) { | 351 Expression visitGetClosureVariable(cps_ir.GetClosureVariable node) { |
| 351 return getClosureVariable(node.variable); | 352 return getClosureVariable(node.variable.definition); |
| 352 } | 353 } |
| 353 | 354 |
| 354 Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) { | 355 Statement visitSetClosureVariable(cps_ir.SetClosureVariable node) { |
| 355 Variable variable = getClosureVariable(node.variable); | 356 Variable variable = getClosureVariable(node.variable.definition); |
| 356 Expression value = getVariableReference(node.value); | 357 Expression value = getVariableReference(node.value); |
| 357 return new Assign(variable, value, visit(node.body), | 358 return new Assign(variable, value, visit(node.body), |
| 358 isDeclaration: node.isDeclaration); | 359 isDeclaration: node.isDeclaration); |
| 359 } | 360 } |
| 360 | 361 |
| 361 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { | 362 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { |
| 362 Variable variable = getClosureVariable(node.variable); | 363 Variable variable = getClosureVariable(node.variable.definition); |
| 363 FunctionDefinition function = makeSubFunction(node.definition); | 364 FunctionDefinition function = makeSubFunction(node.definition); |
| 364 return new FunctionDeclaration(variable, function, visit(node.body)); | 365 return new FunctionDeclaration(variable, function, visit(node.body)); |
| 365 } | 366 } |
| 366 | 367 |
| 367 Statement visitTypeOperator(cps_ir.TypeOperator node) { | 368 Statement visitTypeOperator(cps_ir.TypeOperator node) { |
| 368 Expression receiver = getVariableReference(node.receiver); | 369 Expression receiver = getVariableReference(node.receiver); |
| 369 Expression concat = | 370 Expression concat = |
| 370 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); | 371 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); |
| 371 return continueWithExpression(node.continuation, concat); | 372 return continueWithExpression(node.continuation, concat); |
| 372 } | 373 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 | 501 |
| 501 Expression visitIdentical(cps_ir.Identical node) { | 502 Expression visitIdentical(cps_ir.Identical node) { |
| 502 return new InvokeStatic( | 503 return new InvokeStatic( |
| 503 compiler.identicalFunction, | 504 compiler.identicalFunction, |
| 504 identicalSelector, | 505 identicalSelector, |
| 505 <Expression>[getVariableReference(node.left), | 506 <Expression>[getVariableReference(node.left), |
| 506 getVariableReference(node.right)]); | 507 getVariableReference(node.right)]); |
| 507 } | 508 } |
| 508 } | 509 } |
| 509 | 510 |
| OLD | NEW |