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 import 'dart:collection'; | 5 import 'dart:collection'; |
6 | 6 |
7 import 'package:js_runtime/shared/embedded_names.dart'; | 7 import 'package:js_runtime/shared/embedded_names.dart'; |
8 | 8 |
9 import '../closure.dart'; | 9 import '../closure.dart'; |
10 import '../common.dart'; | 10 import '../common.dart'; |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 } | 320 } |
321 | 321 |
322 /** | 322 /** |
323 * Documentation wanted -- johnniwinther | 323 * Documentation wanted -- johnniwinther |
324 * | 324 * |
325 * Invariant: [function] must be an implementation element. | 325 * Invariant: [function] must be an implementation element. |
326 */ | 326 */ |
327 void startFunction(AstElement element, ast.Node node) { | 327 void startFunction(AstElement element, ast.Node node) { |
328 assert(invariant(element, element.isImplementation)); | 328 assert(invariant(element, element.isImplementation)); |
329 Compiler compiler = builder.compiler; | 329 Compiler compiler = builder.compiler; |
330 closureData = compiler.closureToClassMapper | 330 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
331 .computeClosureToClassMapping(element.resolvedAst); | 331 compiler.backend.frontend.getResolvedAst(element.declaration)); |
332 | 332 |
333 if (element is FunctionElement) { | 333 if (element is FunctionElement) { |
334 FunctionElement functionElement = element; | 334 FunctionElement functionElement = element; |
335 FunctionSignature params = functionElement.functionSignature; | 335 FunctionSignature params = functionElement.functionSignature; |
336 ClosureScope scopeData = closureData.capturingScopes[node]; | 336 ClosureScope scopeData = closureData.capturingScopes[node]; |
337 params.orderedForEachParameter((ParameterElement parameterElement) { | 337 params.orderedForEachParameter((ParameterElement parameterElement) { |
338 if (element.isGenerativeConstructorBody) { | 338 if (element.isGenerativeConstructorBody) { |
339 if (scopeData != null && | 339 if (scopeData != null && |
340 scopeData.isCapturedVariable(parameterElement)) { | 340 scopeData.isCapturedVariable(parameterElement)) { |
341 // The parameter will be a field in the box passed as the | 341 // The parameter will be a field in the box passed as the |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 * boxed or stored in a closure then the method generates code to retrieve | 450 * boxed or stored in a closure then the method generates code to retrieve |
451 * the value. | 451 * the value. |
452 */ | 452 */ |
453 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { | 453 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { |
454 if (isAccessedDirectly(local)) { | 454 if (isAccessedDirectly(local)) { |
455 if (directLocals[local] == null) { | 455 if (directLocals[local] == null) { |
456 if (local is TypeVariableElement) { | 456 if (local is TypeVariableElement) { |
457 builder.reporter.internalError(builder.compiler.currentElement, | 457 builder.reporter.internalError(builder.compiler.currentElement, |
458 "Runtime type information not available for $local."); | 458 "Runtime type information not available for $local."); |
459 } else { | 459 } else { |
460 builder.reporter.internalError(local, "Cannot find value $local."); | 460 builder.reporter.internalError( |
| 461 local, "Cannot find value $local in ${directLocals.keys}."); |
461 } | 462 } |
462 } | 463 } |
463 HInstruction value = directLocals[local]; | 464 HInstruction value = directLocals[local]; |
464 if (sourceInformation != null) { | 465 if (sourceInformation != null) { |
465 value = new HRef(value, sourceInformation); | 466 value = new HRef(value, sourceInformation); |
466 builder.add(value); | 467 builder.add(value); |
467 } | 468 } |
468 return value; | 469 return value; |
469 } else if (isStoredInClosureField(local)) { | 470 } else if (isStoredInClosureField(local)) { |
470 ClosureFieldElement redirect = redirectionMapping[local]; | 471 ClosureFieldElement redirect = redirectionMapping[local]; |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 // We only inline factory JavaScript interop constructors. | 1371 // We only inline factory JavaScript interop constructors. |
1371 return false; | 1372 return false; |
1372 } | 1373 } |
1373 | 1374 |
1374 // Ensure that [element] is an implementation element. | 1375 // Ensure that [element] is an implementation element. |
1375 element = element.implementation; | 1376 element = element.implementation; |
1376 | 1377 |
1377 if (compiler.elementHasCompileTimeError(element)) return false; | 1378 if (compiler.elementHasCompileTimeError(element)) return false; |
1378 | 1379 |
1379 FunctionElement function = element; | 1380 FunctionElement function = element; |
| 1381 ResolvedAst functionResolvedAst = backend.frontend.getResolvedAst(function); |
1380 bool insideLoop = loopNesting > 0 || graph.calledInLoop; | 1382 bool insideLoop = loopNesting > 0 || graph.calledInLoop; |
1381 | 1383 |
1382 // Bail out early if the inlining decision is in the cache and we can't | 1384 // Bail out early if the inlining decision is in the cache and we can't |
1383 // inline (no need to check the hard constraints). | 1385 // inline (no need to check the hard constraints). |
1384 bool cachedCanBeInlined = | 1386 bool cachedCanBeInlined = |
1385 backend.inlineCache.canInline(function, insideLoop: insideLoop); | 1387 backend.inlineCache.canInline(function, insideLoop: insideLoop); |
1386 if (cachedCanBeInlined == false) return false; | 1388 if (cachedCanBeInlined == false) return false; |
1387 | 1389 |
1388 bool meetsHardConstraints() { | 1390 bool meetsHardConstraints() { |
1389 if (compiler.options.disableInlining) return false; | 1391 if (compiler.options.disableInlining) return false; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 isReachable = false; | 1431 isReachable = false; |
1430 return false; | 1432 return false; |
1431 } | 1433 } |
1432 } | 1434 } |
1433 | 1435 |
1434 return true; | 1436 return true; |
1435 } | 1437 } |
1436 | 1438 |
1437 bool doesNotContainCode() { | 1439 bool doesNotContainCode() { |
1438 // A function with size 1 does not contain any code. | 1440 // A function with size 1 does not contain any code. |
1439 return InlineWeeder.canBeInlined(function, 1, true, | 1441 return InlineWeeder.canBeInlined(functionResolvedAst, 1, true, |
1440 enableUserAssertions: compiler.options.enableUserAssertions); | 1442 enableUserAssertions: compiler.options.enableUserAssertions); |
1441 } | 1443 } |
1442 | 1444 |
1443 bool reductiveHeuristic() { | 1445 bool reductiveHeuristic() { |
1444 // The call is on a path which is executed rarely, so inline only if it | 1446 // The call is on a path which is executed rarely, so inline only if it |
1445 // does not make the program larger. | 1447 // does not make the program larger. |
1446 if (isCalledOnce(element)) { | 1448 if (isCalledOnce(element)) { |
1447 return InlineWeeder.canBeInlined(function, -1, false, | 1449 return InlineWeeder.canBeInlined(functionResolvedAst, -1, false, |
1448 enableUserAssertions: compiler.options.enableUserAssertions); | 1450 enableUserAssertions: compiler.options.enableUserAssertions); |
1449 } | 1451 } |
1450 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable | 1452 // TODO(sra): Measure if inlining would 'reduce' the size. One desirable |
1451 // case we miss by doing nothing is inlining very simple constructors | 1453 // case we miss by doing nothing is inlining very simple constructors |
1452 // where all fields are initialized with values from the arguments at this | 1454 // where all fields are initialized with values from the arguments at this |
1453 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but | 1455 // call site. The code is slightly larger (`new Foo(1)` vs `Foo$(1)`) but |
1454 // that usually means the factory constructor is left unused and not | 1456 // that usually means the factory constructor is left unused and not |
1455 // emitted. | 1457 // emitted. |
1456 // We at least inline bodies that are empty (and thus have a size of 1). | 1458 // We at least inline bodies that are empty (and thus have a size of 1). |
1457 return doesNotContainCode(); | 1459 return doesNotContainCode(); |
(...skipping 17 matching lines...) Expand all Loading... |
1475 } | 1477 } |
1476 | 1478 |
1477 // Do not inline code that is rarely executed unless it reduces size. | 1479 // Do not inline code that is rarely executed unless it reduces size. |
1478 if (inExpressionOfThrow || inLazyInitializerExpression) { | 1480 if (inExpressionOfThrow || inLazyInitializerExpression) { |
1479 return reductiveHeuristic(); | 1481 return reductiveHeuristic(); |
1480 } | 1482 } |
1481 | 1483 |
1482 if (cachedCanBeInlined == true) { | 1484 if (cachedCanBeInlined == true) { |
1483 // We may have forced the inlining of some methods. Therefore check | 1485 // We may have forced the inlining of some methods. Therefore check |
1484 // if we can inline this method regardless of size. | 1486 // if we can inline this method regardless of size. |
1485 assert(InlineWeeder.canBeInlined(function, -1, false, | 1487 assert(InlineWeeder.canBeInlined(functionResolvedAst, -1, false, |
1486 allowLoops: true, | 1488 allowLoops: true, |
1487 enableUserAssertions: compiler.options.enableUserAssertions)); | 1489 enableUserAssertions: compiler.options.enableUserAssertions)); |
1488 return true; | 1490 return true; |
1489 } | 1491 } |
1490 | 1492 |
1491 int numParameters = function.functionSignature.parameterCount; | 1493 int numParameters = function.functionSignature.parameterCount; |
1492 int maxInliningNodes; | 1494 int maxInliningNodes; |
1493 bool useMaxInliningNodes = true; | 1495 bool useMaxInliningNodes = true; |
1494 if (insideLoop) { | 1496 if (insideLoop) { |
1495 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 1497 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
1496 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 1498 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
1497 } else { | 1499 } else { |
1498 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 1500 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
1499 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 1501 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
1500 } | 1502 } |
1501 | 1503 |
1502 // If a method is called only once, and all the methods in the | 1504 // If a method is called only once, and all the methods in the |
1503 // inlining stack are called only once as well, we know we will | 1505 // inlining stack are called only once as well, we know we will |
1504 // save on output size by inlining this method. | 1506 // save on output size by inlining this method. |
1505 if (isCalledOnce(element)) { | 1507 if (isCalledOnce(element)) { |
1506 useMaxInliningNodes = false; | 1508 useMaxInliningNodes = false; |
1507 } | 1509 } |
1508 bool canInline; | 1510 bool canInline; |
1509 canInline = InlineWeeder.canBeInlined( | 1511 canInline = InlineWeeder.canBeInlined( |
1510 function, maxInliningNodes, useMaxInliningNodes, | 1512 functionResolvedAst, maxInliningNodes, useMaxInliningNodes, |
1511 enableUserAssertions: compiler.options.enableUserAssertions); | 1513 enableUserAssertions: compiler.options.enableUserAssertions); |
1512 if (canInline) { | 1514 if (canInline) { |
1513 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); | 1515 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
1514 } else { | 1516 } else { |
1515 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1517 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
1516 } | 1518 } |
1517 return canInline; | 1519 return canInline; |
1518 } | 1520 } |
1519 | 1521 |
1520 void doInlining() { | 1522 void doInlining() { |
1521 // Add an explicit null check on the receiver before doing the | 1523 // Add an explicit null check on the receiver before doing the |
1522 // inlining. We use [element] to get the same name in the | 1524 // inlining. We use [element] to get the same name in the |
1523 // NoSuchMethodError message as if we had called it. | 1525 // NoSuchMethodError message as if we had called it. |
1524 if (element.isInstanceMember && | 1526 if (element.isInstanceMember && |
1525 !element.isGenerativeConstructorBody && | 1527 !element.isGenerativeConstructorBody && |
1526 (mask == null || mask.isNullable)) { | 1528 (mask == null || mask.isNullable)) { |
1527 addWithPosition( | 1529 addWithPosition( |
1528 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1530 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
1529 isAssignable: false), | 1531 isAssignable: false), |
1530 currentNode); | 1532 currentNode); |
1531 } | 1533 } |
1532 List<HInstruction> compiledArguments = completeSendArgumentsList( | 1534 List<HInstruction> compiledArguments = completeSendArgumentsList( |
1533 function, selector, providedArguments, currentNode); | 1535 function, selector, providedArguments, currentNode); |
1534 enterInlinedMethod(function, currentNode, compiledArguments, | 1536 enterInlinedMethod(function, functionResolvedAst, compiledArguments, |
1535 instanceType: instanceType); | 1537 instanceType: instanceType); |
1536 inlinedFrom(function, () { | 1538 inlinedFrom(function, () { |
1537 if (!isReachable) { | 1539 if (!isReachable) { |
1538 emitReturn(graph.addConstantNull(compiler), null); | 1540 emitReturn(graph.addConstantNull(compiler), null); |
1539 } else { | 1541 } else { |
1540 doInline(function); | 1542 doInline(function); |
1541 } | 1543 } |
1542 }); | 1544 }); |
1543 leaveInlinedMethod(); | 1545 leaveInlinedMethod(); |
1544 } | 1546 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 } | 1673 } |
1672 | 1674 |
1673 /** | 1675 /** |
1674 * Documentation wanted -- johnniwinther | 1676 * Documentation wanted -- johnniwinther |
1675 * | 1677 * |
1676 * Invariant: [functionElement] must be an implementation element. | 1678 * Invariant: [functionElement] must be an implementation element. |
1677 */ | 1679 */ |
1678 HGraph buildMethod(FunctionElement functionElement) { | 1680 HGraph buildMethod(FunctionElement functionElement) { |
1679 assert(invariant(functionElement, functionElement.isImplementation)); | 1681 assert(invariant(functionElement, functionElement.isImplementation)); |
1680 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); | 1682 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); |
1681 ast.FunctionExpression function = functionElement.node; | 1683 ast.FunctionExpression function = resolvedAst.node; |
1682 assert(function != null); | 1684 assert(function != null); |
1683 assert(elements.getFunctionDefinition(function) != null); | 1685 assert(elements.getFunctionDefinition(function) != null); |
1684 openFunction(functionElement, function); | 1686 openFunction(functionElement, function); |
1685 String name = functionElement.name; | 1687 String name = functionElement.name; |
1686 if (backend.isJsInterop(functionElement)) { | 1688 if (backend.isJsInterop(functionElement)) { |
1687 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), | 1689 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), |
1688 sourceInformationBuilder.buildGeneric(function))); | 1690 sourceInformationBuilder.buildGeneric(function))); |
1689 var value = pop(); | 1691 var value = pop(); |
1690 closeAndGotoExit(new HReturn( | 1692 closeAndGotoExit(new HReturn( |
1691 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 1693 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 * The arguments of the function are inserted into the [localsHandler]. | 1827 * The arguments of the function are inserted into the [localsHandler]. |
1826 * | 1828 * |
1827 * When inlining a function, [:return:] statements are not emitted as | 1829 * When inlining a function, [:return:] statements are not emitted as |
1828 * [HReturn] instructions. Instead, the value of a synthetic element is | 1830 * [HReturn] instructions. Instead, the value of a synthetic element is |
1829 * updated in the [localsHandler]. This function creates such an element and | 1831 * updated in the [localsHandler]. This function creates such an element and |
1830 * stores it in the [returnLocal] field. | 1832 * stores it in the [returnLocal] field. |
1831 */ | 1833 */ |
1832 void setupStateForInlining( | 1834 void setupStateForInlining( |
1833 FunctionElement function, List<HInstruction> compiledArguments, | 1835 FunctionElement function, List<HInstruction> compiledArguments, |
1834 {InterfaceType instanceType}) { | 1836 {InterfaceType instanceType}) { |
| 1837 ResolvedAst resolvedAst = |
| 1838 compiler.backend.frontend.getResolvedAst(function.declaration); |
| 1839 assert(resolvedAst != null); |
1835 localsHandler = new LocalsHandler(this, function, instanceType); | 1840 localsHandler = new LocalsHandler(this, function, instanceType); |
1836 localsHandler.closureData = compiler.closureToClassMapper | 1841 localsHandler.closureData = |
1837 .computeClosureToClassMapping(function.resolvedAst); | 1842 compiler.closureToClassMapper.computeClosureToClassMapping(resolvedAst); |
1838 returnLocal = new SyntheticLocal("result", function); | 1843 returnLocal = new SyntheticLocal("result", function); |
1839 localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler)); | 1844 localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler)); |
1840 | 1845 |
1841 inTryStatement = false; // TODO(lry): why? Document. | 1846 inTryStatement = false; // TODO(lry): why? Document. |
1842 | 1847 |
1843 int argumentIndex = 0; | 1848 int argumentIndex = 0; |
1844 if (function.isInstanceMember) { | 1849 if (function.isInstanceMember) { |
1845 localsHandler.updateLocal(localsHandler.closureData.thisLocal, | 1850 localsHandler.updateLocal(localsHandler.closureData.thisLocal, |
1846 compiledArguments[argumentIndex++]); | 1851 compiledArguments[argumentIndex++]); |
1847 } | 1852 } |
1848 | 1853 |
1849 FunctionSignature signature = function.functionSignature; | 1854 FunctionSignature signature = function.functionSignature; |
1850 signature.orderedForEachParameter((ParameterElement parameter) { | 1855 signature.orderedForEachParameter((ParameterElement parameter) { |
1851 HInstruction argument = compiledArguments[argumentIndex++]; | 1856 HInstruction argument = compiledArguments[argumentIndex++]; |
1852 localsHandler.updateLocal(parameter, argument); | 1857 localsHandler.updateLocal(parameter, argument); |
1853 }); | 1858 }); |
1854 | 1859 |
1855 ClassElement enclosing = function.enclosingClass; | 1860 ClassElement enclosing = function.enclosingClass; |
1856 if ((function.isConstructor || function.isGenerativeConstructorBody) && | 1861 if ((function.isConstructor || function.isGenerativeConstructorBody) && |
1857 backend.classNeedsRti(enclosing)) { | 1862 backend.classNeedsRti(enclosing)) { |
1858 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1863 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
1859 HInstruction argument = compiledArguments[argumentIndex++]; | 1864 HInstruction argument = compiledArguments[argumentIndex++]; |
1860 localsHandler.updateLocal( | 1865 localsHandler.updateLocal( |
1861 localsHandler.getTypeVariableAsLocal(typeVariable), argument); | 1866 localsHandler.getTypeVariableAsLocal(typeVariable), argument); |
1862 }); | 1867 }); |
1863 } | 1868 } |
1864 assert(argumentIndex == compiledArguments.length); | 1869 assert(argumentIndex == compiledArguments.length); |
1865 | 1870 |
1866 resolvedAst = function.resolvedAst; | |
1867 assert(resolvedAst != null); | |
1868 returnType = signature.type.returnType; | 1871 returnType = signature.type.returnType; |
1869 stack = <HInstruction>[]; | 1872 stack = <HInstruction>[]; |
1870 | 1873 |
1871 insertTraceCall(function); | 1874 insertTraceCall(function); |
1872 insertCoverageCall(function); | 1875 insertCoverageCall(function); |
1873 } | 1876 } |
1874 | 1877 |
1875 void restoreState(AstInliningState state) { | 1878 void restoreState(AstInliningState state) { |
1876 localsHandler = state.oldLocalsHandler; | 1879 localsHandler = state.oldLocalsHandler; |
1877 returnLocal = state.oldReturnLocal; | 1880 returnLocal = state.oldReturnLocal; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 // Don't forget to update the field, if the parameter is of the | 2004 // Don't forget to update the field, if the parameter is of the |
2002 // form [:this.x:]. | 2005 // form [:this.x:]. |
2003 if (parameter.isInitializingFormal) { | 2006 if (parameter.isInitializingFormal) { |
2004 InitializingFormalElement fieldParameterElement = parameter; | 2007 InitializingFormalElement fieldParameterElement = parameter; |
2005 fieldValues[fieldParameterElement.fieldElement] = argument; | 2008 fieldValues[fieldParameterElement.fieldElement] = argument; |
2006 } | 2009 } |
2007 }); | 2010 }); |
2008 | 2011 |
2009 // Build the initializers in the context of the new constructor. | 2012 // Build the initializers in the context of the new constructor. |
2010 ResolvedAst oldResolvedAst = resolvedAst; | 2013 ResolvedAst oldResolvedAst = resolvedAst; |
2011 resolvedAst = callee.resolvedAst; | 2014 resolvedAst = backend.frontend.getResolvedAst(callee); |
2012 ClosureClassMap oldClosureData = localsHandler.closureData; | 2015 ClosureClassMap oldClosureData = localsHandler.closureData; |
2013 ClosureClassMap newClosureData = compiler.closureToClassMapper | 2016 ClosureClassMap newClosureData = compiler.closureToClassMapper |
2014 .computeClosureToClassMapping(resolvedAst); | 2017 .computeClosureToClassMapping(resolvedAst); |
2015 localsHandler.closureData = newClosureData; | 2018 localsHandler.closureData = newClosureData; |
2016 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 2019 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
2017 localsHandler.enterScope(resolvedAst.node, callee); | 2020 localsHandler.enterScope(resolvedAst.node, callee); |
2018 } | 2021 } |
2019 buildInitializers(callee, constructors, fieldValues); | 2022 buildInitializers(callee, constructors, fieldValues); |
2020 localsHandler.closureData = oldClosureData; | 2023 localsHandler.closureData = oldClosureData; |
2021 resolvedAst = oldResolvedAst; | 2024 resolvedAst = oldResolvedAst; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2168 ast.Expression initializer = member.initializer; | 2171 ast.Expression initializer = member.initializer; |
2169 if (initializer == null) { | 2172 if (initializer == null) { |
2170 // Unassigned fields of native classes are not initialized to | 2173 // Unassigned fields of native classes are not initialized to |
2171 // prevent overwriting pre-initialized native properties. | 2174 // prevent overwriting pre-initialized native properties. |
2172 if (!backend.isNativeOrExtendsNative(classElement)) { | 2175 if (!backend.isNativeOrExtendsNative(classElement)) { |
2173 fieldValues[member] = graph.addConstantNull(compiler); | 2176 fieldValues[member] = graph.addConstantNull(compiler); |
2174 } | 2177 } |
2175 } else { | 2178 } else { |
2176 ast.Node right = initializer; | 2179 ast.Node right = initializer; |
2177 ResolvedAst savedResolvedAst = resolvedAst; | 2180 ResolvedAst savedResolvedAst = resolvedAst; |
2178 resolvedAst = member.resolvedAst; | 2181 resolvedAst = backend.frontend.getResolvedAst(member); |
2179 // In case the field initializer uses closures, run the | 2182 // In case the field initializer uses closures, run the |
2180 // closure to class mapper. | 2183 // closure to class mapper. |
2181 compiler.closureToClassMapper | 2184 compiler.closureToClassMapper |
2182 .computeClosureToClassMapping(resolvedAst); | 2185 .computeClosureToClassMapping(resolvedAst); |
2183 inlinedFrom(member, () => right.accept(this)); | 2186 inlinedFrom(member, () => right.accept(this)); |
2184 resolvedAst = savedResolvedAst; | 2187 resolvedAst = savedResolvedAst; |
2185 fieldValues[member] = pop(); | 2188 fieldValues[member] = pop(); |
2186 } | 2189 } |
2187 }); | 2190 }); |
2188 }); | 2191 }); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2375 List bodyCallInputs = <HInstruction>[]; | 2378 List bodyCallInputs = <HInstruction>[]; |
2376 if (isNativeUpgradeFactory) { | 2379 if (isNativeUpgradeFactory) { |
2377 if (interceptor == null) { | 2380 if (interceptor == null) { |
2378 ConstantValue constant = | 2381 ConstantValue constant = |
2379 new InterceptorConstantValue(classElement.thisType); | 2382 new InterceptorConstantValue(classElement.thisType); |
2380 interceptor = graph.addConstant(constant, compiler); | 2383 interceptor = graph.addConstant(constant, compiler); |
2381 } | 2384 } |
2382 bodyCallInputs.add(interceptor); | 2385 bodyCallInputs.add(interceptor); |
2383 } | 2386 } |
2384 bodyCallInputs.add(newObject); | 2387 bodyCallInputs.add(newObject); |
2385 ResolvedAst resolvedAst = constructor.resolvedAst; | 2388 ResolvedAst resolvedAst = backend.frontend.getResolvedAst(constructor); |
2386 ast.Node node = resolvedAst.node; | 2389 ast.Node node = resolvedAst.node; |
2387 ClosureClassMap parameterClosureData = | 2390 ClosureClassMap parameterClosureData = |
2388 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 2391 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
2389 | 2392 |
2390 FunctionSignature functionSignature = body.functionSignature; | 2393 FunctionSignature functionSignature = body.functionSignature; |
2391 // Provide the parameters to the generative constructor body. | 2394 // Provide the parameters to the generative constructor body. |
2392 functionSignature.orderedForEachParameter((ParameterElement parameter) { | 2395 functionSignature.orderedForEachParameter((ParameterElement parameter) { |
2393 // If [parameter] is boxed, it will be a field in the box passed as the | 2396 // If [parameter] is boxed, it will be a field in the box passed as the |
2394 // last parameter. So no need to directly pass it. | 2397 // last parameter. So no need to directly pass it. |
2395 if (!localsHandler.isBoxed(parameter)) { | 2398 if (!localsHandler.isBoxed(parameter)) { |
(...skipping 5476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7872 } | 7875 } |
7873 | 7876 |
7874 visitTypeVariable(ast.TypeVariable node) { | 7877 visitTypeVariable(ast.TypeVariable node) { |
7875 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); | 7878 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); |
7876 } | 7879 } |
7877 | 7880 |
7878 /** | 7881 /** |
7879 * This method is invoked before inlining the body of [function] into this | 7882 * This method is invoked before inlining the body of [function] into this |
7880 * [SsaBuilder]. | 7883 * [SsaBuilder]. |
7881 */ | 7884 */ |
7882 void enterInlinedMethod(FunctionElement function, ast.Node _, | 7885 void enterInlinedMethod(FunctionElement function, |
7883 List<HInstruction> compiledArguments, | 7886 ResolvedAst functionResolvedAst, List<HInstruction> compiledArguments, |
7884 {InterfaceType instanceType}) { | 7887 {InterfaceType instanceType}) { |
7885 AstInliningState state = new AstInliningState( | 7888 AstInliningState state = new AstInliningState( |
7886 function, | 7889 function, |
7887 returnLocal, | 7890 returnLocal, |
7888 returnType, | 7891 returnType, |
7889 resolvedAst, | 7892 resolvedAst, |
7890 stack, | 7893 stack, |
7891 localsHandler, | 7894 localsHandler, |
7892 inTryStatement, | 7895 inTryStatement, |
7893 allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function)); | 7896 allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function)); |
| 7897 resolvedAst = functionResolvedAst; |
7894 inliningStack.add(state); | 7898 inliningStack.add(state); |
7895 | 7899 |
7896 // Setting up the state of the (AST) builder is performed even when the | 7900 // Setting up the state of the (AST) builder is performed even when the |
7897 // inlined function is in IR, because the irInliner uses the [returnElement] | 7901 // inlined function is in IR, because the irInliner uses the [returnElement] |
7898 // of the AST builder. | 7902 // of the AST builder. |
7899 setupStateForInlining(function, compiledArguments, | 7903 setupStateForInlining(function, compiledArguments, |
7900 instanceType: instanceType); | 7904 instanceType: instanceType); |
7901 } | 7905 } |
7902 | 7906 |
7903 void leaveInlinedMethod() { | 7907 void leaveInlinedMethod() { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8080 int nodeCount = 0; | 8084 int nodeCount = 0; |
8081 final int maxInliningNodes; | 8085 final int maxInliningNodes; |
8082 final bool useMaxInliningNodes; | 8086 final bool useMaxInliningNodes; |
8083 final bool allowLoops; | 8087 final bool allowLoops; |
8084 final bool enableUserAssertions; | 8088 final bool enableUserAssertions; |
8085 | 8089 |
8086 InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes, this.allowLoops, | 8090 InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes, this.allowLoops, |
8087 this.enableUserAssertions); | 8091 this.enableUserAssertions); |
8088 | 8092 |
8089 static bool canBeInlined( | 8093 static bool canBeInlined( |
8090 FunctionElement function, int maxInliningNodes, bool useMaxInliningNodes, | 8094 ResolvedAst resolvedAst, int maxInliningNodes, bool useMaxInliningNodes, |
8091 {bool allowLoops: false, bool enableUserAssertions: null}) { | 8095 {bool allowLoops: false, bool enableUserAssertions: null}) { |
8092 assert(enableUserAssertions is bool); // Ensure we passed it. | 8096 assert(enableUserAssertions is bool); // Ensure we passed it. |
8093 if (function.resolvedAst.elements.containsTryStatement) return false; | 8097 if (resolvedAst.elements.containsTryStatement) return false; |
8094 | 8098 |
8095 InlineWeeder weeder = new InlineWeeder(maxInliningNodes, | 8099 InlineWeeder weeder = new InlineWeeder(maxInliningNodes, |
8096 useMaxInliningNodes, allowLoops, enableUserAssertions); | 8100 useMaxInliningNodes, allowLoops, enableUserAssertions); |
8097 ast.FunctionExpression functionExpression = function.node; | 8101 ast.FunctionExpression functionExpression = resolvedAst.node; |
8098 weeder.visit(functionExpression.initializers); | 8102 weeder.visit(functionExpression.initializers); |
8099 weeder.visit(functionExpression.body); | 8103 weeder.visit(functionExpression.body); |
8100 weeder.visit(functionExpression.asyncModifier); | 8104 weeder.visit(functionExpression.asyncModifier); |
8101 return !weeder.tooDifficult; | 8105 return !weeder.tooDifficult; |
8102 } | 8106 } |
8103 | 8107 |
8104 bool registerNode() { | 8108 bool registerNode() { |
8105 if (!useMaxInliningNodes) return true; | 8109 if (!useMaxInliningNodes) return true; |
8106 if (nodeCount++ > maxInliningNodes) { | 8110 if (nodeCount++ > maxInliningNodes) { |
8107 tooDifficult = true; | 8111 tooDifficult = true; |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8569 const _LoopTypeVisitor(); | 8573 const _LoopTypeVisitor(); |
8570 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8574 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
8571 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8575 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
8572 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8576 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
8573 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8577 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
8574 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8578 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8575 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8579 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8576 int visitSwitchStatement(ast.SwitchStatement node) => | 8580 int visitSwitchStatement(ast.SwitchStatement node) => |
8577 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8581 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
8578 } | 8582 } |
OLD | NEW |