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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 331343004: Avoid critical edge for loop-exits. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove bad comment. Created 6 years, 6 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of ssa; 5 part of ssa;
6 6
7 class SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 currentBlockInformation = oldInfo; 748 currentBlockInformation = oldInfo;
749 } else { 749 } else {
750 generateStatements(info.body); 750 generateStatements(info.body);
751 } 751 }
752 } 752 }
753 753
754 bool visitLoopInfo(HLoopBlockInformation info) { 754 bool visitLoopInfo(HLoopBlockInformation info) {
755 HExpressionInformation condition = info.condition; 755 HExpressionInformation condition = info.condition;
756 bool isConditionExpression = isJSCondition(condition); 756 bool isConditionExpression = isJSCondition(condition);
757 757
758 // Assert that the block we inserted to avoid critical edges satisfies
759 // basic assumptions.
760 assert(!condition.end.successors.last.isEmpty);
761 assert(condition.end.successors.last.first is HGoto);
762 assert(condition.end.successors.last.first.next == null);
ngeoffray 2014/06/24 12:39:14 Should that be in validator.dart instead?
floitsch 2014/06/24 14:44:38 Done.
763
758 js.Loop loop; 764 js.Loop loop;
759 765
760 switch (info.kind) { 766 switch (info.kind) {
761 // Treate all three "test-first" loops the same way. 767 // Treate all three "test-first" loops the same way.
762 case HLoopBlockInformation.FOR_LOOP: 768 case HLoopBlockInformation.FOR_LOOP:
763 case HLoopBlockInformation.WHILE_LOOP: 769 case HLoopBlockInformation.WHILE_LOOP:
764 case HLoopBlockInformation.FOR_IN_LOOP: 770 case HLoopBlockInformation.FOR_IN_LOOP:
765 case HLoopBlockInformation.SWITCH_CONTINUE_LOOP: 771 case HLoopBlockInformation.SWITCH_CONTINUE_LOOP:
766 HBlockInformation initialization = info.initializer; 772 HBlockInformation initialization = info.initializer;
767 int initializationType = TYPE_STATEMENT; 773 int initializationType = TYPE_STATEMENT;
768 if (initialization != null) { 774 if (initialization != null) {
769 initializationType = expressionType(initialization); 775 initializationType = expressionType(initialization);
770 if (initializationType == TYPE_STATEMENT) { 776 if (initializationType == TYPE_STATEMENT) {
771 generateStatements(initialization); 777 generateStatements(initialization);
772 initialization = null; 778 initialization = null;
773 } 779 }
774 } 780 }
781
782 // We inserted a basic block to avoid critical edges. This block is
783 // part of the LoopBlockInformation and must therefore be handled here.
784 js.Block oldContainer = currentContainer;
785 js.Block avoidContainer = new js.Block.empty();
786 currentContainer = avoidContainer;
787 assignPhisOfSuccessors(condition.end.successors.last);
788 bool hasPhiUpdates = !avoidContainer.statements.isEmpty;
789 currentContainer = oldContainer;
790
775 if (isConditionExpression && 791 if (isConditionExpression &&
792 !hasPhiUpdates &&
776 info.updates != null && isJSExpression(info.updates)) { 793 info.updates != null && isJSExpression(info.updates)) {
777 // If we have an updates graph, and it's expressible as an 794 // If we have an updates graph, and it's expressible as an
778 // expression, generate a for-loop. 795 // expression, generate a for-loop.
779 js.Expression jsInitialization = null; 796 js.Expression jsInitialization = null;
780 if (initialization != null) { 797 if (initialization != null) {
781 int delayedVariablesCount = collectedVariableDeclarations.length; 798 int delayedVariablesCount = collectedVariableDeclarations.length;
782 jsInitialization = generateExpression(initialization); 799 jsInitialization = generateExpression(initialization);
783 if (!shouldGroupVarDeclarations && 800 if (!shouldGroupVarDeclarations &&
784 delayedVariablesCount < collectedVariableDeclarations.length) { 801 delayedVariablesCount < collectedVariableDeclarations.length) {
785 // We just added a new delayed variable-declaration. See if we can 802 // We just added a new delayed variable-declaration. See if we can
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 jsInitialization = new js.VariableDeclarationList(inits); 838 jsInitialization = new js.VariableDeclarationList(inits);
822 } 839 }
823 } 840 }
824 } 841 }
825 js.Expression jsCondition = generateExpression(condition); 842 js.Expression jsCondition = generateExpression(condition);
826 js.Expression jsUpdates = generateExpression(info.updates); 843 js.Expression jsUpdates = generateExpression(info.updates);
827 // The body might be labeled. Ignore this when recursing on the 844 // The body might be labeled. Ignore this when recursing on the
828 // subgraph. 845 // subgraph.
829 // TODO(lrn): Remove this extra labeling when handling all loops 846 // TODO(lrn): Remove this extra labeling when handling all loops
830 // using subgraphs. 847 // using subgraphs.
831 js.Block oldContainer = currentContainer; 848 oldContainer = currentContainer;
832 js.Statement body = new js.Block.empty(); 849 js.Statement body = new js.Block.empty();
833 currentContainer = body; 850 currentContainer = body;
834 visitBodyIgnoreLabels(info); 851 visitBodyIgnoreLabels(info);
835 currentContainer = oldContainer; 852 currentContainer = oldContainer;
836 body = unwrapStatement(body); 853 body = unwrapStatement(body);
837 loop = new js.For(jsInitialization, jsCondition, jsUpdates, body); 854 loop = new js.For(jsInitialization, jsCondition, jsUpdates, body);
838 } else { 855 } else {
839 // We have either no update graph, or it's too complex to 856 // We have either no update graph, or it's too complex to
840 // put in an expression. 857 // put in an expression.
841 if (initialization != null) { 858 if (initialization != null) {
842 generateStatements(initialization); 859 generateStatements(initialization);
843 } 860 }
844 js.Expression jsCondition; 861 js.Expression jsCondition;
845 js.Block oldContainer = currentContainer; 862 js.Block oldContainer = currentContainer;
846 js.Statement body = new js.Block.empty(); 863 js.Statement body = new js.Block.empty();
847 if (isConditionExpression) { 864 if (isConditionExpression && !hasPhiUpdates) {
848 jsCondition = generateExpression(condition); 865 jsCondition = generateExpression(condition);
849 currentContainer = body; 866 currentContainer = body;
850 } else { 867 } else {
851 jsCondition = newLiteralBool(true); 868 jsCondition = newLiteralBool(true);
852 currentContainer = body; 869 currentContainer = body;
853 generateStatements(condition); 870 generateStatements(condition);
854 use(condition.conditionExpression); 871 use(condition.conditionExpression);
855 js.Expression ifTest = new js.Prefix("!", pop()); 872 js.Expression ifTest = new js.Prefix("!", pop());
856 js.Break jsBreak = new js.Break(null); 873 js.Statement jsBreak = new js.Break(null);
857 pushStatement(new js.If.noElse(ifTest, jsBreak)); 874 js.Statement exitLoop;
875 if (avoidContainer.statements.isEmpty) {
876 exitLoop = jsBreak;
877 } else {
878 avoidContainer.statements.add(jsBreak);
879 exitLoop = avoidContainer;
880 }
881 pushStatement(new js.If.noElse(ifTest, exitLoop));
858 } 882 }
859 if (info.updates != null) { 883 if (info.updates != null) {
860 wrapLoopBodyForContinue(info); 884 wrapLoopBodyForContinue(info);
861 generateStatements(info.updates); 885 generateStatements(info.updates);
862 } else { 886 } else {
863 visitBodyIgnoreLabels(info); 887 visitBodyIgnoreLabels(info);
864 } 888 }
865 currentContainer = oldContainer; 889 currentContainer = oldContainer;
866 body = unwrapStatement(body); 890 body = unwrapStatement(body);
867 loop = new js.While(jsCondition, body); 891 loop = new js.While(jsCondition, body);
868 } 892 }
869 break; 893 break;
870 case HLoopBlockInformation.DO_WHILE_LOOP: 894 case HLoopBlockInformation.DO_WHILE_LOOP:
871 if (info.initializer != null) { 895 if (info.initializer != null) {
872 generateStatements(info.initializer); 896 generateStatements(info.initializer);
873 } 897 }
898 // We inserted a basic block to avoid critical edges. This block is
899 // part of the LoopBlockInformation and must therefore be handled here.
874 js.Block oldContainer = currentContainer; 900 js.Block oldContainer = currentContainer;
901 js.Block exitAvoidContainer = new js.Block.empty();
902 currentContainer = exitAvoidContainer;
903 assignPhisOfSuccessors(condition.end.successors.last);
904 bool hasExitPhiUpdates = !exitAvoidContainer.statements.isEmpty;
905 currentContainer = oldContainer;
906
907
908 oldContainer = currentContainer;
875 js.Block body = new js.Block.empty(); 909 js.Block body = new js.Block.empty();
876 // If there are phi copies in the block that jumps to the 910 // If there are phi copies in the block that jumps to the
877 // loop entry, we must emit the condition like this: 911 // loop entry, we must emit the condition like this:
878 // do { 912 // do {
879 // body; 913 // body;
880 // if (condition) { 914 // if (condition) {
881 // phi updates; 915 // phi updates;
882 // continue; 916 // continue;
883 // } else { 917 // } else {
884 // break; 918 // break;
(...skipping 15 matching lines...) Expand all
900 generateStatements(condition); 934 generateStatements(condition);
901 use(condition.conditionExpression); 935 use(condition.conditionExpression);
902 } 936 }
903 js.Expression jsCondition = pop(); 937 js.Expression jsCondition = pop();
904 if (jsCondition == null) { 938 if (jsCondition == null) {
905 // If the condition is dead code, we turn the do-while into 939 // If the condition is dead code, we turn the do-while into
906 // a simpler while because we will never reach the condition 940 // a simpler while because we will never reach the condition
907 // at the end of the loop anyway. 941 // at the end of the loop anyway.
908 loop = new js.While(newLiteralBool(true), unwrapStatement(body)); 942 loop = new js.While(newLiteralBool(true), unwrapStatement(body));
909 } else { 943 } else {
910 if (hasPhiUpdates) { 944 if (hasPhiUpdates || hasExitPhiUpdates) {
911 updateBody.statements.add(new js.Continue(null)); 945 updateBody.statements.add(new js.Continue(null));
946 js.Statement jsBreak = new js.Break(null);
947 js.Statement exitLoop;
948 if (exitAvoidContainer.statements.isEmpty) {
949 exitLoop = jsBreak;
950 } else {
951 exitAvoidContainer.statements.add(jsBreak);
952 exitLoop = exitAvoidContainer;
953 }
912 body.statements.add( 954 body.statements.add(
913 new js.If(jsCondition, updateBody, new js.Break(null))); 955 new js.If(jsCondition, updateBody, exitLoop));
914 jsCondition = newLiteralBool(true); 956 jsCondition = newLiteralBool(true);
915 } 957 }
916 loop = new js.Do(unwrapStatement(body), jsCondition); 958 loop = new js.Do(unwrapStatement(body), jsCondition);
917 } 959 }
918 currentContainer = oldContainer; 960 currentContainer = oldContainer;
919 break; 961 break;
920 default: 962 default:
921 compiler.internalError(condition.conditionExpression, 963 compiler.internalError(condition.conditionExpression,
922 'Unexpected loop kind: ${info.kind}.'); 964 'Unexpected loop kind: ${info.kind}.');
923 } 965 }
(...skipping 1751 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 js.PropertyAccess accessHelper(String name) { 2717 js.PropertyAccess accessHelper(String name) {
2676 Element helper = compiler.findHelper(name); 2718 Element helper = compiler.findHelper(name);
2677 if (helper == null) { 2719 if (helper == null) {
2678 // For mocked-up tests. 2720 // For mocked-up tests.
2679 return js.js('(void 0).$name'); 2721 return js.js('(void 0).$name');
2680 } 2722 }
2681 registry.registerStaticUse(helper); 2723 registry.registerStaticUse(helper);
2682 return backend.namer.elementAccess(helper); 2724 return backend.namer.elementAccess(helper);
2683 } 2725 }
2684 } 2726 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698