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

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

Issue 809603005: Do less inlining in lazy initializer expressions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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 SsaCodeGeneratorTask generator; 8 SsaCodeGeneratorTask generator;
9 SsaBuilderTask builder; 9 SsaBuilderTask builder;
10 SsaOptimizerTask optimizer; 10 SsaOptimizerTask optimizer;
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 /** 927 /**
928 * This class builds SSA nodes for functions represented in AST. 928 * This class builds SSA nodes for functions represented in AST.
929 */ 929 */
930 class SsaBuilder extends ResolvedVisitor { 930 class SsaBuilder extends ResolvedVisitor {
931 final Compiler compiler; 931 final Compiler compiler;
932 final JavaScriptBackend backend; 932 final JavaScriptBackend backend;
933 final ConstantSystem constantSystem; 933 final ConstantSystem constantSystem;
934 final CodegenWorkItem work; 934 final CodegenWorkItem work;
935 final RuntimeTypes rti; 935 final RuntimeTypes rti;
936 final bool generateSourceMap; 936 final bool generateSourceMap;
937 bool inLazyInitializerExpression = false;
937 938
938 /* This field is used by the native handler. */ 939 /* This field is used by the native handler. */
939 final NativeEmitter nativeEmitter; 940 final NativeEmitter nativeEmitter;
940 941
941 final HGraph graph = new HGraph(); 942 final HGraph graph = new HGraph();
942 943
943 /** 944 /**
944 * The current block to add instructions to. Might be null, if we are 945 * The current block to add instructions to. Might be null, if we are
945 * visiting dead code, but see [isReachable]. 946 * visiting dead code, but see [isReachable].
946 */ 947 */
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 && returnType.isEmpty 1269 && returnType.isEmpty
1269 && !returnType.isNullable) { 1270 && !returnType.isNullable) {
1270 isReachable = false; 1271 isReachable = false;
1271 return false; 1272 return false;
1272 } 1273 }
1273 } 1274 }
1274 1275
1275 return true; 1276 return true;
1276 } 1277 }
1277 1278
1279 bool reductiveHeuristic() {
1280 // The call is on a path which is executed rarely, so inline only if it
1281 // does not make the program larger.
1282 if (isCalledOnce(element)) {
1283 return InlineWeeder.canBeInlined(function.node, -1, false);
1284 }
1285 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable
1286 // case we miss my doing nothing is inlining very simple constructors
1287 // where all fields are initialized with values from the arguments at this
1288 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but
1289 // that usually means the factory constructor is left unused and not
1290 // emitted.
1291 return false;
1292 }
1293
1278 bool heuristicSayGoodToGo() { 1294 bool heuristicSayGoodToGo() {
1279 // Don't inline recursivly 1295 // Don't inline recursively
1280 if (inliningStack.any((entry) => entry.function == function)) { 1296 if (inliningStack.any((entry) => entry.function == function)) {
1281 return false; 1297 return false;
1282 } 1298 }
1283 1299
1284 if (inExpressionOfThrow) return false; 1300 if (element.isSynthesized) return true;
1285 1301
1286 if (element.isSynthesized) return true; 1302 if (inExpressionOfThrow || inLazyInitializerExpression) {
1303 return reductiveHeuristic();
1304 }
1287 1305
1288 if (cachedCanBeInlined == true) return cachedCanBeInlined; 1306 if (cachedCanBeInlined == true) return cachedCanBeInlined;
1289 1307
1290 if (backend.functionsToAlwaysInline.contains(function)) { 1308 if (backend.functionsToAlwaysInline.contains(function)) {
1291 // Inline this function regardless of it's size. 1309 // Inline this function regardless of it's size.
1292 assert(InlineWeeder.canBeInlined(function.node, -1, false, 1310 assert(InlineWeeder.canBeInlined(function.node, -1, false,
1293 allowLoops: true)); 1311 allowLoops: true));
1294 return true; 1312 return true;
1295 } 1313 }
1296 1314
1297 int numParameters = function.functionSignature.parameterCount; 1315 int numParameters = function.functionSignature.parameterCount;
1298 int maxInliningNodes; 1316 int maxInliningNodes;
1299 bool useMaxInliningNodes = true; 1317 bool useMaxInliningNodes = true;
1300 if (insideLoop) { 1318 if (insideLoop) {
1301 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + 1319 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
1302 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; 1320 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
1303 } else { 1321 } else {
1304 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + 1322 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP +
1305 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; 1323 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters;
1306 } 1324 }
1307 1325
1308 // If a method is called only once, and all the methods in the 1326 // If a method is called only once, and all the methods in the
1309 // inlining stack are called only once as well, we know we will 1327 // inlining stack are called only once as well, we know we will
1310 // save on output size by inlining this method. 1328 // save on output size by inlining this method.
1311 TypesInferrer inferrer = compiler.typesTask.typesInferrer; 1329 if (isCalledOnce(element)) {
1312 if (inferrer.isCalledOnce(element) && allInlinedFunctionsCalledOnce) {
1313 useMaxInliningNodes = false; 1330 useMaxInliningNodes = false;
1314 } 1331 }
1315 bool canInline; 1332 bool canInline;
1316 ast.FunctionExpression functionNode = function.node; 1333 ast.FunctionExpression functionNode = function.node;
1317 canInline = InlineWeeder.canBeInlined( 1334 canInline = InlineWeeder.canBeInlined(
1318 functionNode, maxInliningNodes, useMaxInliningNodes); 1335 functionNode, maxInliningNodes, useMaxInliningNodes);
1319 if (canInline) { 1336 if (canInline) {
1320 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); 1337 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
1321 } else { 1338 } else {
1322 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); 1339 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 return true; 1374 return true;
1358 } 1375 }
1359 1376
1360 return false; 1377 return false;
1361 } 1378 }
1362 1379
1363 bool get allInlinedFunctionsCalledOnce { 1380 bool get allInlinedFunctionsCalledOnce {
1364 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; 1381 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce;
1365 } 1382 }
1366 1383
1384 bool isCalledOnce(Element element) {
1385 if (!allInlinedFunctionsCalledOnce) return false;
1386 TypesInferrer inferrer = compiler.typesTask.typesInferrer;
1387 return inferrer.isCalledOnce(element);
1388 }
1389
1367 inlinedFrom(Element element, f()) { 1390 inlinedFrom(Element element, f()) {
1368 assert(element is FunctionElement || element is VariableElement); 1391 assert(element is FunctionElement || element is VariableElement);
1369 return compiler.withCurrentElement(element, () { 1392 return compiler.withCurrentElement(element, () {
1370 // The [sourceElementStack] contains declaration elements. 1393 // The [sourceElementStack] contains declaration elements.
1371 sourceElementStack.add(element.declaration); 1394 sourceElementStack.add(element.declaration);
1372 var result = f(); 1395 var result = f();
1373 sourceElementStack.removeLast(); 1396 sourceElementStack.removeLast();
1374 return result; 1397 return result;
1375 }); 1398 });
1376 } 1399 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 // Add the parameter as the last instruction of the entry block. 1535 // Add the parameter as the last instruction of the entry block.
1513 // If the method is intercepted, we want the actual receiver 1536 // If the method is intercepted, we want the actual receiver
1514 // to be the first parameter. 1537 // to be the first parameter.
1515 graph.entry.addBefore(graph.entry.last, parameter); 1538 graph.entry.addBefore(graph.entry.last, parameter);
1516 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); 1539 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type);
1517 add(new HFieldSet(field, thisInstruction, value)); 1540 add(new HFieldSet(field, thisInstruction, value));
1518 return closeFunction(); 1541 return closeFunction();
1519 } 1542 }
1520 1543
1521 HGraph buildLazyInitializer(VariableElement variable) { 1544 HGraph buildLazyInitializer(VariableElement variable) {
1545 inLazyInitializerExpression = true;
1522 ast.Node node = variable.node; 1546 ast.Node node = variable.node;
1523 openFunction(variable, node); 1547 openFunction(variable, node);
1524 assert(invariant(variable, variable.initializer != null, 1548 assert(invariant(variable, variable.initializer != null,
1525 message: "Non-constant variable $variable has no initializer.")); 1549 message: "Non-constant variable $variable has no initializer."));
1526 visit(variable.initializer); 1550 visit(variable.initializer);
1527 HInstruction value = pop(); 1551 HInstruction value = pop();
1528 value = potentiallyCheckOrTrustType(value, variable.type); 1552 value = potentiallyCheckOrTrustType(value, variable.type);
1529 closeAndGotoExit(new HReturn(value)); 1553 closeAndGotoExit(new HReturn(value));
1530 return closeFunction(); 1554 return closeFunction();
1531 } 1555 }
(...skipping 5091 matching lines...) Expand 10 before | Expand all | Expand 10 after
6623 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6647 if (unaliased is TypedefType) throw 'unable to unalias $type';
6624 unaliased.accept(this, builder); 6648 unaliased.accept(this, builder);
6625 } 6649 }
6626 6650
6627 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6651 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6628 JavaScriptBackend backend = builder.compiler.backend; 6652 JavaScriptBackend backend = builder.compiler.backend;
6629 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 6653 ClassElement cls = backend.findHelper('DynamicRuntimeType');
6630 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 6654 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
6631 } 6655 }
6632 } 6656 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698