| 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; |
| 11 import 'tree_ir_nodes.dart'; | 11 import 'tree_ir_nodes.dart'; |
| 12 import '../js_backend/codegen/glue.dart'; | |
| 13 | 12 |
| 14 /** | 13 /** |
| 15 * Builder translates from CPS-based IR to direct-style Tree. | 14 * Builder translates from CPS-based IR to direct-style Tree. |
| 16 * | 15 * |
| 17 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced | 16 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced |
| 18 * non-exit continuation `Cont(v, body)` is translated into a direct-style call | 17 * non-exit continuation `Cont(v, body)` is translated into a direct-style call |
| 19 * whose value is bound in the continuation body: | 18 * whose value is bound in the continuation body: |
| 20 * | 19 * |
| 21 * `LetVal(v, Invoke(fun, args), body)` | 20 * `LetVal(v, Invoke(fun, args), body)` |
| 22 * | 21 * |
| (...skipping 14 matching lines...) Expand all Loading... |
| 37 * | 36 * |
| 38 * Block arguments are later replaced with data flow during the Tree-to-Tree | 37 * Block arguments are later replaced with data flow during the Tree-to-Tree |
| 39 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree | 38 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree |
| 40 * control-flow recognition. | 39 * control-flow recognition. |
| 41 * | 40 * |
| 42 * Otherwise, the output of Builder looks very much like the input. In | 41 * Otherwise, the output of Builder looks very much like the input. In |
| 43 * particular, intermediate values and blocks used for local control flow are | 42 * particular, intermediate values and blocks used for local control flow are |
| 44 * still all named. | 43 * still all named. |
| 45 */ | 44 */ |
| 46 class Builder extends cps_ir.Visitor<Node> { | 45 class Builder extends cps_ir.Visitor<Node> { |
| 47 // TODO(karlklose): remove the compiler. | |
| 48 final dart2js.Compiler compiler; | 46 final dart2js.Compiler compiler; |
| 49 final Glue glue; | |
| 50 | 47 |
| 51 /// Maps variable/parameter elements to the Tree variables that represent it. | 48 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 52 final Map<Element, List<Variable>> element2variables = | 49 final Map<Element, List<Variable>> element2variables = |
| 53 <Element,List<Variable>>{}; | 50 <Element,List<Variable>>{}; |
| 54 | 51 |
| 55 /// Like [element2variables], except for closure variables. | 52 /// Like [element2variables], except for closure variables. |
| 56 final Map<cps_ir.ClosureVariable, Variable> local2closure = | 53 final Map<cps_ir.ClosureVariable, Variable> local2closure = |
| 57 <cps_ir.ClosureVariable, Variable>{}; | 54 <cps_ir.ClosureVariable, Variable>{}; |
| 58 | 55 |
| 59 // 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 |
| 60 // is the mapping from continuations to labels. | 57 // is the mapping from continuations to labels. |
| 61 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; | 58 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; |
| 62 | 59 |
| 63 ExecutableElement currentElement; | 60 ExecutableElement currentElement; |
| 64 cps_ir.Continuation returnContinuation; | 61 cps_ir.Continuation returnContinuation; |
| 65 | 62 |
| 66 Builder parent; | 63 Builder parent; |
| 67 | 64 |
| 68 Builder(this.glue, this.compiler); | 65 Builder(this.compiler); |
| 69 | 66 |
| 70 Builder.inner(Builder parent) | 67 Builder.inner(Builder parent) |
| 71 : this.parent = parent, | 68 : this.parent = parent, |
| 72 this.glue = parent.glue, | |
| 73 compiler = parent.compiler; | 69 compiler = parent.compiler; |
| 74 | 70 |
| 75 /// Variable used in [buildPhiAssignments] as a temporary when swapping | 71 /// Variable used in [buildPhiAssignments] as a temporary when swapping |
| 76 /// variables. | 72 /// variables. |
| 77 Variable phiTempVar; | 73 Variable phiTempVar; |
| 78 | 74 |
| 79 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { | 75 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { |
| 80 if (irVariable.host != currentElement) { | 76 if (irVariable.host != currentElement) { |
| 81 return parent.getClosureVariable(irVariable); | 77 return parent.getClosureVariable(irVariable); |
| 82 } | 78 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 phiTempVar = new Variable(node.element, null); | 155 phiTempVar = new Variable(node.element, null); |
| 160 body = visit(node.body); | 156 body = visit(node.body); |
| 161 } | 157 } |
| 162 | 158 |
| 163 return new FunctionDefinition(node.element, parameters, | 159 return new FunctionDefinition(node.element, parameters, |
| 164 body, node.localConstants, node.defaultParameterValues); | 160 body, node.localConstants, node.defaultParameterValues); |
| 165 } | 161 } |
| 166 | 162 |
| 167 List<Expression> translateArguments(List<cps_ir.Reference> args) { | 163 List<Expression> translateArguments(List<cps_ir.Reference> args) { |
| 168 return new List<Expression>.generate(args.length, | 164 return new List<Expression>.generate(args.length, |
| 169 (int index) => getVariableReference(args[index]), | 165 (int index) => getVariableReference(args[index])); |
| 170 growable: false); | |
| 171 } | 166 } |
| 172 | 167 |
| 173 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { | 168 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { |
| 174 return new List<Variable>.generate(args.length, | 169 return new List<Variable>.generate(args.length, |
| 175 (int index) => getVariableReference(args[index])); | 170 (int index) => getVariableReference(args[index])); |
| 176 } | 171 } |
| 177 | 172 |
| 178 Statement buildContinuationAssignment( | 173 Statement buildContinuationAssignment( |
| 179 cps_ir.Parameter parameter, | 174 cps_ir.Parameter parameter, |
| 180 Expression argument, | 175 Expression argument, |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 } | 309 } |
| 315 | 310 |
| 316 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { | 311 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { |
| 317 // Calls are translated to direct style. | 312 // Calls are translated to direct style. |
| 318 List<Expression> arguments = translateArguments(node.arguments); | 313 List<Expression> arguments = translateArguments(node.arguments); |
| 319 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); | 314 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); |
| 320 return continueWithExpression(node.continuation, invoke); | 315 return continueWithExpression(node.continuation, invoke); |
| 321 } | 316 } |
| 322 | 317 |
| 323 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { | 318 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { |
| 324 Expression invoke = new InvokeMethod(getVariableReference(node.receiver), | 319 Expression receiver = getVariableReference(node.receiver); |
| 325 node.selector, | 320 List<Expression> arguments = translateArguments(node.arguments); |
| 326 translateArguments(node.arguments)); | 321 Expression invoke = new InvokeMethod(receiver, node.selector, arguments); |
| 327 return continueWithExpression(node.continuation, invoke); | 322 return continueWithExpression(node.continuation, invoke); |
| 328 } | 323 } |
| 329 | 324 |
| 330 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { | 325 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { |
| 331 List<Expression> arguments = translateArguments(node.arguments); | 326 List<Expression> arguments = translateArguments(node.arguments); |
| 332 Expression invoke = new InvokeSuperMethod(node.selector, arguments); | 327 Expression invoke = new InvokeSuperMethod(node.selector, arguments); |
| 333 return continueWithExpression(node.continuation, invoke); | 328 return continueWithExpression(node.continuation, invoke); |
| 334 } | 329 } |
| 335 | 330 |
| 336 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { | 331 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 // The successor will be filled in by visitLetPrim. | 473 // The successor will be filled in by visitLetPrim. |
| 479 return new FunctionDeclaration(getVariable(node), def, null); | 474 return new FunctionDeclaration(getVariable(node), def, null); |
| 480 } else { | 475 } else { |
| 481 return new FunctionExpression(def); | 476 return new FunctionExpression(def); |
| 482 } | 477 } |
| 483 } | 478 } |
| 484 | 479 |
| 485 Expression visitParameter(cps_ir.Parameter node) { | 480 Expression visitParameter(cps_ir.Parameter node) { |
| 486 // Continuation parameters are not visited (continuations themselves are | 481 // Continuation parameters are not visited (continuations themselves are |
| 487 // not visited yet). | 482 // not visited yet). |
| 488 compiler.internalError(compiler.currentElement, | 483 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); |
| 489 'Unexpected IR node: $node'); | |
| 490 return null; | 484 return null; |
| 491 } | 485 } |
| 492 | 486 |
| 493 Expression visitContinuation(cps_ir.Continuation node) { | 487 Expression visitContinuation(cps_ir.Continuation node) { |
| 494 // Until continuations with multiple uses are supported, they are not | 488 // Until continuations with multiple uses are supported, they are not |
| 495 // visited. | 489 // visited. |
| 496 compiler.internalError(compiler.currentElement, | 490 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); |
| 497 'Unexpected IR node: $node.'); | |
| 498 return null; | 491 return null; |
| 499 } | 492 } |
| 500 | 493 |
| 501 Expression visitIsTrue(cps_ir.IsTrue node) { | 494 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 502 return getVariableReference(node.value); | 495 return getVariableReference(node.value); |
| 503 } | 496 } |
| 504 | 497 |
| 505 dart2js.Selector get identicalSelector { | 498 dart2js.Selector get identicalSelector { |
| 506 return new dart2js.Selector.call('identical', null, 2); | 499 return new dart2js.Selector.call('identical', null, 2); |
| 507 } | 500 } |
| 508 | 501 |
| 509 Expression visitIdentical(cps_ir.Identical node) { | 502 Expression visitIdentical(cps_ir.Identical node) { |
| 510 return new InvokeStatic( | 503 return new InvokeStatic( |
| 511 compiler.identicalFunction, | 504 compiler.identicalFunction, |
| 512 identicalSelector, | 505 identicalSelector, |
| 513 <Expression>[getVariableReference(node.left), | 506 <Expression>[getVariableReference(node.left), |
| 514 getVariableReference(node.right)]); | 507 getVariableReference(node.right)]); |
| 515 } | 508 } |
| 516 | |
| 517 Expression visitInterceptor(cps_ir.Interceptor node) { | |
| 518 Element getInterceptor = glue.getInterceptorMethod; | |
| 519 glue.registerUseInterceptorInCodegen(); | |
| 520 return new InvokeStatic( | |
| 521 getInterceptor, | |
| 522 new dart2js.Selector.fromElement(getInterceptor), | |
| 523 <Expression>[getVariableReference(node.input)]); | |
| 524 } | |
| 525 } | 509 } |
| 526 | 510 |
| OLD | NEW |