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 |