| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 /// This is not safe if the code is moved inside the scope of an exception | 62 /// This is not safe if the code is moved inside the scope of an exception |
| 63 /// handler (i.e., into a try block). We keep a stack of singly-referenced | 63 /// handler (i.e., into a try block). We keep a stack of singly-referenced |
| 64 /// continuations that are in scope without crossing a binding for a handler. | 64 /// continuations that are in scope without crossing a binding for a handler. |
| 65 List<cps_ir.Continuation> safeForInlining = <cps_ir.Continuation>[]; | 65 List<cps_ir.Continuation> safeForInlining = <cps_ir.Continuation>[]; |
| 66 | 66 |
| 67 ExecutableElement currentElement; | 67 ExecutableElement currentElement; |
| 68 /// The 'this' Parameter for currentElement or the enclosing method. | 68 /// The 'this' Parameter for currentElement or the enclosing method. |
| 69 cps_ir.Parameter thisParameter; | 69 cps_ir.Parameter thisParameter; |
| 70 cps_ir.Continuation returnContinuation; | 70 cps_ir.Continuation returnContinuation; |
| 71 | 71 |
| 72 /// Number of loops enclosing the currently visited node. | |
| 73 int enclosingLoops = 0; | |
| 74 | |
| 75 Builder parent; | 72 Builder parent; |
| 76 | 73 |
| 77 Builder(this.internalError, [this.parent]); | 74 Builder(this.internalError, [this.parent]); |
| 78 | 75 |
| 79 Builder createInnerBuilder() { | 76 Builder createInnerBuilder() { |
| 80 return new Builder(internalError, this); | 77 return new Builder(internalError, this); |
| 81 } | 78 } |
| 82 | 79 |
| 83 /// Variable used in [buildPhiAssignments] as a temporary when swapping | 80 /// Variable used in [buildPhiAssignments] as a temporary when swapping |
| 84 /// variables. | 81 /// variables. |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 nextBuilder); | 466 nextBuilder); |
| 470 } | 467 } |
| 471 } | 468 } |
| 472 | 469 |
| 473 Statement visitLetMutable(cps_ir.LetMutable node) { | 470 Statement visitLetMutable(cps_ir.LetMutable node) { |
| 474 Variable variable = addMutableVariable(node.variable); | 471 Variable variable = addMutableVariable(node.variable); |
| 475 Expression value = getVariableUse(node.value); | 472 Expression value = getVariableUse(node.value); |
| 476 Statement body = visit(node.body); | 473 Statement body = visit(node.body); |
| 477 // If the variable was captured by an inner function in the body, this | 474 // If the variable was captured by an inner function in the body, this |
| 478 // must be declared here so we assign to a fresh copy of the variable. | 475 // must be declared here so we assign to a fresh copy of the variable. |
| 479 if (variable.isCaptured && enclosingLoops > 0) { | 476 if (variable.isCaptured) { |
| 480 return new VariableDeclaration(variable, value, body); | 477 return new VariableDeclaration(variable, value, body); |
| 481 } | 478 } |
| 482 return Assign.makeStatement(variable, value, body); | 479 return Assign.makeStatement(variable, value, body); |
| 483 } | 480 } |
| 484 | 481 |
| 485 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 482 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 486 return getMutableVariableUse(node.variable); | 483 return getMutableVariableUse(node.variable); |
| 487 } | 484 } |
| 488 | 485 |
| 489 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { | 486 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 // inline at the invocation site. | 533 // inline at the invocation site. |
| 537 // - If there are multiple uses, translate to Break. | 534 // - If there are multiple uses, translate to Break. |
| 538 // * Recursive continuations | 535 // * Recursive continuations |
| 539 // - There is a single non-recursive invocation. Translate | 536 // - There is a single non-recursive invocation. Translate |
| 540 // the continuation body inline as a labeled loop at the | 537 // the continuation body inline as a labeled loop at the |
| 541 // invocation site. | 538 // invocation site. |
| 542 // - Translate the recursive invocations to Continue. | 539 // - Translate the recursive invocations to Continue. |
| 543 if (cont.isRecursive) { | 540 if (cont.isRecursive) { |
| 544 return node.isRecursive | 541 return node.isRecursive |
| 545 ? new Continue(labels[cont]) | 542 ? new Continue(labels[cont]) |
| 546 : new WhileTrue(labels[cont], makeLoopBody(cont.body)); | 543 : new WhileTrue(labels[cont], visit(cont.body)); |
| 547 } else { | 544 } else { |
| 548 if (cont.hasExactlyOneUse) { | 545 if (cont.hasExactlyOneUse) { |
| 549 if (safeForInlining.contains(cont)) { | 546 if (safeForInlining.contains(cont)) { |
| 550 return visit(cont.body); | 547 return visit(cont.body); |
| 551 } | 548 } |
| 552 labels[cont] = new Label(); | 549 labels[cont] = new Label(); |
| 553 } | 550 } |
| 554 return new Break(labels[cont]); | 551 return new Break(labels[cont]); |
| 555 } | 552 } |
| 556 }); | 553 }); |
| 557 } | 554 } |
| 558 } | 555 } |
| 559 | 556 |
| 560 Statement makeLoopBody(cps_ir.Expression body) { | |
| 561 ++enclosingLoops; | |
| 562 Statement result = visit(body); | |
| 563 --enclosingLoops; | |
| 564 return result; | |
| 565 } | |
| 566 | |
| 567 Statement visitBranch(cps_ir.Branch node) { | 557 Statement visitBranch(cps_ir.Branch node) { |
| 568 Expression condition = visit(node.condition); | 558 Expression condition = visit(node.condition); |
| 569 Statement thenStatement, elseStatement; | 559 Statement thenStatement, elseStatement; |
| 570 cps_ir.Continuation cont = node.trueContinuation.definition; | 560 cps_ir.Continuation cont = node.trueContinuation.definition; |
| 571 assert(cont.parameters.isEmpty); | 561 assert(cont.parameters.isEmpty); |
| 572 thenStatement = | 562 thenStatement = |
| 573 cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]); | 563 cont.hasExactlyOneUse ? visit(cont.body) : new Break(labels[cont]); |
| 574 cont = node.falseContinuation.definition; | 564 cont = node.falseContinuation.definition; |
| 575 assert(cont.parameters.isEmpty); | 565 assert(cont.parameters.isEmpty); |
| 576 elseStatement = | 566 elseStatement = |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 } | 641 } |
| 652 | 642 |
| 653 @override | 643 @override |
| 654 Node visitTypeExpression(cps_ir.TypeExpression node) { | 644 Node visitTypeExpression(cps_ir.TypeExpression node) { |
| 655 return new TypeExpression( | 645 return new TypeExpression( |
| 656 node.dartType, | 646 node.dartType, |
| 657 node.arguments.map(getVariableUse).toList()); | 647 node.arguments.map(getVariableUse).toList()); |
| 658 } | 648 } |
| 659 } | 649 } |
| 660 | 650 |
| OLD | NEW |