Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart

Issue 459763003: dart2dart: Fix a scoping bug in the translation of loops. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/language/for_test.dart » ('j') | tests/language/for_test.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 677 }
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, ...) =
sigurdm 2014/08/12 07:25:53 Should this be loop(v, ...)?
Kevin Millikin (Google) 2014/08/12 08:54:55 It's not necessarily the same as the v, ... passed
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
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 }
OLDNEW
« no previous file with comments | « no previous file | tests/language/for_test.dart » ('j') | tests/language/for_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698