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 |