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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 } | 1330 } |
1331 } | 1331 } |
1332 | 1332 |
1333 return true; | 1333 return true; |
1334 } | 1334 } |
1335 | 1335 |
1336 bool reductiveHeuristic() { | 1336 bool reductiveHeuristic() { |
1337 // The call is on a path which is executed rarely, so inline only if it | 1337 // The call is on a path which is executed rarely, so inline only if it |
1338 // does not make the program larger. | 1338 // does not make the program larger. |
1339 if (isCalledOnce(element)) { | 1339 if (isCalledOnce(element)) { |
1340 return InlineWeeder.canBeInlined(function.node, -1, false); | 1340 return InlineWeeder.canBeInlined(function, -1, false); |
1341 } | 1341 } |
1342 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable | 1342 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable |
1343 // case we miss my doing nothing is inlining very simple constructors | 1343 // case we miss my doing nothing is inlining very simple constructors |
1344 // where all fields are initialized with values from the arguments at this | 1344 // where all fields are initialized with values from the arguments at this |
1345 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but | 1345 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but |
1346 // that usually means the factory constructor is left unused and not | 1346 // that usually means the factory constructor is left unused and not |
1347 // emitted. | 1347 // emitted. |
1348 return false; | 1348 return false; |
1349 } | 1349 } |
1350 | 1350 |
1351 bool heuristicSayGoodToGo() { | 1351 bool heuristicSayGoodToGo() { |
1352 // Don't inline recursively | 1352 // Don't inline recursively |
1353 if (inliningStack.any((entry) => entry.function == function)) { | 1353 if (inliningStack.any((entry) => entry.function == function)) { |
1354 return false; | 1354 return false; |
1355 } | 1355 } |
1356 | 1356 |
1357 if (element.isSynthesized) return true; | 1357 if (element.isSynthesized) return true; |
1358 | 1358 |
1359 if (inExpressionOfThrow || inLazyInitializerExpression) { | 1359 if (inExpressionOfThrow || inLazyInitializerExpression) { |
1360 return reductiveHeuristic(); | 1360 return reductiveHeuristic(); |
1361 } | 1361 } |
1362 | 1362 |
1363 if (cachedCanBeInlined == true) return cachedCanBeInlined; | 1363 if (cachedCanBeInlined == true) return cachedCanBeInlined; |
1364 | 1364 |
1365 if (backend.functionsToAlwaysInline.contains(function)) { | 1365 if (backend.functionsToAlwaysInline.contains(function)) { |
1366 // Inline this function regardless of it's size. | 1366 // Inline this function regardless of it's size. |
1367 assert(InlineWeeder.canBeInlined(function.node, -1, false, | 1367 assert(InlineWeeder.canBeInlined(function, -1, false, |
1368 allowLoops: true)); | 1368 allowLoops: true)); |
1369 return true; | 1369 return true; |
1370 } | 1370 } |
1371 | 1371 |
1372 int numParameters = function.functionSignature.parameterCount; | 1372 int numParameters = function.functionSignature.parameterCount; |
1373 int maxInliningNodes; | 1373 int maxInliningNodes; |
1374 bool useMaxInliningNodes = true; | 1374 bool useMaxInliningNodes = true; |
1375 if (insideLoop) { | 1375 if (insideLoop) { |
1376 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 1376 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
1377 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 1377 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
1378 } else { | 1378 } else { |
1379 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 1379 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
1380 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 1380 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
1381 } | 1381 } |
1382 | 1382 |
1383 // If a method is called only once, and all the methods in the | 1383 // If a method is called only once, and all the methods in the |
1384 // inlining stack are called only once as well, we know we will | 1384 // inlining stack are called only once as well, we know we will |
1385 // save on output size by inlining this method. | 1385 // save on output size by inlining this method. |
1386 if (isCalledOnce(element)) { | 1386 if (isCalledOnce(element)) { |
1387 useMaxInliningNodes = false; | 1387 useMaxInliningNodes = false; |
1388 } | 1388 } |
1389 bool canInline; | 1389 bool canInline; |
1390 ast.FunctionExpression functionNode = function.node; | |
1391 canInline = InlineWeeder.canBeInlined( | 1390 canInline = InlineWeeder.canBeInlined( |
1392 functionNode, maxInliningNodes, useMaxInliningNodes); | 1391 function, maxInliningNodes, useMaxInliningNodes); |
1393 if (canInline) { | 1392 if (canInline) { |
1394 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); | 1393 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
1395 } else { | 1394 } else { |
1396 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1395 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
1397 } | 1396 } |
1398 return canInline; | 1397 return canInline; |
1399 } | 1398 } |
1400 | 1399 |
1401 void doInlining() { | 1400 void doInlining() { |
1402 // Add an explicit null check on the receiver before doing the | 1401 // Add an explicit null check on the receiver before doing the |
(...skipping 5041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6444 bool tooDifficult = false; | 6443 bool tooDifficult = false; |
6445 int nodeCount = 0; | 6444 int nodeCount = 0; |
6446 final int maxInliningNodes; | 6445 final int maxInliningNodes; |
6447 final bool useMaxInliningNodes; | 6446 final bool useMaxInliningNodes; |
6448 final bool allowLoops; | 6447 final bool allowLoops; |
6449 | 6448 |
6450 InlineWeeder(this.maxInliningNodes, | 6449 InlineWeeder(this.maxInliningNodes, |
6451 this.useMaxInliningNodes, | 6450 this.useMaxInliningNodes, |
6452 this.allowLoops); | 6451 this.allowLoops); |
6453 | 6452 |
6454 static bool canBeInlined(ast.FunctionExpression functionExpression, | 6453 static bool canBeInlined(FunctionElement function, |
6455 int maxInliningNodes, | 6454 int maxInliningNodes, |
6456 bool useMaxInliningNodes, | 6455 bool useMaxInliningNodes, |
6457 {bool allowLoops: false}) { | 6456 {bool allowLoops: false}) { |
6458 InlineWeeder weeder = | 6457 InlineWeeder weeder = |
6459 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); | 6458 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); |
| 6459 ast.FunctionExpression functionExpression = function.node; |
6460 weeder.visit(functionExpression.initializers); | 6460 weeder.visit(functionExpression.initializers); |
6461 weeder.visit(functionExpression.body); | 6461 weeder.visit(functionExpression.body); |
6462 weeder.visit(functionExpression.asyncModifier); | 6462 weeder.visit(functionExpression.asyncModifier); |
6463 return !weeder.tooDifficult; | 6463 return !weeder.tooDifficult; |
6464 } | 6464 } |
6465 | 6465 |
6466 bool registerNode() { | 6466 bool registerNode() { |
6467 if (!useMaxInliningNodes) return true; | 6467 if (!useMaxInliningNodes) return true; |
6468 if (nodeCount++ > maxInliningNodes) { | 6468 if (nodeCount++ > maxInliningNodes) { |
6469 tooDifficult = true; | 6469 tooDifficult = true; |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6915 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6915 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6916 unaliased.accept(this, builder); | 6916 unaliased.accept(this, builder); |
6917 } | 6917 } |
6918 | 6918 |
6919 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6919 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6920 JavaScriptBackend backend = builder.compiler.backend; | 6920 JavaScriptBackend backend = builder.compiler.backend; |
6921 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6921 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6922 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6922 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6923 } | 6923 } |
6924 } | 6924 } |
OLD | NEW |