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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
6 String get name(); | 6 String get name(); |
7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
8 } | 8 } |
9 | 9 |
10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1168 | 1168 |
1169 void visitGraph(HGraph visitee) { | 1169 void visitGraph(HGraph visitee) { |
1170 graph = visitee; | 1170 graph = visitee; |
1171 visitDominatorTree(visitee); | 1171 visitDominatorTree(visitee); |
1172 } | 1172 } |
1173 | 1173 |
1174 void visitFieldGet(HFieldGet node) { | 1174 void visitFieldGet(HFieldGet node) { |
1175 if (!node.element.enclosingElement.isClass()) return; | 1175 if (!node.element.enclosingElement.isClass()) return; |
1176 Element field = node.element; | 1176 Element field = node.element; |
1177 HType type = backend.optimisticFieldTypeAfterConstruction(field); | 1177 HType type = backend.optimisticFieldTypeAfterConstruction(field); |
1178 switch (compiler.phase) { | 1178 if (!type.isConflicting() && !type.isUnknown()) { |
Mads Ager (google)
2012/07/11 10:24:34
I think we can relax this check but I will look in
| |
1179 case Compiler.PHASE_COMPILING: | 1179 switch (compiler.phase) { |
1180 if (!type.isConflicting()) { | 1180 case Compiler.PHASE_COMPILING: |
1181 compiler.enqueuer.codegen.registerRecompilationCandidate( | 1181 compiler.enqueuer.codegen.registerRecompilationCandidate( |
1182 work.element); | 1182 work.element); |
1183 } | 1183 break; |
1184 break; | 1184 case Compiler.PHASE_RECOMPILING: |
1185 case Compiler.PHASE_RECOMPILING: | |
1186 if (!type.isConflicting() && !type.isUnknown()) { | |
1187 // Check if optimistic type is based on a setter in the constructor | 1185 // Check if optimistic type is based on a setter in the constructor |
1188 // body. | 1186 // body. |
1189 if (backend.hasConstructorBodyFieldSetter(field)) { | 1187 if (backend.hasConstructorBodyFieldSetter(field)) { |
1190 // There is at least one field setter from the constructor. | 1188 // There is at least one field setter from the constructor. |
1191 if (!compiler.codegenWorld.hasInvokedSetter(field, compiler)) { | 1189 if (!compiler.codegenWorld.hasInvokedSetter(field, compiler)) { |
1192 node.guaranteedType = | 1190 node.guaranteedType = |
1193 type.union(backend.fieldSettersTypeSoFar(node.element)); | 1191 type.union(backend.fieldSettersTypeSoFar(node.element)); |
1194 } else { | 1192 } else { |
1195 node.propagatedType = | 1193 node.propagatedType = |
1196 type.union(backend.fieldSettersTypeSoFar(node.element)); | 1194 type.union(backend.fieldSettersTypeSoFar(node.element)); |
1197 } | 1195 } |
1198 } else { | 1196 } else { |
1199 // Optimistic type is based on field initializer list. | 1197 // Optimistic type is based on field initializer list. |
1200 if (!compiler.codegenWorld.hasFieldSetter(field, compiler) && | 1198 if (!compiler.codegenWorld.hasFieldSetter(field, compiler) && |
1201 !compiler.codegenWorld.hasInvokedSetter(field, compiler)) { | 1199 !compiler.codegenWorld.hasInvokedSetter(field, compiler)) { |
1202 node.guaranteedType = type; | 1200 node.guaranteedType = type; |
1203 } else { | 1201 } else { |
1204 node.propagatedType = type; | 1202 node.propagatedType = type; |
1205 } | 1203 } |
1206 } | 1204 } |
1207 } | 1205 break; |
1208 break; | 1206 } |
1209 } | 1207 } |
1210 } | 1208 } |
1211 | 1209 |
1212 HInstruction visitEquals(HEquals node) { | 1210 HInstruction visitEquals(HEquals node) { |
1213 // Determine if one of the operands is an HFieldGet. | 1211 // Determine if one of the operands is an HFieldGet. |
1214 HFieldGet field; | 1212 HFieldGet field; |
1215 HInstruction other; | 1213 HInstruction other; |
1216 if (node.left is HFieldGet) { | 1214 if (node.left is HFieldGet) { |
1217 field = node.left; | 1215 field = node.left; |
1218 other = node.right; | 1216 other = node.right; |
1219 } else if (node.right is HFieldGet) { | 1217 } else if (node.right is HFieldGet) { |
1220 field = node.right; | 1218 field = node.right; |
1221 other = node.left; | 1219 other = node.left; |
1222 } | 1220 } |
1223 // Try to optimize the case where a field which is known to always be an | 1221 // Try to optimize the case where a field which is known to always be an |
1224 // integer is compared with a constant integer literal. | 1222 // integer is compared with a constant integer literal. |
1225 if (other != null && | 1223 if (other != null && |
1226 other is HConstant && | 1224 other.isConstantInteger() && |
1227 other.isInteger() && | |
1228 field.element != null && | 1225 field.element != null && |
1229 field.element.enclosingElement.isClass()) { | 1226 field.element.enclosingElement.isClass()) { |
1230 // Calculate the field type from the information available. | 1227 // Calculate the field type from the information available. |
1231 HType type = | 1228 HType type = |
1232 backend.fieldSettersTypeSoFar(field.element).union( | 1229 backend.fieldSettersTypeSoFar(field.element).union( |
1233 backend.typeFromInitializersSoFar(field.element)); | 1230 backend.typeFromInitializersSoFar(field.element)); |
1234 if (!type.isConflicting()) { | 1231 if (!type.isUnknown()) { |
1235 switch (compiler.phase) { | 1232 switch (compiler.phase) { |
1236 case Compiler.PHASE_COMPILING: | 1233 case Compiler.PHASE_COMPILING: |
1237 compiler.enqueuer.codegen.registerRecompilationCandidate( | 1234 compiler.enqueuer.codegen.registerRecompilationCandidate( |
1238 work.element); | 1235 work.element); |
1239 break; | 1236 break; |
1240 case Compiler.PHASE_RECOMPILING: | 1237 case Compiler.PHASE_RECOMPILING: |
1241 if (compiler.codegenWorld.hasInvokedSetter(field.element, | 1238 if (compiler.codegenWorld.hasInvokedSetter(field.element, |
1242 compiler)) { | 1239 compiler)) { |
1243 // If there are invoked setters we don't know for sure that the | 1240 // If there are invoked setters we don't know for sure that the |
1244 // field will hold the calculated, but the fact that the class | 1241 // field will hold the calculated, but the fact that the class |
(...skipping 22 matching lines...) Expand all Loading... | |
1267 if (node.left is HFieldGet) { | 1264 if (node.left is HFieldGet) { |
1268 field = node.left; | 1265 field = node.left; |
1269 other = node.right; | 1266 other = node.right; |
1270 } else if (node.right is HFieldGet) { | 1267 } else if (node.right is HFieldGet) { |
1271 field = node.right; | 1268 field = node.right; |
1272 other = node.left; | 1269 other = node.left; |
1273 } | 1270 } |
1274 // Check that the other operand is a number and that we have type | 1271 // Check that the other operand is a number and that we have type |
1275 // information for the field get. | 1272 // information for the field get. |
1276 if (other != null && | 1273 if (other != null && |
1277 other is HConstant && | 1274 other.isConstantNumber() && |
1278 other.isNumber() && | |
1279 field.element != null && | 1275 field.element != null && |
1280 field.element.enclosingElement.isClass()) { | 1276 field.element.enclosingElement.isClass()) { |
1281 // If we have type information for the field and it contains | 1277 // If we have type information for the field and it contains |
1282 // NUMBER, we mark for recompilation. | 1278 // NUMBER, we mark for recompilation. |
1283 Element fieldElement = field.element; | 1279 Element fieldElement = field.element; |
1284 HType fieldSettersType = backend.fieldSettersTypeSoFar(fieldElement); | 1280 HType fieldSettersType = backend.fieldSettersTypeSoFar(fieldElement); |
1285 HType initializersType = backend.typeFromInitializersSoFar(fieldElement); | 1281 HType initializersType = backend.typeFromInitializersSoFar(fieldElement); |
1286 HType fieldType = fieldSettersType.union(initializersType); | 1282 HType fieldType = fieldSettersType.union(initializersType); |
1287 HType type = HType.NUMBER.union(fieldType); | 1283 HType type = HType.NUMBER.union(fieldType); |
1288 if (!type.isConflicting()) { | 1284 if (type == HType.NUMBER) { |
1289 switch (compiler.phase) { | 1285 switch (compiler.phase) { |
1290 case Compiler.PHASE_COMPILING: | 1286 case Compiler.PHASE_COMPILING: |
1291 compiler.enqueuer.codegen.registerRecompilationCandidate( | 1287 compiler.enqueuer.codegen.registerRecompilationCandidate( |
1292 work.element); | 1288 work.element); |
1293 break; | 1289 break; |
1294 case Compiler.PHASE_RECOMPILING: | 1290 case Compiler.PHASE_RECOMPILING: |
1295 if (compiler.codegenWorld.hasInvokedSetter(fieldElement, | 1291 if (compiler.codegenWorld.hasInvokedSetter(fieldElement, |
1296 compiler)) { | 1292 compiler)) { |
1297 // If there are invoked setters we don't know for sure | 1293 // If there are invoked setters we don't know for sure |
1298 // that the field will hold a value of the calculated | 1294 // that the field will hold a value of the calculated |
1299 // type, but the fact that the class itself sticks to | 1295 // type, but the fact that the class itself sticks to |
1300 // this type for the field is still a strong signal | 1296 // this type for the field is still a strong signal |
1301 // indicating the expected type of the field. | 1297 // indicating the expected type of the field. |
1302 field.propagatedType = type; | 1298 field.propagatedType = type; |
1303 graph.highTypeLikelyhood = true; | 1299 graph.highTypeLikelyhood = true; |
1304 } else { | 1300 } else { |
1305 // If there are no invoked setters we know the type of | 1301 // If there are no invoked setters we know the type of |
1306 // this field for sure. | 1302 // this field for sure. |
1307 field.guaranteedType = type; | 1303 field.guaranteedType = type; |
1308 } | 1304 } |
1309 break; | 1305 break; |
1310 default: | 1306 default: |
1311 assert(false); | 1307 assert(false); |
1312 break; | 1308 break; |
1313 } | 1309 } |
1314 } | 1310 } |
1315 } | 1311 } |
1316 } | 1312 } |
1317 } | 1313 } |
OLD | NEW |