Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1737)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1345413002: dart2js ssa: Inlining heuristics ignore assert() statement size. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sdk/lib/_internal/js_runtime/lib/js_rti.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 final SsaCodeGeneratorTask generator; 8 final SsaCodeGeneratorTask generator;
9 final SsaBuilderTask builder; 9 final SsaBuilderTask builder;
10 final SsaOptimizerTask optimizer; 10 final SsaOptimizerTask optimizer;
(...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 isReachable = false; 1356 isReachable = false;
1357 return false; 1357 return false;
1358 } 1358 }
1359 } 1359 }
1360 1360
1361 return true; 1361 return true;
1362 } 1362 }
1363 1363
1364 bool doesNotContainCode() { 1364 bool doesNotContainCode() {
1365 // A function with size 1 does not contain any code. 1365 // A function with size 1 does not contain any code.
1366 return InlineWeeder.canBeInlined(function, 1, true); 1366 return InlineWeeder.canBeInlined(function, 1, true,
1367 enableUserAssertions: compiler.enableUserAssertions);
1367 } 1368 }
1368 1369
1369 bool reductiveHeuristic() { 1370 bool reductiveHeuristic() {
1370 // The call is on a path which is executed rarely, so inline only if it 1371 // The call is on a path which is executed rarely, so inline only if it
1371 // does not make the program larger. 1372 // does not make the program larger.
1372 if (isCalledOnce(element)) { 1373 if (isCalledOnce(element)) {
1373 return InlineWeeder.canBeInlined(function, -1, false); 1374 return InlineWeeder.canBeInlined(function, -1, false,
1375 enableUserAssertions: compiler.enableUserAssertions);
1374 } 1376 }
1375 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable 1377 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable
1376 // case we miss by doing nothing is inlining very simple constructors 1378 // case we miss by doing nothing is inlining very simple constructors
1377 // where all fields are initialized with values from the arguments at this 1379 // where all fields are initialized with values from the arguments at this
1378 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but 1380 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but
1379 // that usually means the factory constructor is left unused and not 1381 // that usually means the factory constructor is left unused and not
1380 // emitted. 1382 // emitted.
1381 // We at least inline bodies that are empty (and thus have a size of 1). 1383 // We at least inline bodies that are empty (and thus have a size of 1).
1382 return doesNotContainCode(); 1384 return doesNotContainCode();
1383 } 1385 }
(...skipping 17 matching lines...) Expand all
1401 1403
1402 // Do not inline code that is rarely executed unless it reduces size. 1404 // Do not inline code that is rarely executed unless it reduces size.
1403 if (inExpressionOfThrow || inLazyInitializerExpression) { 1405 if (inExpressionOfThrow || inLazyInitializerExpression) {
1404 return reductiveHeuristic(); 1406 return reductiveHeuristic();
1405 } 1407 }
1406 1408
1407 if (cachedCanBeInlined == true) { 1409 if (cachedCanBeInlined == true) {
1408 // We may have forced the inlining of some methods. Therefore check 1410 // We may have forced the inlining of some methods. Therefore check
1409 // if we can inline this method regardless of size. 1411 // if we can inline this method regardless of size.
1410 assert(InlineWeeder.canBeInlined(function, -1, false, 1412 assert(InlineWeeder.canBeInlined(function, -1, false,
1411 allowLoops: true)); 1413 allowLoops: true,
1414 enableUserAssertions: compiler.enableUserAssertions));
1412 return true; 1415 return true;
1413 } 1416 }
1414 1417
1415 int numParameters = function.functionSignature.parameterCount; 1418 int numParameters = function.functionSignature.parameterCount;
1416 int maxInliningNodes; 1419 int maxInliningNodes;
1417 bool useMaxInliningNodes = true; 1420 bool useMaxInliningNodes = true;
1418 if (insideLoop) { 1421 if (insideLoop) {
1419 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + 1422 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
1420 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; 1423 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
1421 } else { 1424 } else {
1422 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + 1425 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP +
1423 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; 1426 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters;
1424 } 1427 }
1425 1428
1426 // If a method is called only once, and all the methods in the 1429 // If a method is called only once, and all the methods in the
1427 // inlining stack are called only once as well, we know we will 1430 // inlining stack are called only once as well, we know we will
1428 // save on output size by inlining this method. 1431 // save on output size by inlining this method.
1429 if (isCalledOnce(element)) { 1432 if (isCalledOnce(element)) {
1430 useMaxInliningNodes = false; 1433 useMaxInliningNodes = false;
1431 } 1434 }
1432 bool canInline; 1435 bool canInline;
1433 canInline = InlineWeeder.canBeInlined( 1436 canInline = InlineWeeder.canBeInlined(
1434 function, maxInliningNodes, useMaxInliningNodes); 1437 function, maxInliningNodes, useMaxInliningNodes,
1438 enableUserAssertions: compiler.enableUserAssertions);
1435 if (canInline) { 1439 if (canInline) {
1436 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); 1440 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
1437 } else { 1441 } else {
1438 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); 1442 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop);
1439 } 1443 }
1440 return canInline; 1444 return canInline;
1441 } 1445 }
1442 1446
1443 void doInlining() { 1447 void doInlining() {
1444 // Add an explicit null check on the receiver before doing the 1448 // Add an explicit null check on the receiver before doing the
(...skipping 7016 matching lines...) Expand 10 before | Expand all | Expand 10 after
8461 static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3; 8465 static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
8462 static const INLINING_NODES_INSIDE_LOOP = 42; 8466 static const INLINING_NODES_INSIDE_LOOP = 42;
8463 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4; 8467 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
8464 8468
8465 bool seenReturn = false; 8469 bool seenReturn = false;
8466 bool tooDifficult = false; 8470 bool tooDifficult = false;
8467 int nodeCount = 0; 8471 int nodeCount = 0;
8468 final int maxInliningNodes; 8472 final int maxInliningNodes;
8469 final bool useMaxInliningNodes; 8473 final bool useMaxInliningNodes;
8470 final bool allowLoops; 8474 final bool allowLoops;
8475 final bool enableUserAssertions;
8471 8476
8472 InlineWeeder(this.maxInliningNodes, 8477 InlineWeeder(this.maxInliningNodes,
8473 this.useMaxInliningNodes, 8478 this.useMaxInliningNodes,
8474 this.allowLoops); 8479 this.allowLoops,
8480 this.enableUserAssertions);
8475 8481
8476 static bool canBeInlined(FunctionElement function, 8482 static bool canBeInlined(FunctionElement function,
8477 int maxInliningNodes, 8483 int maxInliningNodes,
8478 bool useMaxInliningNodes, 8484 bool useMaxInliningNodes,
8479 {bool allowLoops: false}) { 8485 {bool allowLoops: false,
8486 bool enableUserAssertions: null}) {
8487 assert(enableUserAssertions is bool); // Ensure we passed it.
8480 if (function.resolvedAst.elements.containsTryStatement) return false; 8488 if (function.resolvedAst.elements.containsTryStatement) return false;
8481 8489
8482 InlineWeeder weeder = 8490 InlineWeeder weeder =
8483 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); 8491 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops,
8492 enableUserAssertions);
8484 ast.FunctionExpression functionExpression = function.node; 8493 ast.FunctionExpression functionExpression = function.node;
8485 weeder.visit(functionExpression.initializers); 8494 weeder.visit(functionExpression.initializers);
8486 weeder.visit(functionExpression.body); 8495 weeder.visit(functionExpression.body);
8487 weeder.visit(functionExpression.asyncModifier); 8496 weeder.visit(functionExpression.asyncModifier);
8488 return !weeder.tooDifficult; 8497 return !weeder.tooDifficult;
8489 } 8498 }
8490 8499
8491 bool registerNode() { 8500 bool registerNode() {
8492 if (!useMaxInliningNodes) return true; 8501 if (!useMaxInliningNodes) return true;
8493 if (nodeCount++ > maxInliningNodes) { 8502 if (nodeCount++ > maxInliningNodes) {
(...skipping 11 matching lines...) Expand all
8505 void visitNode(ast.Node node) { 8514 void visitNode(ast.Node node) {
8506 if (!registerNode()) return; 8515 if (!registerNode()) return;
8507 if (seenReturn) { 8516 if (seenReturn) {
8508 tooDifficult = true; 8517 tooDifficult = true;
8509 } else { 8518 } else {
8510 node.visitChildren(this); 8519 node.visitChildren(this);
8511 } 8520 }
8512 } 8521 }
8513 8522
8514 @override 8523 @override
8524 void visitAssert(ast.Assert node) {
8525 if (enableUserAssertions) {
8526 visitNode(node);
8527 }
8528 }
8529
8530 @override
8515 void visitAsyncModifier(ast.AsyncModifier node) { 8531 void visitAsyncModifier(ast.AsyncModifier node) {
8516 if (node.isYielding || node.isAsynchronous) { 8532 if (node.isYielding || node.isAsynchronous) {
8517 tooDifficult = true; 8533 tooDifficult = true;
8518 } 8534 }
8519 } 8535 }
8520 8536
8521 void visitFunctionExpression(ast.Node node) { 8537 void visitFunctionExpression(ast.Node node) {
8522 if (!registerNode()) return; 8538 if (!registerNode()) return;
8523 tooDifficult = true; 8539 tooDifficult = true;
8524 } 8540 }
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
8951 if (unaliased is TypedefType) throw 'unable to unalias $type'; 8967 if (unaliased is TypedefType) throw 'unable to unalias $type';
8952 unaliased.accept(this, builder); 8968 unaliased.accept(this, builder);
8953 } 8969 }
8954 8970
8955 void visitDynamicType(DynamicType type, SsaBuilder builder) { 8971 void visitDynamicType(DynamicType type, SsaBuilder builder) {
8956 JavaScriptBackend backend = builder.compiler.backend; 8972 JavaScriptBackend backend = builder.compiler.backend;
8957 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 8973 ClassElement cls = backend.findHelper('DynamicRuntimeType');
8958 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 8974 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
8959 } 8975 }
8960 } 8976 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/js_runtime/lib/js_rti.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698