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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
6 | 6 |
7 final JavaScriptBackend backend; | 7 final JavaScriptBackend backend; |
8 | 8 |
9 SsaCodeGeneratorTask(JavaScriptBackend backend) | 9 SsaCodeGeneratorTask(JavaScriptBackend backend) |
10 : this.backend = backend, | 10 : this.backend = backend, |
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1095 } | 1095 } |
1096 | 1096 |
1097 void emitAssignment(String destination, String source) { | 1097 void emitAssignment(String destination, String source) { |
1098 assignVariable(destination, new js.VariableUse(source)); | 1098 assignVariable(destination, new js.VariableUse(source)); |
1099 } | 1099 } |
1100 | 1100 |
1101 /** | 1101 /** |
1102 * Sequentialize a list of conceptually parallel copies. Parallel | 1102 * Sequentialize a list of conceptually parallel copies. Parallel |
1103 * copies may contain cycles, that this method breaks. | 1103 * copies may contain cycles, that this method breaks. |
1104 */ | 1104 */ |
1105 void sequentializeCopies(List<Copy> copies) { | 1105 void sequentializeCopies(List<Copy> copies, |
1106 String tempName, | |
ngeoffray
2012/10/25 11:27:45
Why parameterizing tempName? It's swapTemp for bot
floitsch
2012/10/31 14:49:19
I don't want sequentializeCopies to deal with the
| |
1107 void doAssignment(String target, String source)) { | |
1106 // Map to keep track of the current location (ie the variable that | 1108 // Map to keep track of the current location (ie the variable that |
1107 // holds the initial value) of a variable. | 1109 // holds the initial value) of a variable. |
1108 Map<String, String> currentLocation = new Map<String, String>(); | 1110 Map<String, String> currentLocation = new Map<String, String>(); |
1109 | 1111 |
1110 // Map to keep track of the initial value of a variable. | 1112 // Map to keep track of the initial value of a variable. |
1111 Map<String, String> initialValue = new Map<String, String>(); | 1113 Map<String, String> initialValue = new Map<String, String>(); |
1112 | 1114 |
1113 // List of variables to assign a value. | 1115 // List of variables to assign a value. |
1114 List<String> worklist = <String>[]; | 1116 List<String> worklist = <String>[]; |
1115 | 1117 |
1116 // List of variables that we can assign a value to (ie are not | 1118 // List of variables that we can assign a value to (ie are not |
1117 // being used anymore). | 1119 // being used anymore). |
1118 List<String> ready = <String>[]; | 1120 List<String> ready = <String>[]; |
1119 | 1121 |
1120 // Prune [copies] by removing self-copies. | 1122 // Prune [copies] by removing self-copies. |
1121 List<Copy> prunedCopies = <Copy>[]; | 1123 List<Copy> prunedCopies = <Copy>[]; |
1122 for (Copy copy in copies) { | 1124 for (Copy copy in copies) { |
1123 String sourceName = variableNames.getName(copy.source); | 1125 if (copy.source != copy.destination) { |
1124 String destinationName = variableNames.getName(copy.destination); | 1126 prunedCopies.add(copy); |
1125 if (sourceName != destinationName) { | |
1126 prunedCopies.add(new Copy(sourceName, destinationName)); | |
1127 } | 1127 } |
1128 } | 1128 } |
1129 copies = prunedCopies; | 1129 copies = prunedCopies; |
1130 | 1130 |
1131 | 1131 |
1132 // For each copy, set the current location of the source to | 1132 // For each copy, set the current location of the source to |
1133 // itself, and the initial value of the destination to the source. | 1133 // itself, and the initial value of the destination to the source. |
1134 // Add the destination to the list of copies to make. | 1134 // Add the destination to the list of copies to make. |
1135 for (Copy copy in copies) { | 1135 for (Copy copy in copies) { |
1136 currentLocation[copy.source] = copy.source; | 1136 currentLocation[copy.source] = copy.source; |
1137 initialValue[copy.destination] = copy.source; | 1137 initialValue[copy.destination] = copy.source; |
1138 worklist.add(copy.destination); | 1138 worklist.add(copy.destination); |
1139 } | 1139 } |
1140 | 1140 |
1141 // For each copy, if the destination does not have a current | 1141 // For each copy, if the destination does not have a current |
1142 // location, then we can safely assign to it. | 1142 // location, then we can safely assign to it. |
1143 for (Copy copy in copies) { | 1143 for (Copy copy in copies) { |
1144 if (currentLocation[copy.destination] == null) { | 1144 if (currentLocation[copy.destination] == null) { |
1145 ready.add(copy.destination); | 1145 ready.add(copy.destination); |
1146 } | 1146 } |
1147 } | 1147 } |
1148 | 1148 |
1149 while (!worklist.isEmpty()) { | 1149 while (!worklist.isEmpty()) { |
1150 while (!ready.isEmpty()) { | 1150 while (!ready.isEmpty()) { |
1151 String destination = ready.removeLast(); | 1151 String destination = ready.removeLast(); |
1152 String source = initialValue[destination]; | 1152 String source = initialValue[destination]; |
1153 // Since [source] might have been updated, use the current | 1153 // Since [source] might have been updated, use the current |
1154 // location of [source] | 1154 // location of [source] |
1155 String copy = currentLocation[source]; | 1155 String copy = currentLocation[source]; |
1156 emitAssignment(destination, copy); | 1156 doAssignment(destination, copy); |
1157 // Now [destination] is the current location of [source]. | 1157 // Now [destination] is the current location of [source]. |
1158 currentLocation[source] = destination; | 1158 currentLocation[source] = destination; |
1159 // If [source] hasn't been updated and needs to have a value, | 1159 // If [source] hasn't been updated and needs to have a value, |
1160 // add it to the list of variables that can be updated. Copies | 1160 // add it to the list of variables that can be updated. Copies |
1161 // of [source] will now use [destination]. | 1161 // of [source] will now use [destination]. |
1162 if (source == copy && initialValue[source] != null) { | 1162 if (source == copy && initialValue[source] != null) { |
1163 ready.add(source); | 1163 ready.add(source); |
1164 } | 1164 } |
1165 } | 1165 } |
1166 | 1166 |
1167 // Check if we have a cycle. | 1167 // Check if we have a cycle. |
1168 String current = worklist.removeLast(); | 1168 String current = worklist.removeLast(); |
1169 // If [current] is used as a source, and the assignment has been | 1169 // If [current] is used as a source, and the assignment has been |
1170 // done, we are done with this variable. Otherwise there is a | 1170 // done, we are done with this variable. Otherwise there is a |
1171 // cycle that we break by using a temporary name. | 1171 // cycle that we break by using a temporary name. |
1172 if (currentLocation[current] != null | 1172 if (currentLocation[current] != null |
1173 && current != currentLocation[initialValue[current]]) { | 1173 && current != currentLocation[initialValue[current]]) { |
1174 String tempName = variableNames.swapTemp; | 1174 doAssignment(tempName, current); |
1175 emitAssignment(tempName, current); | |
1176 currentLocation[current] = tempName; | 1175 currentLocation[current] = tempName; |
1177 // [current] can now be safely updated. Copies of [current] | 1176 // [current] can now be safely updated. Copies of [current] |
1178 // will now use [tempName]. | 1177 // will now use [tempName]. |
1179 ready.add(current); | 1178 ready.add(current); |
1180 } | 1179 } |
1181 } | 1180 } |
1182 } | 1181 } |
1183 | 1182 |
1184 void assignPhisOfSuccessors(HBasicBlock node) { | 1183 void assignPhisOfSuccessors(HBasicBlock node) { |
1185 CopyHandler handler = variableNames.getCopyHandler(node); | 1184 CopyHandler handler = variableNames.getCopyHandler(node); |
1186 if (handler == null) return; | 1185 if (handler == null) return; |
1187 | 1186 |
1188 sequentializeCopies(handler.copies); | 1187 // Map the instructions to strings. |
1188 List<Copy> copies = handler.copies.map((Copy copy) { | |
1189 return new Copy(variableNames.getName(copy.source), | |
1190 variableNames.getName(copy.destination)); | |
1191 }); | |
1192 | |
1193 sequentializeCopies(copies, variableNames.swapTemp, emitAssignment); | |
1189 | 1194 |
1190 for (Copy copy in handler.assignments) { | 1195 for (Copy copy in handler.assignments) { |
1191 String name = variableNames.getName(copy.destination); | 1196 String name = variableNames.getName(copy.destination); |
1192 use(copy.source); | 1197 use(copy.source); |
1193 assignVariable(name, pop()); | 1198 assignVariable(name, pop()); |
1194 } | 1199 } |
1195 } | 1200 } |
1196 | 1201 |
1197 void iterateBasicBlock(HBasicBlock node) { | 1202 void iterateBasicBlock(HBasicBlock node) { |
1198 HInstruction instruction = node.first; | 1203 HInstruction instruction = node.first; |
(...skipping 1588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2787 if (!propagator.hasComplexBailoutTargets) return; | 2792 if (!propagator.hasComplexBailoutTargets) return; |
2788 | 2793 |
2789 js.Block nextBlock = new js.Block.empty(); | 2794 js.Block nextBlock = new js.Block.empty(); |
2790 js.Case clause = new js.Case(new js.LiteralNumber('${node.state}'), | 2795 js.Case clause = new js.Case(new js.LiteralNumber('${node.state}'), |
2791 nextBlock); | 2796 nextBlock); |
2792 currentBailoutSwitch.cases.add(clause); | 2797 currentBailoutSwitch.cases.add(clause); |
2793 currentContainer = nextBlock; | 2798 currentContainer = nextBlock; |
2794 pushExpressionAsStatement(new js.Assignment(generateStateUse(), | 2799 pushExpressionAsStatement(new js.Assignment(generateStateUse(), |
2795 new js.LiteralNumber('0'))); | 2800 new js.LiteralNumber('0'))); |
2796 js.Block setupBlock = new js.Block.empty(); | 2801 js.Block setupBlock = new js.Block.empty(); |
2797 int i = 0; | 2802 List<Copy> copies = <Copy>[]; |
2798 for (HInstruction input in node.inputs) { | 2803 for (int i = 0; i < node.inputs.length; i++) { |
2804 HInstruction input = node.inputs[i]; | |
2799 input = unwrap(input); | 2805 input = unwrap(input); |
2800 String name = variableNames.getName(input); | 2806 String name = variableNames.getName(input); |
2801 if (!isVariableDeclared(name)) { | 2807 String source = "env$i"; |
2802 declaredVariables.add(name); | 2808 copies.add(new Copy(source, name)); |
2809 } | |
2810 sequentializeCopies(copies, | |
2811 variableNames.swapTemp, | |
2812 (String target, String source) { | |
2813 if (!isVariableDeclared(target)) { | |
2814 declaredVariables.add(target); | |
2803 js.VariableInitialization init = | 2815 js.VariableInitialization init = |
2804 new js.VariableInitialization(new js.VariableDeclaration(name), | 2816 new js.VariableInitialization(new js.VariableDeclaration(target), |
2805 new js.VariableUse('env$i')); | 2817 new js.VariableUse(source)); |
2806 js.Expression varList = | 2818 js.Expression varList = |
2807 new js.VariableDeclarationList(<js.VariableInitialization>[init]); | 2819 new js.VariableDeclarationList(<js.VariableInitialization>[init]); |
2808 setupBlock.statements.add(new js.ExpressionStatement(varList)); | 2820 setupBlock.statements.add(new js.ExpressionStatement(varList)); |
2809 } else { | 2821 } else { |
2810 js.Expression target = new js.VariableUse(name); | 2822 js.Expression jsTarget = new js.VariableUse(target); |
2811 js.Expression source = new js.VariableUse('env$i'); | 2823 js.Expression jsSource = new js.VariableUse(source); |
2812 js.Expression assignment = new js.Assignment(target, source); | 2824 js.Expression assignment = new js.Assignment(jsTarget, jsSource); |
2813 setupBlock.statements.add(new js.ExpressionStatement(assignment)); | 2825 setupBlock.statements.add(new js.ExpressionStatement(assignment)); |
2814 } | 2826 } |
2815 i++; | 2827 }); |
2816 } | |
2817 setupBlock.statements.add(new js.Break(null)); | 2828 setupBlock.statements.add(new js.Break(null)); |
2818 js.Case setupClause = | 2829 js.Case setupClause = |
2819 new js.Case(new js.LiteralNumber('${node.state}'), setupBlock); | 2830 new js.Case(new js.LiteralNumber('${node.state}'), setupBlock); |
2820 (setup as js.Switch).cases.add(setupClause); | 2831 (setup as js.Switch).cases.add(setupClause); |
2821 } | 2832 } |
2822 | 2833 |
2823 void startBailoutCase(List<HBailoutTarget> bailouts1, | 2834 void startBailoutCase(List<HBailoutTarget> bailouts1, |
2824 [List<HBailoutTarget> bailouts2 = const []]) { | 2835 [List<HBailoutTarget> bailouts2 = const []]) { |
2825 if (!defaultClauseUsedInBailoutStack.last() && | 2836 if (!defaultClauseUsedInBailoutStack.last() && |
2826 bailouts1.length + bailouts2.length >= 2) { | 2837 bailouts1.length + bailouts2.length >= 2) { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2990 if (leftType.canBeNull() && rightType.canBeNull()) { | 3001 if (leftType.canBeNull() && rightType.canBeNull()) { |
2991 if (left.isConstantNull() || right.isConstantNull() || | 3002 if (left.isConstantNull() || right.isConstantNull() || |
2992 (leftType.isPrimitive() && leftType == rightType)) { | 3003 (leftType.isPrimitive() && leftType == rightType)) { |
2993 return '=='; | 3004 return '=='; |
2994 } | 3005 } |
2995 return null; | 3006 return null; |
2996 } else { | 3007 } else { |
2997 return '==='; | 3008 return '==='; |
2998 } | 3009 } |
2999 } | 3010 } |
OLD | NEW |