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 abstract class OptimizationPhase { | 5 abstract class 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 23 matching lines...) Expand all Loading... | |
| 34 List<OptimizationPhase> phases = <OptimizationPhase>[ | 34 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 35 // Run trivial constant folding first to optimize | 35 // Run trivial constant folding first to optimize |
| 36 // some patterns useful for type conversion. | 36 // some patterns useful for type conversion. |
| 37 new SsaConstantFolder(constantSystem, backend, work, types), | 37 new SsaConstantFolder(constantSystem, backend, work, types), |
| 38 new SsaTypeConversionInserter(compiler), | 38 new SsaTypeConversionInserter(compiler), |
| 39 new SsaTypePropagator(compiler, types), | 39 new SsaTypePropagator(compiler, types), |
| 40 new SsaCheckInserter(backend, types, context.boundsChecked), | 40 new SsaCheckInserter(backend, types, context.boundsChecked), |
| 41 new SsaConstantFolder(constantSystem, backend, work, types), | 41 new SsaConstantFolder(constantSystem, backend, work, types), |
| 42 new SsaRedundantPhiEliminator(), | 42 new SsaRedundantPhiEliminator(), |
| 43 new SsaDeadPhiEliminator(), | 43 new SsaDeadPhiEliminator(), |
| 44 new SsaConstantFolder(constantSystem, backend, work, types), | |
| 44 new SsaGlobalValueNumberer(compiler, types), | 45 new SsaGlobalValueNumberer(compiler, types), |
| 45 new SsaCodeMotion(), | 46 new SsaCodeMotion(), |
| 47 new SsaValueRangeAnalyzer(constantSystem, types, work), | |
| 46 // Previous optimizations may have generated new | 48 // Previous optimizations may have generated new |
| 47 // opportunities for constant folding. | 49 // opportunities for constant folding. |
| 48 new SsaConstantFolder(constantSystem, backend, work, types), | 50 new SsaConstantFolder(constantSystem, backend, work, types), |
| 49 new SsaDeadCodeEliminator(types), | 51 new SsaDeadCodeEliminator(types), |
| 50 new SsaRegisterRecompilationCandidates(backend, work, types)]; | 52 new SsaRegisterRecompilationCandidates(backend, work, types)]; |
| 51 runPhases(graph, phases); | 53 runPhases(graph, phases); |
| 52 }); | 54 }); |
| 53 } | 55 } |
| 54 | 56 |
| 55 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { | 57 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 if (operand is HConstant) { | 192 if (operand is HConstant) { |
| 191 UnaryOperation operation = node.operation(constantSystem); | 193 UnaryOperation operation = node.operation(constantSystem); |
| 192 HConstant receiver = operand; | 194 HConstant receiver = operand; |
| 193 Constant folded = operation.fold(receiver.constant); | 195 Constant folded = operation.fold(receiver.constant); |
| 194 if (folded !== null) return graph.addConstant(folded); | 196 if (folded !== null) return graph.addConstant(folded); |
| 195 } | 197 } |
| 196 return node; | 198 return node; |
| 197 } | 199 } |
| 198 | 200 |
| 199 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { | 201 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { |
| 202 // Try to recognize [:new List(int):]. | |
|
Søren Gjesse
2012/09/26 14:00:15
Isn't it "Try to recognize length interceptor with
ngeoffray
2012/09/27 13:22:02
Yes, done.
| |
| 203 if (node.isLengthGetter() && node.inputs[1] is HInvokeStatic) { | |
| 204 HInvokeStatic call = node.inputs[1]; | |
| 205 Element element = call.inputs[0].element; | |
| 206 if (element.isConstructor() && | |
| 207 element.enclosingElement == compiler.listClass.defaultClass.element) { | |
| 208 if (call.inputs.length == 2 && call.inputs[1].isInteger(types)) { | |
| 209 return call.inputs[1]; | |
| 210 } | |
| 211 } | |
| 212 } | |
| 200 HInstruction input = node.inputs[1]; | 213 HInstruction input = node.inputs[1]; |
| 201 if (node.isLengthGetter()) { | 214 if (node.isLengthGetter()) { |
| 202 if (input.isConstantString()) { | 215 if (input.isConstantString()) { |
| 203 HConstant constantInput = input; | 216 HConstant constantInput = input; |
| 204 StringConstant constant = constantInput.constant; | 217 StringConstant constant = constantInput.constant; |
| 205 return graph.addConstantInt(constant.length, constantSystem); | 218 return graph.addConstantInt(constant.length, constantSystem); |
| 206 } else if (input.isConstantList()) { | 219 } else if (input.isConstantList()) { |
| 207 HConstant constantInput = input; | 220 HConstant constantInput = input; |
| 208 ListConstant constant = constantInput.constant; | 221 ListConstant constant = constantInput.constant; |
| 209 return graph.addConstantInt(constant.length, constantSystem); | 222 return graph.addConstantInt(constant.length, constantSystem); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 263 HInvokeDynamicMethod result = new HInvokeDynamicMethod( | 276 HInvokeDynamicMethod result = new HInvokeDynamicMethod( |
| 264 selector, | 277 selector, |
| 265 node.inputs.getRange(1, node.inputs.length - 1)); | 278 node.inputs.getRange(1, node.inputs.length - 1)); |
| 266 if (type.isExact()) { | 279 if (type.isExact()) { |
| 267 HBoundedType concrete = type; | 280 HBoundedType concrete = type; |
| 268 result.element = concrete.lookupMember(selector.name); | 281 result.element = concrete.lookupMember(selector.name); |
| 269 } | 282 } |
| 270 return result; | 283 return result; |
| 271 } | 284 } |
| 272 | 285 |
| 273 HInstruction visitBoundsCheck(HBoundsCheck node) { | |
| 274 int tryGetIntConstantValue(HInstruction instruction, String errorMessage) { | |
| 275 // Tests whether an [HInstruction] is a constant. | |
| 276 // If it is a constant, and not an int constant, it fails. | |
| 277 // If it's an int constant it returns the value. | |
| 278 // Otherwise it's not a constant, and this function returns null. | |
| 279 if (!instruction.isConstant()) return null; | |
| 280 HConstant constantInstruction = instruction; | |
| 281 Constant constant = constantInstruction.constant; | |
| 282 if (!constant.isInt()) { | |
| 283 compiler.internalError(errorMessage, instruction: instruction); | |
| 284 } | |
| 285 IntConstant intConstant = constant; | |
| 286 return intConstant.value; | |
| 287 } | |
| 288 int index = tryGetIntConstantValue(node.index, | |
| 289 'String or List index not a number'); | |
| 290 if (index !== null) { | |
| 291 if (index < 0) { | |
| 292 node.staticChecks = HBoundsCheck.ALWAYS_FALSE; | |
| 293 return node; | |
| 294 } | |
| 295 int length = tryGetIntConstantValue(node.length, | |
| 296 'String or List length not a number'); | |
| 297 if (length !== null) { | |
| 298 if (index >= length) { | |
| 299 node.staticChecks = HBoundsCheck.ALWAYS_FALSE; | |
| 300 } else { | |
| 301 // Could have set the staticChecks to ALWAYS_TRUE instead. | |
| 302 return node.index; | |
| 303 } | |
| 304 return node; | |
| 305 } | |
| 306 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; | |
| 307 } | |
| 308 return node; | |
| 309 } | |
| 310 | |
| 311 HInstruction visitIntegerCheck(HIntegerCheck node) { | 286 HInstruction visitIntegerCheck(HIntegerCheck node) { |
| 312 HInstruction value = node.value; | 287 HInstruction value = node.value; |
| 313 if (value.isInteger(types)) return value; | 288 if (value.isInteger(types)) return value; |
| 314 if (value.isConstant()) { | 289 if (value.isConstant()) { |
| 315 HConstant constantInstruction = value; | 290 HConstant constantInstruction = value; |
| 316 assert(!constantInstruction.constant.isInt()); | 291 assert(!constantInstruction.constant.isInt()); |
| 317 if (!constantSystem.isInt(constantInstruction.constant)) { | 292 if (!constantSystem.isInt(constantInstruction.constant)) { |
| 318 // -0.0 is a double but will pass the runtime integer check. | 293 // -0.0 is a double but will pass the runtime integer check. |
| 319 node.alwaysFalse = true; | 294 node.alwaysFalse = true; |
| 320 } | 295 } |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 | 696 |
| 722 void visitIndex(HIndex node) { | 697 void visitIndex(HIndex node) { |
| 723 if (!node.receiver.isIndexablePrimitive(types)) return; | 698 if (!node.receiver.isIndexablePrimitive(types)) return; |
| 724 if (boundsChecked.contains(node)) return; | 699 if (boundsChecked.contains(node)) return; |
| 725 HInstruction index = node.index; | 700 HInstruction index = node.index; |
| 726 if (!node.index.isInteger(types)) { | 701 if (!node.index.isInteger(types)) { |
| 727 index = insertIntegerCheck(node, index); | 702 index = insertIntegerCheck(node, index); |
| 728 } | 703 } |
| 729 index = insertBoundsCheck(node, node.receiver, index); | 704 index = insertBoundsCheck(node, node.receiver, index); |
| 730 node.changeUse(node.index, index); | 705 node.changeUse(node.index, index); |
| 706 assert(node.isBuiltin(types)); | |
| 731 } | 707 } |
| 732 | 708 |
| 733 void visitIndexAssign(HIndexAssign node) { | 709 void visitIndexAssign(HIndexAssign node) { |
| 734 if (!node.receiver.isMutableArray(types)) return; | 710 if (!node.receiver.isMutableArray(types)) return; |
| 735 if (boundsChecked.contains(node)) return; | 711 if (boundsChecked.contains(node)) return; |
| 736 HInstruction index = node.index; | 712 HInstruction index = node.index; |
| 737 if (!node.index.isInteger(types)) { | 713 if (!node.index.isInteger(types)) { |
| 738 index = insertIntegerCheck(node, index); | 714 index = insertIntegerCheck(node, index); |
| 739 } | 715 } |
| 740 index = insertBoundsCheck(node, node.receiver, index); | 716 index = insertBoundsCheck(node, node.receiver, index); |
| 741 node.changeUse(node.index, index); | 717 node.changeUse(node.index, index); |
| 718 assert(node.isBuiltin(types)); | |
| 742 } | 719 } |
| 743 | 720 |
| 744 void visitInvokeInterceptor(HInvokeInterceptor node) { | 721 void visitInvokeInterceptor(HInvokeInterceptor node) { |
| 745 if (!node.isPopCall(types)) return; | 722 if (!node.isPopCall(types)) return; |
| 746 if (boundsChecked.contains(node)) return; | 723 if (boundsChecked.contains(node)) return; |
| 747 HInstruction receiver = node.inputs[1]; | 724 HInstruction receiver = node.inputs[1]; |
| 748 insertBoundsCheck(node, receiver, graph.addConstantInt(0, constantSystem)); | 725 insertBoundsCheck(node, receiver, graph.addConstantInt(0, constantSystem)); |
| 749 } | 726 } |
| 750 } | 727 } |
| 751 | 728 |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 // this type for the field is still a strong signal | 1346 // this type for the field is still a strong signal |
| 1370 // indicating the expected type of the field. | 1347 // indicating the expected type of the field. |
| 1371 types[field] = type; | 1348 types[field] = type; |
| 1372 } else { | 1349 } else { |
| 1373 // If there are no invoked setters we know the type of | 1350 // If there are no invoked setters we know the type of |
| 1374 // this field for sure. | 1351 // this field for sure. |
| 1375 field.guaranteedType = type; | 1352 field.guaranteedType = type; |
| 1376 } | 1353 } |
| 1377 } | 1354 } |
| 1378 } | 1355 } |
| OLD | NEW |