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 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 |