| 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.computeClosureToClassMapping( | 330 closureData = compiler.closureToClassMapper |
| 331 compiler.backend.frontend.getResolvedAst(element.declaration)); | 331 .computeClosureToClassMapping(element.resolvedAst); |
| 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 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 // We only inline factory JavaScript interop constructors. | 1376 // We only inline factory JavaScript interop constructors. |
| 1377 return false; | 1377 return false; |
| 1378 } | 1378 } |
| 1379 | 1379 |
| 1380 // Ensure that [element] is an implementation element. | 1380 // Ensure that [element] is an implementation element. |
| 1381 element = element.implementation; | 1381 element = element.implementation; |
| 1382 | 1382 |
| 1383 if (compiler.elementHasCompileTimeError(element)) return false; | 1383 if (compiler.elementHasCompileTimeError(element)) return false; |
| 1384 | 1384 |
| 1385 FunctionElement function = element; | 1385 FunctionElement function = element; |
| 1386 ResolvedAst functionResolvedAst = backend.frontend.getResolvedAst(function); | 1386 ResolvedAst functionResolvedAst = function.resolvedAst; |
| 1387 bool insideLoop = loopNesting > 0 || graph.calledInLoop; | 1387 bool insideLoop = loopNesting > 0 || graph.calledInLoop; |
| 1388 | 1388 |
| 1389 // Bail out early if the inlining decision is in the cache and we can't | 1389 // Bail out early if the inlining decision is in the cache and we can't |
| 1390 // inline (no need to check the hard constraints). | 1390 // inline (no need to check the hard constraints). |
| 1391 bool cachedCanBeInlined = | 1391 bool cachedCanBeInlined = |
| 1392 backend.inlineCache.canInline(function, insideLoop: insideLoop); | 1392 backend.inlineCache.canInline(function, insideLoop: insideLoop); |
| 1393 if (cachedCanBeInlined == false) return false; | 1393 if (cachedCanBeInlined == false) return false; |
| 1394 | 1394 |
| 1395 bool meetsHardConstraints() { | 1395 bool meetsHardConstraints() { |
| 1396 if (compiler.options.disableInlining) return false; | 1396 if (compiler.options.disableInlining) return false; |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 * The arguments of the function are inserted into the [localsHandler]. | 1840 * The arguments of the function are inserted into the [localsHandler]. |
| 1841 * | 1841 * |
| 1842 * When inlining a function, [:return:] statements are not emitted as | 1842 * When inlining a function, [:return:] statements are not emitted as |
| 1843 * [HReturn] instructions. Instead, the value of a synthetic element is | 1843 * [HReturn] instructions. Instead, the value of a synthetic element is |
| 1844 * updated in the [localsHandler]. This function creates such an element and | 1844 * updated in the [localsHandler]. This function creates such an element and |
| 1845 * stores it in the [returnLocal] field. | 1845 * stores it in the [returnLocal] field. |
| 1846 */ | 1846 */ |
| 1847 void setupStateForInlining( | 1847 void setupStateForInlining( |
| 1848 FunctionElement function, List<HInstruction> compiledArguments, | 1848 FunctionElement function, List<HInstruction> compiledArguments, |
| 1849 {InterfaceType instanceType}) { | 1849 {InterfaceType instanceType}) { |
| 1850 ResolvedAst resolvedAst = | 1850 ResolvedAst resolvedAst = function.resolvedAst; |
| 1851 compiler.backend.frontend.getResolvedAst(function.declaration); | |
| 1852 assert(resolvedAst != null); | 1851 assert(resolvedAst != null); |
| 1853 localsHandler = new LocalsHandler(this, function, instanceType); | 1852 localsHandler = new LocalsHandler(this, function, instanceType); |
| 1854 localsHandler.closureData = | 1853 localsHandler.closureData = |
| 1855 compiler.closureToClassMapper.computeClosureToClassMapping(resolvedAst); | 1854 compiler.closureToClassMapper.computeClosureToClassMapping(resolvedAst); |
| 1856 returnLocal = new SyntheticLocal("result", function); | 1855 returnLocal = new SyntheticLocal("result", function); |
| 1857 localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler)); | 1856 localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler)); |
| 1858 | 1857 |
| 1859 inTryStatement = false; // TODO(lry): why? Document. | 1858 inTryStatement = false; // TODO(lry): why? Document. |
| 1860 | 1859 |
| 1861 int argumentIndex = 0; | 1860 int argumentIndex = 0; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 // Don't forget to update the field, if the parameter is of the | 2016 // Don't forget to update the field, if the parameter is of the |
| 2018 // form [:this.x:]. | 2017 // form [:this.x:]. |
| 2019 if (parameter.isInitializingFormal) { | 2018 if (parameter.isInitializingFormal) { |
| 2020 InitializingFormalElement fieldParameterElement = parameter; | 2019 InitializingFormalElement fieldParameterElement = parameter; |
| 2021 fieldValues[fieldParameterElement.fieldElement] = argument; | 2020 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 2022 } | 2021 } |
| 2023 }); | 2022 }); |
| 2024 | 2023 |
| 2025 // Build the initializers in the context of the new constructor. | 2024 // Build the initializers in the context of the new constructor. |
| 2026 ResolvedAst oldResolvedAst = resolvedAst; | 2025 ResolvedAst oldResolvedAst = resolvedAst; |
| 2027 resolvedAst = backend.frontend.getResolvedAst(callee); | 2026 resolvedAst = callee.resolvedAst; |
| 2028 ClosureClassMap oldClosureData = localsHandler.closureData; | 2027 ClosureClassMap oldClosureData = localsHandler.closureData; |
| 2029 ClosureClassMap newClosureData = compiler.closureToClassMapper | 2028 ClosureClassMap newClosureData = compiler.closureToClassMapper |
| 2030 .computeClosureToClassMapping(resolvedAst); | 2029 .computeClosureToClassMapping(resolvedAst); |
| 2031 localsHandler.closureData = newClosureData; | 2030 localsHandler.closureData = newClosureData; |
| 2032 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 2031 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 2033 localsHandler.enterScope(resolvedAst.node, callee); | 2032 localsHandler.enterScope(resolvedAst.node, callee); |
| 2034 } | 2033 } |
| 2035 buildInitializers(callee, constructorResolvedAsts, fieldValues); | 2034 buildInitializers(callee, constructorResolvedAsts, fieldValues); |
| 2036 localsHandler.closureData = oldClosureData; | 2035 localsHandler.closureData = oldClosureData; |
| 2037 resolvedAst = oldResolvedAst; | 2036 resolvedAst = oldResolvedAst; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2058 ConstructorElement constructor, | 2057 ConstructorElement constructor, |
| 2059 List<ResolvedAst> constructorResolvedAsts, | 2058 List<ResolvedAst> constructorResolvedAsts, |
| 2060 Map<Element, HInstruction> fieldValues) { | 2059 Map<Element, HInstruction> fieldValues) { |
| 2061 assert(invariant(constructor, constructor.isSynthesized, | 2060 assert(invariant(constructor, constructor.isSynthesized, |
| 2062 message: "Unexpected unsynthesized constructor: $constructor")); | 2061 message: "Unexpected unsynthesized constructor: $constructor")); |
| 2063 List<HInstruction> arguments = <HInstruction>[]; | 2062 List<HInstruction> arguments = <HInstruction>[]; |
| 2064 HInstruction compileArgument(ParameterElement parameter) { | 2063 HInstruction compileArgument(ParameterElement parameter) { |
| 2065 return localsHandler.readLocal(parameter); | 2064 return localsHandler.readLocal(parameter); |
| 2066 } | 2065 } |
| 2067 | 2066 |
| 2068 Element target = constructor.definingConstructor.implementation; | 2067 ConstructorElement target = constructor.definingConstructor.implementation; |
| 2069 bool match = !target.isMalformed && | 2068 bool match = !target.isMalformed && |
| 2070 CallStructure.addForwardingElementArgumentsToList( | 2069 CallStructure.addForwardingElementArgumentsToList( |
| 2071 constructor, | 2070 constructor, |
| 2072 arguments, | 2071 arguments, |
| 2073 target, | 2072 target, |
| 2074 compileArgument, | 2073 compileArgument, |
| 2075 handleConstantForOptionalParameter); | 2074 handleConstantForOptionalParameter); |
| 2076 if (!match) { | 2075 if (!match) { |
| 2077 if (compiler.elementHasCompileTimeError(constructor)) { | 2076 if (compiler.elementHasCompileTimeError(constructor)) { |
| 2078 return; | 2077 return; |
| 2079 } | 2078 } |
| 2080 // If this fails, the selector we constructed for the call to a | 2079 // If this fails, the selector we constructed for the call to a |
| 2081 // forwarding constructor in a mixin application did not match the | 2080 // forwarding constructor in a mixin application did not match the |
| 2082 // constructor (which, for example, may happen when the libraries are | 2081 // constructor (which, for example, may happen when the libraries are |
| 2083 // not compatible for private names, see issue 20394). | 2082 // not compatible for private names, see issue 20394). |
| 2084 reporter.internalError( | 2083 reporter.internalError( |
| 2085 constructor, 'forwarding constructor call does not match'); | 2084 constructor, 'forwarding constructor call does not match'); |
| 2086 } | 2085 } |
| 2087 inlineSuperOrRedirect(backend.frontend.getResolvedAst(target), arguments, | 2086 inlineSuperOrRedirect(target.resolvedAst, arguments, |
| 2088 constructorResolvedAsts, fieldValues, constructor); | 2087 constructorResolvedAsts, fieldValues, constructor); |
| 2089 } | 2088 } |
| 2090 | 2089 |
| 2091 /** | 2090 /** |
| 2092 * Run through the initializers and inline all field initializers. Recursively | 2091 * Run through the initializers and inline all field initializers. Recursively |
| 2093 * inlines super initializers. | 2092 * inlines super initializers. |
| 2094 * | 2093 * |
| 2095 * The constructors of the inlined initializers is added to [constructors] | 2094 * The constructors of the inlined initializers is added to [constructors] |
| 2096 * with sub constructors having a lower index than super constructors. | 2095 * with sub constructors having a lower index than super constructors. |
| 2097 * | 2096 * |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2124 ast.Initializers.isConstructorRedirect(call)); | 2123 ast.Initializers.isConstructorRedirect(call)); |
| 2125 FunctionElement target = elements[call].implementation; | 2124 FunctionElement target = elements[call].implementation; |
| 2126 CallStructure callStructure = | 2125 CallStructure callStructure = |
| 2127 elements.getSelector(call).callStructure; | 2126 elements.getSelector(call).callStructure; |
| 2128 Link<ast.Node> arguments = call.arguments; | 2127 Link<ast.Node> arguments = call.arguments; |
| 2129 List<HInstruction> compiledArguments; | 2128 List<HInstruction> compiledArguments; |
| 2130 inlinedFrom(resolvedAst, () { | 2129 inlinedFrom(resolvedAst, () { |
| 2131 compiledArguments = | 2130 compiledArguments = |
| 2132 makeStaticArgumentList(callStructure, arguments, target); | 2131 makeStaticArgumentList(callStructure, arguments, target); |
| 2133 }); | 2132 }); |
| 2134 inlineSuperOrRedirect( | 2133 inlineSuperOrRedirect(target.resolvedAst, compiledArguments, |
| 2135 backend.frontend.getResolvedAst(target.declaration), | 2134 constructorResolvedAsts, fieldValues, constructor); |
| 2136 compiledArguments, | |
| 2137 constructorResolvedAsts, | |
| 2138 fieldValues, | |
| 2139 constructor); | |
| 2140 } else { | 2135 } else { |
| 2141 // A field initializer. | 2136 // A field initializer. |
| 2142 ast.SendSet init = link.head; | 2137 ast.SendSet init = link.head; |
| 2143 Link<ast.Node> arguments = init.arguments; | 2138 Link<ast.Node> arguments = init.arguments; |
| 2144 assert(!arguments.isEmpty && arguments.tail.isEmpty); | 2139 assert(!arguments.isEmpty && arguments.tail.isEmpty); |
| 2145 inlinedFrom(resolvedAst, () { | 2140 inlinedFrom(resolvedAst, () { |
| 2146 visit(arguments.head); | 2141 visit(arguments.head); |
| 2147 }); | 2142 }); |
| 2148 fieldValues[elements[init]] = pop(); | 2143 fieldValues[elements[init]] = pop(); |
| 2149 } | 2144 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2162 FunctionElement target = superClass.lookupDefaultConstructor(); | 2157 FunctionElement target = superClass.lookupDefaultConstructor(); |
| 2163 if (target == null) { | 2158 if (target == null) { |
| 2164 reporter.internalError( | 2159 reporter.internalError( |
| 2165 superClass, "No default constructor available."); | 2160 superClass, "No default constructor available."); |
| 2166 } | 2161 } |
| 2167 List<HInstruction> arguments = CallStructure.NO_ARGS.makeArgumentsList( | 2162 List<HInstruction> arguments = CallStructure.NO_ARGS.makeArgumentsList( |
| 2168 const Link<ast.Node>(), | 2163 const Link<ast.Node>(), |
| 2169 target.implementation, | 2164 target.implementation, |
| 2170 null, | 2165 null, |
| 2171 handleConstantForOptionalParameter); | 2166 handleConstantForOptionalParameter); |
| 2172 inlineSuperOrRedirect( | 2167 inlineSuperOrRedirect(target.resolvedAst, arguments, |
| 2173 backend.frontend.getResolvedAst(target.declaration), | 2168 constructorResolvedAsts, fieldValues, constructor); |
| 2174 arguments, | |
| 2175 constructorResolvedAsts, | |
| 2176 fieldValues, | |
| 2177 constructor); | |
| 2178 } | 2169 } |
| 2179 } | 2170 } |
| 2180 } | 2171 } |
| 2181 | 2172 |
| 2182 /** | 2173 /** |
| 2183 * Run through the fields of [cls] and add their potential | 2174 * Run through the fields of [cls] and add their potential |
| 2184 * initializers. | 2175 * initializers. |
| 2185 * | 2176 * |
| 2186 * Invariant: [classElement] must be an implementation element. | 2177 * Invariant: [classElement] must be an implementation element. |
| 2187 */ | 2178 */ |
| 2188 void buildFieldInitializers( | 2179 void buildFieldInitializers( |
| 2189 ClassElement classElement, Map<Element, HInstruction> fieldValues) { | 2180 ClassElement classElement, Map<Element, HInstruction> fieldValues) { |
| 2190 assert(invariant(classElement, classElement.isImplementation)); | 2181 assert(invariant(classElement, classElement.isImplementation)); |
| 2191 classElement.forEachInstanceField( | 2182 classElement.forEachInstanceField( |
| 2192 (ClassElement enclosingClass, FieldElement member) { | 2183 (ClassElement enclosingClass, FieldElement member) { |
| 2193 if (compiler.elementHasCompileTimeError(member)) return; | 2184 if (compiler.elementHasCompileTimeError(member)) return; |
| 2194 reporter.withCurrentElement(member, () { | 2185 reporter.withCurrentElement(member, () { |
| 2195 ResolvedAst fieldResolvedAst = backend.frontend.getResolvedAst(member); | 2186 ResolvedAst fieldResolvedAst = member.resolvedAst; |
| 2196 ast.Node node = fieldResolvedAst.node; | 2187 ast.Node node = fieldResolvedAst.node; |
| 2197 ast.Expression initializer = fieldResolvedAst.body; | 2188 ast.Expression initializer = fieldResolvedAst.body; |
| 2198 if (initializer == null) { | 2189 if (initializer == null) { |
| 2199 // Unassigned fields of native classes are not initialized to | 2190 // Unassigned fields of native classes are not initialized to |
| 2200 // prevent overwriting pre-initialized native properties. | 2191 // prevent overwriting pre-initialized native properties. |
| 2201 if (!backend.isNativeOrExtendsNative(classElement)) { | 2192 if (!backend.isNativeOrExtendsNative(classElement)) { |
| 2202 fieldValues[member] = graph.addConstantNull(compiler); | 2193 fieldValues[member] = graph.addConstantNull(compiler); |
| 2203 } | 2194 } |
| 2204 } else { | 2195 } else { |
| 2205 ast.Node right = initializer; | 2196 ast.Node right = initializer; |
| (...skipping 6400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8606 const _LoopTypeVisitor(); | 8597 const _LoopTypeVisitor(); |
| 8607 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8598 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
| 8608 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8599 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
| 8609 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8600 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
| 8610 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8601 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
| 8611 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8602 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
| 8612 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8603 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
| 8613 int visitSwitchStatement(ast.SwitchStatement node) => | 8604 int visitSwitchStatement(ast.SwitchStatement node) => |
| 8614 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8605 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
| 8615 } | 8606 } |
| OLD | NEW |