Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |