| 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 '../util/util.dart' show CURRENT_ELEMENT_SPANNABLE; |
| 11 import 'tree_ir_nodes.dart'; | 12 import 'tree_ir_nodes.dart'; |
| 12 import '../js_backend/codegen/glue.dart'; | 13 import '../js_backend/codegen/glue.dart'; |
| 13 | 14 |
| 14 /** | 15 /** |
| 15 * Builder translates from CPS-based IR to direct-style Tree. | 16 * Builder translates from CPS-based IR to direct-style Tree. |
| 16 * | 17 * |
| 17 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced | 18 * 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 | 19 * non-exit continuation `Cont(v, body)` is translated into a direct-style call |
| 19 * whose value is bound in the continuation body: | 20 * whose value is bound in the continuation body: |
| 20 * | 21 * |
| (...skipping 16 matching lines...) Expand all Loading... |
| 37 * | 38 * |
| 38 * Block arguments are later replaced with data flow during the Tree-to-Tree | 39 * 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 | 40 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree |
| 40 * control-flow recognition. | 41 * control-flow recognition. |
| 41 * | 42 * |
| 42 * Otherwise, the output of Builder looks very much like the input. In | 43 * Otherwise, the output of Builder looks very much like the input. In |
| 43 * particular, intermediate values and blocks used for local control flow are | 44 * particular, intermediate values and blocks used for local control flow are |
| 44 * still all named. | 45 * still all named. |
| 45 */ | 46 */ |
| 46 class Builder extends cps_ir.Visitor<Node> { | 47 class Builder extends cps_ir.Visitor<Node> { |
| 47 // TODO(karlklose): remove the compiler. | 48 final dart2js.InternalErrorFunction internalError; |
| 48 final dart2js.Compiler compiler; | 49 final Element identicalFunction; |
| 49 final Glue glue; | 50 final Glue glue; |
| 50 | 51 |
| 51 /// Maps variable/parameter elements to the Tree variables that represent it. | 52 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 52 final Map<Element, List<Variable>> element2variables = | 53 final Map<Element, List<Variable>> element2variables = |
| 53 <Element,List<Variable>>{}; | 54 <Element,List<Variable>>{}; |
| 54 | 55 |
| 55 /// Like [element2variables], except for closure variables. | 56 /// Like [element2variables], except for closure variables. |
| 56 final Map<cps_ir.ClosureVariable, Variable> local2closure = | 57 final Map<cps_ir.ClosureVariable, Variable> local2closure = |
| 57 <cps_ir.ClosureVariable, Variable>{}; | 58 <cps_ir.ClosureVariable, Variable>{}; |
| 58 | 59 |
| 59 // Continuations with more than one use are replaced with Tree labels. This | 60 // Continuations with more than one use are replaced with Tree labels. This |
| 60 // is the mapping from continuations to labels. | 61 // is the mapping from continuations to labels. |
| 61 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; | 62 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; |
| 62 | 63 |
| 63 ExecutableElement currentElement; | 64 ExecutableElement currentElement; |
| 64 cps_ir.Continuation returnContinuation; | 65 cps_ir.Continuation returnContinuation; |
| 65 | 66 |
| 66 Builder parent; | 67 Builder parent; |
| 67 | 68 |
| 68 Builder(this.glue, this.compiler); | 69 Builder(this.glue, this.internalError, this.identicalFunction); |
| 69 | 70 |
| 70 Builder.inner(Builder parent) | 71 Builder.inner(Builder parent) |
| 71 : this.parent = parent, | 72 : this.parent = parent, |
| 72 this.glue = parent.glue, | 73 this.glue = parent.glue, |
| 73 compiler = parent.compiler; | 74 this.internalError = parent.internalError, |
| 75 this.identicalFunction = parent.identicalFunction; |
| 74 | 76 |
| 75 /// Variable used in [buildPhiAssignments] as a temporary when swapping | 77 /// Variable used in [buildPhiAssignments] as a temporary when swapping |
| 76 /// variables. | 78 /// variables. |
| 77 Variable phiTempVar; | 79 Variable phiTempVar; |
| 78 | 80 |
| 79 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { | 81 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { |
| 80 if (irVariable.host != currentElement) { | 82 if (irVariable.host != currentElement) { |
| 81 return parent.getClosureVariable(irVariable); | 83 return parent.getClosureVariable(irVariable); |
| 82 } | 84 } |
| 83 return local2closure.putIfAbsent(irVariable, | 85 return local2closure.putIfAbsent(irVariable, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 98 return variables[primitive.registerIndex]; | 100 return variables[primitive.registerIndex]; |
| 99 } | 101 } |
| 100 | 102 |
| 101 /// Obtains a reference to the tree Variable corresponding to the IR primitive | 103 /// Obtains a reference to the tree Variable corresponding to the IR primitive |
| 102 /// referred to by [reference]. | 104 /// referred to by [reference]. |
| 103 /// This increments the reference count for the given variable, so the | 105 /// This increments the reference count for the given variable, so the |
| 104 /// returned expression must be used in the tree. | 106 /// returned expression must be used in the tree. |
| 105 Expression getVariableReference(cps_ir.Reference reference) { | 107 Expression getVariableReference(cps_ir.Reference reference) { |
| 106 Variable variable = getVariable(reference.definition); | 108 Variable variable = getVariable(reference.definition); |
| 107 if (variable == null) { | 109 if (variable == null) { |
| 108 compiler.internalError( | 110 internalError( |
| 109 compiler.currentElement, | 111 CURRENT_ELEMENT_SPANNABLE, |
| 110 "Reference to ${reference.definition} has no register"); | 112 "Reference to ${reference.definition} has no register"); |
| 111 } | 113 } |
| 112 ++variable.readCount; | 114 ++variable.readCount; |
| 113 return variable; | 115 return variable; |
| 114 } | 116 } |
| 115 | 117 |
| 116 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { | 118 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { |
| 117 if (node is cps_ir.FieldDefinition) { | 119 if (node is cps_ir.FieldDefinition) { |
| 118 return buildField(node); | 120 return buildField(node); |
| 119 } else if (node is cps_ir.FunctionDefinition) { | 121 } else if (node is cps_ir.FunctionDefinition) { |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 // The successor will be filled in by visitLetPrim. | 480 // The successor will be filled in by visitLetPrim. |
| 479 return new FunctionDeclaration(getVariable(node), def, null); | 481 return new FunctionDeclaration(getVariable(node), def, null); |
| 480 } else { | 482 } else { |
| 481 return new FunctionExpression(def); | 483 return new FunctionExpression(def); |
| 482 } | 484 } |
| 483 } | 485 } |
| 484 | 486 |
| 485 Expression visitParameter(cps_ir.Parameter node) { | 487 Expression visitParameter(cps_ir.Parameter node) { |
| 486 // Continuation parameters are not visited (continuations themselves are | 488 // Continuation parameters are not visited (continuations themselves are |
| 487 // not visited yet). | 489 // not visited yet). |
| 488 compiler.internalError(compiler.currentElement, | 490 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node'); |
| 489 'Unexpected IR node: $node'); | |
| 490 return null; | 491 return null; |
| 491 } | 492 } |
| 492 | 493 |
| 493 Expression visitContinuation(cps_ir.Continuation node) { | 494 Expression visitContinuation(cps_ir.Continuation node) { |
| 494 // Until continuations with multiple uses are supported, they are not | 495 // Until continuations with multiple uses are supported, they are not |
| 495 // visited. | 496 // visited. |
| 496 compiler.internalError(compiler.currentElement, | 497 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); |
| 497 'Unexpected IR node: $node.'); | |
| 498 return null; | 498 return null; |
| 499 } | 499 } |
| 500 | 500 |
| 501 Expression visitIsTrue(cps_ir.IsTrue node) { | 501 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 502 return getVariableReference(node.value); | 502 return getVariableReference(node.value); |
| 503 } | 503 } |
| 504 | 504 |
| 505 dart2js.Selector get identicalSelector { | 505 dart2js.Selector get identicalSelector { |
| 506 return new dart2js.Selector.call('identical', null, 2); | 506 return new dart2js.Selector.call('identical', null, 2); |
| 507 } | 507 } |
| 508 | 508 |
| 509 Expression visitIdentical(cps_ir.Identical node) { | 509 Expression visitIdentical(cps_ir.Identical node) { |
| 510 return new InvokeStatic( | 510 return new InvokeStatic( |
| 511 compiler.identicalFunction, | 511 identicalFunction, |
| 512 identicalSelector, | 512 identicalSelector, |
| 513 <Expression>[getVariableReference(node.left), | 513 <Expression>[getVariableReference(node.left), |
| 514 getVariableReference(node.right)]); | 514 getVariableReference(node.right)]); |
| 515 } | 515 } |
| 516 | 516 |
| 517 Expression visitInterceptor(cps_ir.Interceptor node) { | 517 Expression visitInterceptor(cps_ir.Interceptor node) { |
| 518 Element getInterceptor = glue.getInterceptorMethod; | 518 Element getInterceptor = glue.getInterceptorMethod; |
| 519 glue.registerUseInterceptorInCodegen(); | 519 glue.registerUseInterceptorInCodegen(); |
| 520 return new InvokeStatic( | 520 return new InvokeStatic( |
| 521 getInterceptor, | 521 getInterceptor, |
| 522 new dart2js.Selector.fromElement(getInterceptor), | 522 new dart2js.Selector.fromElement(getInterceptor), |
| 523 <Expression>[getVariableReference(node.input)]); | 523 <Expression>[getVariableReference(node.input)]); |
| 524 } | 524 } |
| 525 } | 525 } |
| 526 | 526 |
| OLD | NEW |