| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library cps_ir.optimization.inline; | 5 library cps_ir.optimization.inline; |
| 6 | 6 |
| 7 import 'cps_fragment.dart'; | 7 import 'cps_fragment.dart'; |
| 8 import 'cps_ir_builder.dart' show ThisParameterLocal; | 8 import 'cps_ir_builder.dart' show ThisParameterLocal; |
| 9 import 'cps_ir_nodes.dart'; | 9 import 'cps_ir_nodes.dart'; |
| 10 import 'optimizers.dart'; | 10 import 'optimizers.dart'; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 final List<StackEntry> stack = <StackEntry>[]; | 159 final List<StackEntry> stack = <StackEntry>[]; |
| 160 | 160 |
| 161 Inliner(this.functionCompiler); | 161 Inliner(this.functionCompiler); |
| 162 | 162 |
| 163 bool isCalledOnce(Element element) { | 163 bool isCalledOnce(Element element) { |
| 164 return functionCompiler.compiler.typesTask.typesInferrer.isCalledOnce( | 164 return functionCompiler.compiler.typesTask.typesInferrer.isCalledOnce( |
| 165 element); | 165 element); |
| 166 } | 166 } |
| 167 | 167 |
| 168 void rewrite(FunctionDefinition node, [CallStructure callStructure]) { | 168 void rewrite(FunctionDefinition node, [CallStructure callStructure]) { |
| 169 Element function = node.element; | 169 ExecutableElement function = node.element; |
| 170 | 170 |
| 171 // Inlining in asynchronous or generator functions is disabled. Inlining | 171 // Inlining in asynchronous or generator functions is disabled. Inlining |
| 172 // triggers a bug in the async rewriter. | 172 // triggers a bug in the async rewriter. |
| 173 // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes | 173 // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes |
| 174 // sense. | 174 // sense. |
| 175 if (function is FunctionElement && | 175 if (function is FunctionElement && |
| 176 function.asyncMarker != AsyncMarker.SYNC) { | 176 function.asyncMarker != AsyncMarker.SYNC) { |
| 177 return; | 177 return; |
| 178 } | 178 } |
| 179 | 179 |
| 180 // Do not inline in functions containing try statements. V8 does not |
| 181 // optimize code in such functions, so inlining will move optimizable code |
| 182 // into a context where it cannot be optimized. |
| 183 if (function.resolvedAst.elements.containsTryStatement) { |
| 184 return; |
| 185 } |
| 186 |
| 180 stack.add(new StackEntry(function, callStructure)); | 187 stack.add(new StackEntry(function, callStructure)); |
| 181 new InliningVisitor(this).visit(node); | 188 new InliningVisitor(this).visit(node); |
| 182 assert(stack.last.match(function, callStructure)); | 189 assert(stack.last.match(function, callStructure)); |
| 183 stack.removeLast(); | 190 stack.removeLast(); |
| 184 new ShrinkingReducer().rewrite(node); | 191 new ShrinkingReducer().rewrite(node); |
| 185 } | 192 } |
| 186 } | 193 } |
| 187 | 194 |
| 188 /// Compute an abstract size of an IR function definition. | 195 /// Compute an abstract size of an IR function definition. |
| 189 /// | 196 /// |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 // | 353 // |
| 347 // An optional call structure indicates a dynamic call. Calls that are | 354 // An optional call structure indicates a dynamic call. Calls that are |
| 348 // already resolved statically have a null call structure. | 355 // already resolved statically have a null call structure. |
| 349 // | 356 // |
| 350 // The [Primitive] representing the result of the inlined call is returned | 357 // The [Primitive] representing the result of the inlined call is returned |
| 351 // if the call was inlined, and the inlined function body is available in | 358 // if the call was inlined, and the inlined function body is available in |
| 352 // [_fragment]. If the call was not inlined, null is returned. | 359 // [_fragment]. If the call was not inlined, null is returned. |
| 353 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target, | 360 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target, |
| 354 CallStructure callStructure) { | 361 CallStructure callStructure) { |
| 355 // Quick checks: do not inline or even cache calls to targets without an | 362 // Quick checks: do not inline or even cache calls to targets without an |
| 356 // AST node or targets that are asynchronous or generator functions. | 363 // AST node, targets that are asynchronous or generator functions, or |
| 364 // targets containing a try statement. |
| 357 if (!target.hasNode) return null; | 365 if (!target.hasNode) return null; |
| 358 if (target.asyncMarker != AsyncMarker.SYNC) return null; | 366 if (target.asyncMarker != AsyncMarker.SYNC) return null; |
| 367 // V8 does not optimize functions containing a try statement. Inlining |
| 368 // code containing a try statement will make the optimizable calling code |
| 369 // become unoptimizable. |
| 370 if (target.resolvedAst.elements.containsTryStatement) { |
| 371 return null; |
| 372 } |
| 359 | 373 |
| 360 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; | 374 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; |
| 361 TypeMask abstractReceiver = | 375 TypeMask abstractReceiver = |
| 362 dartReceiver == null ? null : abstractType(dartReceiver); | 376 dartReceiver == null ? null : abstractType(dartReceiver); |
| 363 List<TypeMask> abstractArguments = | 377 List<TypeMask> abstractArguments = |
| 364 invoke.arguments.map(abstractType).toList(); | 378 invoke.arguments.map(abstractType).toList(); |
| 365 var cachedResult = _inliner.cache.get(target, callStructure, | 379 var cachedResult = _inliner.cache.get(target, callStructure, |
| 366 abstractReceiver, | 380 abstractReceiver, |
| 367 abstractArguments); | 381 abstractArguments); |
| 368 | 382 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 // We cannot inline a constructor invocation containing type arguments | 523 // We cannot inline a constructor invocation containing type arguments |
| 510 // because CreateInstance in the body does not know the type arguments. | 524 // because CreateInstance in the body does not know the type arguments. |
| 511 // We would incorrectly instantiate a class like A instead of A<B>. | 525 // We would incorrectly instantiate a class like A instead of A<B>. |
| 512 // TODO(kmillikin): try to fix this. | 526 // TODO(kmillikin): try to fix this. |
| 513 GenericType generic = node.dartType; | 527 GenericType generic = node.dartType; |
| 514 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; | 528 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; |
| 515 } | 529 } |
| 516 return tryInlining(node, node.target, null); | 530 return tryInlining(node, node.target, null); |
| 517 } | 531 } |
| 518 } | 532 } |
| OLD | NEW |