| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import 'cps_ir_nodes.dart' as ir; | 7 import 'cps_ir_nodes.dart' as ir; |
| 8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../dart2jslib.dart'; | 9 import '../dart2jslib.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 void invokeRecursiveJoin(ir.Continuation join, List<IrBuilder> contexts) { | 539 void invokeRecursiveJoin(ir.Continuation join, List<IrBuilder> contexts) { |
| 540 for (IrBuilder context in contexts) { | 540 for (IrBuilder context in contexts) { |
| 541 // Passing `this` as one of the contexts will not do the right thing | 541 // Passing `this` as one of the contexts will not do the right thing |
| 542 // (this.environment has already been mutated). | 542 // (this.environment has already been mutated). |
| 543 assert(context != this); | 543 assert(context != this); |
| 544 List<ir.Primitive> args = | 544 List<ir.Primitive> args = |
| 545 context.environment.index2value.sublist(0, join.parameters.length); | 545 context.environment.index2value.sublist(0, join.parameters.length); |
| 546 context.add(new ir.InvokeContinuation(join, args, recursive: true)); | 546 context.add(new ir.InvokeContinuation(join, args, recursive: true)); |
| 547 context.current = null; | 547 context.current = null; |
| 548 } | 548 } |
| 549 assert(environment.index2value.length <= join.parameters.length); | |
| 550 for (int i = 0; i < environment.index2value.length; ++i) { | |
| 551 environment.index2value[i] = join.parameters[i]; | |
| 552 } | |
| 553 } | 549 } |
| 554 | 550 |
| 555 ir.Primitive visitFor(ast.For node) { | 551 ir.Primitive visitFor(ast.For node) { |
| 556 assert(isOpen); | 552 assert(isOpen); |
| 557 // TODO(kmillikin,sigurdm): Handle closure variables declared in a for-loop. | 553 // TODO(kmillikin,sigurdm): Handle closure variables declared in a for-loop. |
| 558 if (node.initializer is ast.VariableDefinitions) { | 554 if (node.initializer is ast.VariableDefinitions) { |
| 559 ast.VariableDefinitions definitions = node.initializer; | 555 ast.VariableDefinitions definitions = node.initializer; |
| 560 for (ast.Node definition in definitions.definitions.nodes) { | 556 for (ast.Node definition in definitions.definitions.nodes) { |
| 561 Element element = elements[definition]; | 557 Element element = elements[definition]; |
| 562 if (isClosureVariable(element)) { | 558 if (isClosureVariable(element)) { |
| 563 return giveup(definition, 'Closure variable in for loop initializer'); | 559 return giveup(definition, 'Closure variable in for loop initializer'); |
| 564 } | 560 } |
| 565 } | 561 } |
| 566 } | 562 } |
| 567 | 563 |
| 568 // For loops use three named continuations: the entry to the condition, | 564 // For loops use three named continuations: the entry to the condition, |
| 569 // the entry to the body, and the loop exit (break). The CPS translation | 565 // the entry to the body, and the loop exit (break). The CPS translation |
| 570 // of [[for (initializer; condition; update) body; successor]] is: | 566 // of [[for (initializer; condition; update) body; successor]] is: |
| 571 // | 567 // |
| 572 // [[initializer]]; | 568 // [[initializer]]; |
| 573 // let cont loop(x, ...) = | 569 // let cont loop(x, ...) = |
| 570 // let prim cond = [[condition]] in |
| 574 // let cont exit() = [[successor]] in | 571 // let cont exit() = [[successor]] in |
| 575 // let cont body() = [[body]]; [[update]]; loop(v, ...) in | 572 // let cont body() = [[body]]; [[update]]; loop(v, ...) in |
| 576 // let prim cond = [[condition]] in | |
| 577 // branch cond (body, exit) in | 573 // branch cond (body, exit) in |
| 578 // loop(v, ...) | 574 // loop(v, ...) |
| 579 | 575 |
| 580 if (node.initializer != null) visit(node.initializer); | 576 if (node.initializer != null) visit(node.initializer); |
| 581 | 577 |
| 582 IrBuilder condBuilder = new IrBuilder.recursive(this); | 578 IrBuilder condBuilder = new IrBuilder.recursive(this); |
| 583 ir.Primitive condition; | 579 ir.Primitive condition; |
| 584 if (node.condition == null) { | 580 if (node.condition == null) { |
| 585 // If the condition is empty then the body is entered unconditionally. | 581 // If the condition is empty then the body is entered unconditionally. |
| 586 condition = makePrimConst(constantSystem.createBool(true)); | 582 condition = makePrimConst(constantSystem.createBool(true)); |
| 587 condBuilder.add(new ir.LetPrim(condition)); | 583 condBuilder.add(new ir.LetPrim(condition)); |
| 588 } else { | 584 } else { |
| 589 condition = condBuilder.visit(node.condition); | 585 condition = condBuilder.visit(node.condition); |
| 590 } | 586 } |
| 591 | 587 |
| 592 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); | 588 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); |
| 593 bodyBuilder.visit(node.body); | 589 bodyBuilder.visit(node.body); |
| 594 for (ast.Node n in node.update) { | 590 for (ast.Node n in node.update) { |
| 595 if (!bodyBuilder.isOpen) break; | 591 if (!bodyBuilder.isOpen) break; |
| 596 bodyBuilder.visit(n); | 592 bodyBuilder.visit(n); |
| 597 } | 593 } |
| 598 | 594 |
| 599 // Create body entry and loop exit continuations and a join-point | 595 // Create body entry and loop exit continuations and a join-point |
| 600 // continuation if control flow reaches the end of the body (update). | 596 // continuation if control flow reaches the end of the body (update). |
| 601 ir.Continuation bodyContinuation = new ir.Continuation([]); | 597 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 602 ir.Continuation exitContinuation = new ir.Continuation([]); | 598 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 603 condBuilder.add(new ir.Branch(new ir.IsTrue(condition), | 599 condBuilder.add( |
| 604 bodyContinuation, | 600 new ir.LetCont(exitContinuation, |
| 605 exitContinuation)); | 601 new ir.LetCont(bodyContinuation, |
| 602 new ir.Branch(new ir.IsTrue(condition), |
| 603 bodyContinuation, |
| 604 exitContinuation)))); |
| 606 List<ir.Parameter> parameters = condBuilder.parameters; | 605 List<ir.Parameter> parameters = condBuilder.parameters; |
| 607 ir.Continuation loopContinuation = new ir.Continuation(parameters); | 606 ir.Continuation loopContinuation = new ir.Continuation(parameters); |
| 608 // Copy the environment here because invokeJoin will update it for the | |
| 609 // join-point continuation. | |
| 610 List<ir.Primitive> entryArguments = | |
| 611 new List<ir.Primitive>.from(environment.index2value); | |
| 612 if (bodyBuilder.isOpen) { | 607 if (bodyBuilder.isOpen) { |
| 613 invokeRecursiveJoin(loopContinuation, [bodyBuilder]); | 608 invokeRecursiveJoin(loopContinuation, [bodyBuilder]); |
| 614 } | 609 } |
| 615 bodyContinuation.body = bodyBuilder.root; | 610 bodyContinuation.body = bodyBuilder.root; |
| 616 | 611 |
| 617 ir.Expression resultContext = | 612 loopContinuation.body = condBuilder.root; |
| 618 new ir.LetCont(exitContinuation, | |
| 619 new ir.LetCont(bodyContinuation, | |
| 620 condBuilder.root)); | |
| 621 loopContinuation.body = resultContext; | |
| 622 add(new ir.LetCont(loopContinuation, | 613 add(new ir.LetCont(loopContinuation, |
| 623 new ir.InvokeContinuation(loopContinuation, entryArguments))); | 614 new ir.InvokeContinuation(loopContinuation, |
| 624 current = resultContext; | 615 environment.index2value))); |
| 616 current = condBuilder.current; |
| 617 environment = condBuilder.environment; |
| 625 return null; | 618 return null; |
| 626 } | 619 } |
| 627 | 620 |
| 628 ir.Primitive visitIf(ast.If node) { | 621 ir.Primitive visitIf(ast.If node) { |
| 629 assert(isOpen); | 622 assert(isOpen); |
| 630 ir.Primitive condition = visit(node.condition); | 623 ir.Primitive condition = visit(node.condition); |
| 631 | 624 |
| 632 // The then and else parts are delimited. | 625 // The then and else parts are delimited. |
| 633 IrBuilder thenBuilder = new IrBuilder.delimited(this); | 626 IrBuilder thenBuilder = new IrBuilder.delimited(this); |
| 634 IrBuilder elseBuilder = new IrBuilder.delimited(this); | 627 IrBuilder elseBuilder = new IrBuilder.delimited(this); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 return null; | 678 return null; |
| 686 } | 679 } |
| 687 | 680 |
| 688 ir.Primitive visitWhile(ast.While node) { | 681 ir.Primitive visitWhile(ast.While node) { |
| 689 assert(isOpen); | 682 assert(isOpen); |
| 690 // While loops use three named continuations: the entry to the body, | 683 // While loops use three named continuations: the entry to the body, |
| 691 // the loop exit (break), and the loop back edge (continue). | 684 // the loop exit (break), and the loop back edge (continue). |
| 692 // The CPS translation of [[while (condition) body; successor]] is: | 685 // The CPS translation of [[while (condition) body; successor]] is: |
| 693 // | 686 // |
| 694 // let cont loop(x, ...) = | 687 // let cont loop(x, ...) = |
| 688 // let prim cond = [[condition]] in |
| 695 // let cont exit() = [[successor]] in | 689 // let cont exit() = [[successor]] in |
| 696 // let cont body() = [[body]]; continue(v, ...) in | 690 // let cont body() = [[body]]; continue(v, ...) in |
| 697 // let prim cond = [[condition]] in | |
| 698 // branch cond (body, exit) in | 691 // branch cond (body, exit) in |
| 699 // loop(v, ...) | 692 // loop(v, ...) |
| 700 | 693 |
| 701 // The condition and body are delimited. | 694 // The condition and body are delimited. |
| 702 IrBuilder condBuilder = new IrBuilder.recursive(this); | 695 IrBuilder condBuilder = new IrBuilder.recursive(this); |
| 703 ir.Primitive condition = condBuilder.visit(node.condition); | 696 ir.Primitive condition = condBuilder.visit(node.condition); |
| 704 | 697 |
| 705 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); | 698 IrBuilder bodyBuilder = new IrBuilder.delimited(condBuilder); |
| 706 bodyBuilder.visit(node.body); | 699 bodyBuilder.visit(node.body); |
| 707 | 700 |
| 708 // Create body entry and loop exit continuations and a join-point | 701 // Create body entry and loop exit continuations and a join-point |
| 709 // continuation if control flow reaches the end of the body. | 702 // continuation if control flow reaches the end of the body. |
| 710 ir.Continuation bodyContinuation = new ir.Continuation([]); | 703 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 711 ir.Continuation exitContinuation = new ir.Continuation([]); | 704 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 712 condBuilder.add(new ir.Branch(new ir.IsTrue(condition), | 705 condBuilder.add( |
| 713 bodyContinuation, | 706 new ir.LetCont(exitContinuation, |
| 714 exitContinuation)); | 707 new ir.LetCont(bodyContinuation, |
| 708 new ir.Branch(new ir.IsTrue(condition), |
| 709 bodyContinuation, |
| 710 exitContinuation)))); |
| 715 List<ir.Parameter> parameters = condBuilder.parameters; | 711 List<ir.Parameter> parameters = condBuilder.parameters; |
| 716 ir.Continuation loopContinuation = new ir.Continuation(parameters); | 712 ir.Continuation loopContinuation = new ir.Continuation(parameters); |
| 717 // Copy the environment here because invokeJoin will update it for the | |
| 718 // join-point continuation. | |
| 719 List<ir.Primitive> entryArguments = | |
| 720 new List<ir.Primitive>.from(environment.index2value); | |
| 721 if (bodyBuilder.isOpen) { | 713 if (bodyBuilder.isOpen) { |
| 722 invokeRecursiveJoin(loopContinuation, [bodyBuilder]); | 714 invokeRecursiveJoin(loopContinuation, [bodyBuilder]); |
| 723 } | 715 } |
| 724 bodyContinuation.body = bodyBuilder.root; | 716 bodyContinuation.body = bodyBuilder.root; |
| 725 | 717 |
| 726 ir.Expression resultContext = | 718 loopContinuation.body = condBuilder.root; |
| 727 new ir.LetCont(exitContinuation, | |
| 728 new ir.LetCont(bodyContinuation, | |
| 729 condBuilder.root)); | |
| 730 loopContinuation.body = resultContext; | |
| 731 add(new ir.LetCont(loopContinuation, | 719 add(new ir.LetCont(loopContinuation, |
| 732 new ir.InvokeContinuation(loopContinuation, entryArguments))); | 720 new ir.InvokeContinuation(loopContinuation, |
| 733 current = resultContext; | 721 environment.index2value))); |
| 722 current = condBuilder.current; |
| 723 environment = condBuilder.environment; |
| 734 return null; | 724 return null; |
| 735 } | 725 } |
| 736 | 726 |
| 737 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { | 727 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { |
| 738 assert(isOpen); | 728 assert(isOpen); |
| 739 if (node.modifiers.isConst) { | 729 if (node.modifiers.isConst) { |
| 740 for (ast.SendSet definition in node.definitions.nodes) { | 730 for (ast.SendSet definition in node.definitions.nodes) { |
| 741 assert(!definition.arguments.isEmpty); | 731 assert(!definition.arguments.isEmpty); |
| 742 assert(definition.arguments.tail.isEmpty); | 732 assert(definition.arguments.tail.isEmpty); |
| 743 VariableElement element = elements[definition]; | 733 VariableElement element = elements[definition]; |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1674 } | 1664 } |
| 1675 | 1665 |
| 1676 visitFunctionExpression(ast.FunctionExpression node) { | 1666 visitFunctionExpression(ast.FunctionExpression node) { |
| 1677 FunctionElement oldFunction = currentFunction; | 1667 FunctionElement oldFunction = currentFunction; |
| 1678 currentFunction = elements[node]; | 1668 currentFunction = elements[node]; |
| 1679 visit(node.body); | 1669 visit(node.body); |
| 1680 currentFunction = oldFunction; | 1670 currentFunction = oldFunction; |
| 1681 } | 1671 } |
| 1682 | 1672 |
| 1683 } | 1673 } |
| OLD | NEW |