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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 /// A synthetic local variable only used with the SSA graph. | 7 /// A synthetic local variable only used with the SSA graph. |
8 /// | 8 /// |
9 /// For instance used for holding return value of function or the exception of a | 9 /// For instance used for holding return value of function or the exception of a |
10 /// try-catch statement. | 10 /// try-catch statement. |
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 if (inliningStack.any((entry) => entry.function == function)) { | 1247 if (inliningStack.any((entry) => entry.function == function)) { |
1248 return false; | 1248 return false; |
1249 } | 1249 } |
1250 | 1250 |
1251 if (inExpressionOfThrow) return false; | 1251 if (inExpressionOfThrow) return false; |
1252 | 1252 |
1253 if (element.isSynthesized) return true; | 1253 if (element.isSynthesized) return true; |
1254 | 1254 |
1255 if (cachedCanBeInlined == true) return cachedCanBeInlined; | 1255 if (cachedCanBeInlined == true) return cachedCanBeInlined; |
1256 | 1256 |
| 1257 if (backend.functionsToAlwaysInline.contains(function)) { |
| 1258 // Inline this function regardless of it's size. |
| 1259 assert(InlineWeeder.canBeInlined(function.node, -1, false, |
| 1260 allowLoops: true)); |
| 1261 return true; |
| 1262 } |
| 1263 |
1257 int numParameters = function.functionSignature.parameterCount; | 1264 int numParameters = function.functionSignature.parameterCount; |
1258 int maxInliningNodes; | 1265 int maxInliningNodes; |
1259 bool useMaxInliningNodes = true; | 1266 bool useMaxInliningNodes = true; |
1260 if (insideLoop) { | 1267 if (insideLoop) { |
1261 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 1268 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
1262 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 1269 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
1263 } else { | 1270 } else { |
1264 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 1271 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
1265 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 1272 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
1266 } | 1273 } |
(...skipping 4720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5987 new HStringify(expression, node, builder.backend.stringType); | 5994 new HStringify(expression, node, builder.backend.stringType); |
5988 builder.add(instruction); | 5995 builder.add(instruction); |
5989 return instruction; | 5996 return instruction; |
5990 } | 5997 } |
5991 } | 5998 } |
5992 | 5999 |
5993 /** | 6000 /** |
5994 * This class visits the method that is a candidate for inlining and | 6001 * This class visits the method that is a candidate for inlining and |
5995 * finds whether it is too difficult to inline. | 6002 * finds whether it is too difficult to inline. |
5996 */ | 6003 */ |
| 6004 // TODO(karlklose): refactor to make it possible to distinguish between |
| 6005 // implementation restrictions (for example, we *can't* inline multiple returns) |
| 6006 // and heuristics (we *shouldn't* inline large functions). |
5997 class InlineWeeder extends ast.Visitor { | 6007 class InlineWeeder extends ast.Visitor { |
5998 // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP* | 6008 // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP* |
5999 static const INLINING_NODES_OUTSIDE_LOOP = 18; | 6009 static const INLINING_NODES_OUTSIDE_LOOP = 18; |
6000 static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3; | 6010 static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3; |
6001 static const INLINING_NODES_INSIDE_LOOP = 42; | 6011 static const INLINING_NODES_INSIDE_LOOP = 42; |
6002 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4; | 6012 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4; |
6003 | 6013 |
6004 bool seenReturn = false; | 6014 bool seenReturn = false; |
6005 bool tooDifficult = false; | 6015 bool tooDifficult = false; |
6006 int nodeCount = 0; | 6016 int nodeCount = 0; |
6007 final int maxInliningNodes; | 6017 final int maxInliningNodes; |
6008 final bool useMaxInliningNodes; | 6018 final bool useMaxInliningNodes; |
| 6019 final bool allowLoops; |
6009 | 6020 |
6010 InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes); | 6021 InlineWeeder(this.maxInliningNodes, |
| 6022 this.useMaxInliningNodes, |
| 6023 this.allowLoops); |
6011 | 6024 |
6012 static bool canBeInlined(ast.FunctionExpression functionExpression, | 6025 static bool canBeInlined(ast.FunctionExpression functionExpression, |
6013 int maxInliningNodes, | 6026 int maxInliningNodes, |
6014 bool useMaxInliningNodes) { | 6027 bool useMaxInliningNodes, |
| 6028 {bool allowLoops: false}) { |
6015 InlineWeeder weeder = | 6029 InlineWeeder weeder = |
6016 new InlineWeeder(maxInliningNodes, useMaxInliningNodes); | 6030 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); |
6017 weeder.visit(functionExpression.initializers); | 6031 weeder.visit(functionExpression.initializers); |
6018 weeder.visit(functionExpression.body); | 6032 weeder.visit(functionExpression.body); |
6019 return !weeder.tooDifficult; | 6033 return !weeder.tooDifficult; |
6020 } | 6034 } |
6021 | 6035 |
6022 bool registerNode() { | 6036 bool registerNode() { |
6023 if (!useMaxInliningNodes) return true; | 6037 if (!useMaxInliningNodes) return true; |
6024 if (nodeCount++ > maxInliningNodes) { | 6038 if (nodeCount++ > maxInliningNodes) { |
6025 tooDifficult = true; | 6039 tooDifficult = true; |
6026 return false; | 6040 return false; |
(...skipping 27 matching lines...) Expand all Loading... |
6054 | 6068 |
6055 void visitSend(ast.Send node) { | 6069 void visitSend(ast.Send node) { |
6056 if (!registerNode()) return; | 6070 if (!registerNode()) return; |
6057 node.visitChildren(this); | 6071 node.visitChildren(this); |
6058 } | 6072 } |
6059 | 6073 |
6060 visitLoop(ast.Node node) { | 6074 visitLoop(ast.Node node) { |
6061 // It's actually not difficult to inline a method with a loop, but | 6075 // It's actually not difficult to inline a method with a loop, but |
6062 // our measurements show that it's currently better to not inline a | 6076 // our measurements show that it's currently better to not inline a |
6063 // method that contains a loop. | 6077 // method that contains a loop. |
6064 tooDifficult = true; | 6078 if (!allowLoops) tooDifficult = true; |
6065 } | 6079 } |
6066 | 6080 |
6067 void visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 6081 void visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
6068 if (!registerNode()) return; | 6082 if (!registerNode()) return; |
6069 tooDifficult = true; | 6083 tooDifficult = true; |
6070 } | 6084 } |
6071 | 6085 |
6072 void visitRethrow(ast.Rethrow node) { | 6086 void visitRethrow(ast.Rethrow node) { |
6073 if (!registerNode()) return; | 6087 if (!registerNode()) return; |
6074 tooDifficult = true; | 6088 tooDifficult = true; |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6455 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6469 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6456 unaliased.accept(this, builder); | 6470 unaliased.accept(this, builder); |
6457 } | 6471 } |
6458 | 6472 |
6459 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6473 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6460 JavaScriptBackend backend = builder.compiler.backend; | 6474 JavaScriptBackend backend = builder.compiler.backend; |
6461 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6475 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6462 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6476 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
6463 } | 6477 } |
6464 } | 6478 } |
OLD | NEW |