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 |