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 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 compiler.options.trustTypeAnnotations; | 1175 compiler.options.trustTypeAnnotations; |
1176 | 1176 |
1177 /// Build the graph for [target]. | 1177 /// Build the graph for [target]. |
1178 HGraph build() { | 1178 HGraph build() { |
1179 assert(invariant(target, target.isImplementation)); | 1179 assert(invariant(target, target.isImplementation)); |
1180 HInstruction.idCounter = 0; | 1180 HInstruction.idCounter = 0; |
1181 // TODO(sigmund): remove `result` and return graph directly, need to ensure | 1181 // TODO(sigmund): remove `result` and return graph directly, need to ensure |
1182 // that it can never be null (see result in buildFactory for instance). | 1182 // that it can never be null (see result in buildFactory for instance). |
1183 var result; | 1183 var result; |
1184 if (target.isGenerativeConstructor) { | 1184 if (target.isGenerativeConstructor) { |
1185 result = buildFactory(target); | 1185 result = buildFactory(resolvedAst); |
1186 } else if (target.isGenerativeConstructorBody || | 1186 } else if (target.isGenerativeConstructorBody || |
1187 target.isFactoryConstructor || | 1187 target.isFactoryConstructor || |
1188 target.isFunction || | 1188 target.isFunction || |
1189 target.isGetter || | 1189 target.isGetter || |
1190 target.isSetter) { | 1190 target.isSetter) { |
1191 result = buildMethod(target); | 1191 result = buildMethod(target); |
1192 } else if (target.isField) { | 1192 } else if (target.isField) { |
1193 if (target.isInstanceMember) { | 1193 if (target.isInstanceMember) { |
1194 assert(compiler.options.enableTypeAssertions); | 1194 assert(compiler.options.enableTypeAssertions); |
1195 result = buildCheckedSetter(target); | 1195 result = buildCheckedSetter(target); |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1532 currentNode); | 1532 currentNode); |
1533 } | 1533 } |
1534 List<HInstruction> compiledArguments = completeSendArgumentsList( | 1534 List<HInstruction> compiledArguments = completeSendArgumentsList( |
1535 function, selector, providedArguments, currentNode); | 1535 function, selector, providedArguments, currentNode); |
1536 enterInlinedMethod(function, functionResolvedAst, compiledArguments, | 1536 enterInlinedMethod(function, functionResolvedAst, compiledArguments, |
1537 instanceType: instanceType); | 1537 instanceType: instanceType); |
1538 inlinedFrom(function, () { | 1538 inlinedFrom(function, () { |
1539 if (!isReachable) { | 1539 if (!isReachable) { |
1540 emitReturn(graph.addConstantNull(compiler), null); | 1540 emitReturn(graph.addConstantNull(compiler), null); |
1541 } else { | 1541 } else { |
1542 doInline(function); | 1542 doInline(functionResolvedAst); |
1543 } | 1543 } |
1544 }); | 1544 }); |
1545 leaveInlinedMethod(); | 1545 leaveInlinedMethod(); |
1546 } | 1546 } |
1547 | 1547 |
1548 if (meetsHardConstraints() && heuristicSayGoodToGo()) { | 1548 if (meetsHardConstraints() && heuristicSayGoodToGo()) { |
1549 doInlining(); | 1549 doInlining(); |
1550 infoReporter?.reportInlined(element, | 1550 infoReporter?.reportInlined(element, |
1551 inliningStack.isEmpty ? target : inliningStack.last.function); | 1551 inliningStack.isEmpty ? target : inliningStack.last.function); |
1552 return true; | 1552 return true; |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 sourceInformationBuilder.buildReturn(sendSet.assignmentOperator))); | 1766 sourceInformationBuilder.buildReturn(sendSet.assignmentOperator))); |
1767 return closeFunction(); | 1767 return closeFunction(); |
1768 } | 1768 } |
1769 | 1769 |
1770 /** | 1770 /** |
1771 * Returns the constructor body associated with the given constructor or | 1771 * Returns the constructor body associated with the given constructor or |
1772 * creates a new constructor body, if none can be found. | 1772 * creates a new constructor body, if none can be found. |
1773 * | 1773 * |
1774 * Returns [:null:] if the constructor does not have a body. | 1774 * Returns [:null:] if the constructor does not have a body. |
1775 */ | 1775 */ |
1776 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 1776 ConstructorBodyElement getConstructorBody( |
| 1777 ResolvedAst constructorResolvedAst) { |
| 1778 ConstructorElement constructor = |
| 1779 constructorResolvedAst.element.implementation; |
1777 assert(constructor.isGenerativeConstructor); | 1780 assert(constructor.isGenerativeConstructor); |
1778 assert(invariant(constructor, constructor.isImplementation)); | 1781 if (constructorResolvedAst.kind != ResolvedAstKind.PARSED) return null; |
1779 if (constructor.isSynthesized) return null; | 1782 |
1780 ast.FunctionExpression node = constructor.node; | 1783 ast.FunctionExpression node = constructorResolvedAst.node; |
1781 // If we know the body doesn't have any code, we don't generate it. | 1784 // If we know the body doesn't have any code, we don't generate it. |
1782 if (!node.hasBody) return null; | 1785 if (!node.hasBody) return null; |
1783 if (node.hasEmptyBody) return null; | 1786 if (node.hasEmptyBody) return null; |
1784 ClassElement classElement = constructor.enclosingClass; | 1787 ClassElement classElement = constructor.enclosingClass; |
1785 ConstructorBodyElement bodyElement; | 1788 ConstructorBodyElement bodyElement; |
1786 classElement.forEachBackendMember((Element backendMember) { | 1789 classElement.forEachBackendMember((Element backendMember) { |
1787 if (backendMember.isGenerativeConstructorBody) { | 1790 if (backendMember.isGenerativeConstructorBody) { |
1788 ConstructorBodyElement body = backendMember; | 1791 ConstructorBodyElement body = backendMember; |
1789 if (body.constructor == constructor) { | 1792 if (body.constructor == constructor) { |
1790 // TODO(kasperl): Find a way of stopping the iteration | 1793 // TODO(kasperl): Find a way of stopping the iteration |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1881 inTryStatement = state.inTryStatement; | 1884 inTryStatement = state.inTryStatement; |
1882 resolvedAst = state.oldResolvedAst; | 1885 resolvedAst = state.oldResolvedAst; |
1883 returnType = state.oldReturnType; | 1886 returnType = state.oldReturnType; |
1884 assert(stack.isEmpty); | 1887 assert(stack.isEmpty); |
1885 stack = state.oldStack; | 1888 stack = state.oldStack; |
1886 } | 1889 } |
1887 | 1890 |
1888 /** | 1891 /** |
1889 * Run this builder on the body of the [function] to be inlined. | 1892 * Run this builder on the body of the [function] to be inlined. |
1890 */ | 1893 */ |
1891 void visitInlinedFunction(FunctionElement function) { | 1894 void visitInlinedFunction(ResolvedAst resolvedAst) { |
1892 potentiallyCheckInlinedParameterTypes(function); | 1895 potentiallyCheckInlinedParameterTypes(resolvedAst.element.implementation); |
1893 | 1896 |
1894 if (function.isGenerativeConstructor) { | 1897 if (resolvedAst.element.isGenerativeConstructor) { |
1895 buildFactory(function); | 1898 buildFactory(resolvedAst); |
1896 } else { | 1899 } else { |
1897 ast.FunctionExpression functionNode = function.node; | 1900 ast.FunctionExpression functionNode = resolvedAst.node; |
1898 functionNode.body.accept(this); | 1901 functionNode.body.accept(this); |
1899 } | 1902 } |
1900 } | 1903 } |
1901 | 1904 |
1902 addInlinedInstantiation(DartType type) { | 1905 addInlinedInstantiation(DartType type) { |
1903 if (type != null) { | 1906 if (type != null) { |
1904 currentInlinedInstantiations.add(type); | 1907 currentInlinedInstantiations.add(type); |
1905 } | 1908 } |
1906 } | 1909 } |
1907 | 1910 |
(...skipping 26 matching lines...) Expand all Loading... |
1934 potentiallyCheckOrTrustType(argument, parameter.type); | 1937 potentiallyCheckOrTrustType(argument, parameter.type); |
1935 }); | 1938 }); |
1936 } | 1939 } |
1937 | 1940 |
1938 /** | 1941 /** |
1939 * Documentation wanted -- johnniwinther | 1942 * Documentation wanted -- johnniwinther |
1940 * | 1943 * |
1941 * Invariant: [constructors] must contain only implementation elements. | 1944 * Invariant: [constructors] must contain only implementation elements. |
1942 */ | 1945 */ |
1943 void inlineSuperOrRedirect( | 1946 void inlineSuperOrRedirect( |
1944 ConstructorElement callee, | 1947 ResolvedAst constructorRecolvedAst, |
1945 List<HInstruction> compiledArguments, | 1948 List<HInstruction> compiledArguments, |
1946 List<FunctionElement> constructors, | 1949 List<ResolvedAst> constructorResolvedAsts, |
1947 Map<Element, HInstruction> fieldValues, | 1950 Map<Element, HInstruction> fieldValues, |
1948 FunctionElement caller) { | 1951 FunctionElement caller) { |
1949 callee = callee.implementation; | 1952 ConstructorElement callee = constructorRecolvedAst.element.implementation; |
1950 reporter.withCurrentElement(callee, () { | 1953 reporter.withCurrentElement(callee, () { |
1951 constructors.add(callee); | 1954 constructorResolvedAsts.add(constructorRecolvedAst); |
1952 ClassElement enclosingClass = callee.enclosingClass; | 1955 ClassElement enclosingClass = callee.enclosingClass; |
1953 if (backend.classNeedsRti(enclosingClass)) { | 1956 if (backend.classNeedsRti(enclosingClass)) { |
1954 // If [enclosingClass] needs RTI, we have to give a value to its | 1957 // If [enclosingClass] needs RTI, we have to give a value to its |
1955 // type parameters. | 1958 // type parameters. |
1956 ClassElement currentClass = caller.enclosingClass; | 1959 ClassElement currentClass = caller.enclosingClass; |
1957 // For a super constructor call, the type is the supertype of | 1960 // For a super constructor call, the type is the supertype of |
1958 // [currentClass]. For a redirecting constructor, the type is | 1961 // [currentClass]. For a redirecting constructor, the type is |
1959 // the current type. [InterfaceType.asInstanceOf] takes care | 1962 // the current type. [InterfaceType.asInstanceOf] takes care |
1960 // of both. | 1963 // of both. |
1961 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); | 1964 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2012 // Build the initializers in the context of the new constructor. | 2015 // Build the initializers in the context of the new constructor. |
2013 ResolvedAst oldResolvedAst = resolvedAst; | 2016 ResolvedAst oldResolvedAst = resolvedAst; |
2014 resolvedAst = backend.frontend.getResolvedAst(callee); | 2017 resolvedAst = backend.frontend.getResolvedAst(callee); |
2015 ClosureClassMap oldClosureData = localsHandler.closureData; | 2018 ClosureClassMap oldClosureData = localsHandler.closureData; |
2016 ClosureClassMap newClosureData = compiler.closureToClassMapper | 2019 ClosureClassMap newClosureData = compiler.closureToClassMapper |
2017 .computeClosureToClassMapping(resolvedAst); | 2020 .computeClosureToClassMapping(resolvedAst); |
2018 localsHandler.closureData = newClosureData; | 2021 localsHandler.closureData = newClosureData; |
2019 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 2022 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
2020 localsHandler.enterScope(resolvedAst.node, callee); | 2023 localsHandler.enterScope(resolvedAst.node, callee); |
2021 } | 2024 } |
2022 buildInitializers(callee, constructors, fieldValues); | 2025 buildInitializers(callee, constructorResolvedAsts, fieldValues); |
2023 localsHandler.closureData = oldClosureData; | 2026 localsHandler.closureData = oldClosureData; |
2024 resolvedAst = oldResolvedAst; | 2027 resolvedAst = oldResolvedAst; |
2025 }); | 2028 }); |
2026 } | 2029 } |
2027 | 2030 |
2028 void buildInitializers( | 2031 void buildInitializers( |
2029 ConstructorElement constructor, | 2032 ConstructorElement constructor, |
2030 List<FunctionElement> constructors, | 2033 List<ResolvedAst> constructorResolvedAsts, |
2031 Map<Element, HInstruction> fieldValues) { | 2034 Map<Element, HInstruction> fieldValues) { |
2032 assert(invariant( | 2035 assert(invariant( |
2033 constructor, resolvedAst.element == constructor.declaration, | 2036 constructor, resolvedAst.element == constructor.declaration, |
2034 message: "Expected ResolvedAst for $constructor, found $resolvedAst")); | 2037 message: "Expected ResolvedAst for $constructor, found $resolvedAst")); |
2035 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 2038 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
2036 buildParsedInitializers(constructor, constructors, fieldValues); | 2039 buildParsedInitializers( |
| 2040 constructor, constructorResolvedAsts, fieldValues); |
2037 } else { | 2041 } else { |
2038 buildSynthesizedConstructorInitializers( | 2042 buildSynthesizedConstructorInitializers( |
2039 constructor, constructors, fieldValues); | 2043 constructor, constructorResolvedAsts, fieldValues); |
2040 } | 2044 } |
2041 } | 2045 } |
2042 | 2046 |
2043 void buildSynthesizedConstructorInitializers( | 2047 void buildSynthesizedConstructorInitializers( |
2044 ConstructorElement constructor, | 2048 ConstructorElement constructor, |
2045 List<FunctionElement> constructors, | 2049 List<ResolvedAst> constructorResolvedAsts, |
2046 Map<Element, HInstruction> fieldValues) { | 2050 Map<Element, HInstruction> fieldValues) { |
2047 assert(invariant(constructor, constructor.isSynthesized)); | 2051 assert(invariant(constructor, constructor.isSynthesized, |
| 2052 message: "Unexpected unsynthesized constructor: $constructor")); |
2048 List<HInstruction> arguments = <HInstruction>[]; | 2053 List<HInstruction> arguments = <HInstruction>[]; |
2049 HInstruction compileArgument(ParameterElement parameter) { | 2054 HInstruction compileArgument(ParameterElement parameter) { |
2050 return localsHandler.readLocal(parameter); | 2055 return localsHandler.readLocal(parameter); |
2051 } | 2056 } |
2052 | 2057 |
2053 Element target = constructor.definingConstructor.implementation; | 2058 Element target = constructor.definingConstructor.implementation; |
2054 bool match = !target.isMalformed && | 2059 bool match = !target.isMalformed && |
2055 CallStructure.addForwardingElementArgumentsToList( | 2060 CallStructure.addForwardingElementArgumentsToList( |
2056 constructor, | 2061 constructor, |
2057 arguments, | 2062 arguments, |
2058 target, | 2063 target, |
2059 compileArgument, | 2064 compileArgument, |
2060 handleConstantForOptionalParameter); | 2065 handleConstantForOptionalParameter); |
2061 if (!match) { | 2066 if (!match) { |
2062 if (compiler.elementHasCompileTimeError(constructor)) { | 2067 if (compiler.elementHasCompileTimeError(constructor)) { |
2063 return; | 2068 return; |
2064 } | 2069 } |
2065 // If this fails, the selector we constructed for the call to a | 2070 // If this fails, the selector we constructed for the call to a |
2066 // forwarding constructor in a mixin application did not match the | 2071 // forwarding constructor in a mixin application did not match the |
2067 // constructor (which, for example, may happen when the libraries are | 2072 // constructor (which, for example, may happen when the libraries are |
2068 // not compatible for private names, see issue 20394). | 2073 // not compatible for private names, see issue 20394). |
2069 reporter.internalError( | 2074 reporter.internalError( |
2070 constructor, 'forwarding constructor call does not match'); | 2075 constructor, 'forwarding constructor call does not match'); |
2071 } | 2076 } |
2072 inlineSuperOrRedirect( | 2077 inlineSuperOrRedirect(backend.frontend.getResolvedAst(target), arguments, |
2073 target, arguments, constructors, fieldValues, constructor); | 2078 constructorResolvedAsts, fieldValues, constructor); |
2074 } | 2079 } |
2075 | 2080 |
2076 /** | 2081 /** |
2077 * Run through the initializers and inline all field initializers. Recursively | 2082 * Run through the initializers and inline all field initializers. Recursively |
2078 * inlines super initializers. | 2083 * inlines super initializers. |
2079 * | 2084 * |
2080 * The constructors of the inlined initializers is added to [constructors] | 2085 * The constructors of the inlined initializers is added to [constructors] |
2081 * with sub constructors having a lower index than super constructors. | 2086 * with sub constructors having a lower index than super constructors. |
2082 * | 2087 * |
2083 * Invariant: The [constructor] and elements in [constructors] must all be | 2088 * Invariant: The [constructor] and elements in [constructors] must all be |
2084 * implementation elements. | 2089 * implementation elements. |
2085 */ | 2090 */ |
2086 void buildParsedInitializers( | 2091 void buildParsedInitializers( |
2087 ConstructorElement constructor, | 2092 ConstructorElement constructor, |
2088 List<FunctionElement> constructors, | 2093 List<ResolvedAst> constructorResolvedAsts, |
2089 Map<Element, HInstruction> fieldValues) { | 2094 Map<Element, HInstruction> fieldValues) { |
| 2095 assert( |
| 2096 invariant(constructor, resolvedAst.element == constructor.declaration)); |
2090 assert(invariant(constructor, constructor.isImplementation)); | 2097 assert(invariant(constructor, constructor.isImplementation)); |
2091 assert(invariant(constructor, !constructor.isSynthesized, | 2098 assert(invariant(constructor, !constructor.isSynthesized, |
2092 message: "Unexpected synthesized constructor: $constructor")); | 2099 message: "Unexpected synthesized constructor: $constructor")); |
2093 ast.FunctionExpression functionNode = constructor.node; | 2100 ast.FunctionExpression functionNode = resolvedAst.node; |
2094 | 2101 |
2095 bool foundSuperOrRedirect = false; | 2102 bool foundSuperOrRedirect = false; |
2096 if (functionNode.initializers != null) { | 2103 if (functionNode.initializers != null) { |
2097 Link<ast.Node> initializers = functionNode.initializers.nodes; | 2104 Link<ast.Node> initializers = functionNode.initializers.nodes; |
2098 for (Link<ast.Node> link = initializers; | 2105 for (Link<ast.Node> link = initializers; |
2099 !link.isEmpty; | 2106 !link.isEmpty; |
2100 link = link.tail) { | 2107 link = link.tail) { |
2101 assert(link.head is ast.Send); | 2108 assert(link.head is ast.Send); |
2102 if (link.head is! ast.SendSet) { | 2109 if (link.head is! ast.SendSet) { |
2103 // A super initializer or constructor redirection. | 2110 // A super initializer or constructor redirection. |
2104 foundSuperOrRedirect = true; | 2111 foundSuperOrRedirect = true; |
2105 ast.Send call = link.head; | 2112 ast.Send call = link.head; |
2106 assert(ast.Initializers.isSuperConstructorCall(call) || | 2113 assert(ast.Initializers.isSuperConstructorCall(call) || |
2107 ast.Initializers.isConstructorRedirect(call)); | 2114 ast.Initializers.isConstructorRedirect(call)); |
2108 FunctionElement target = elements[call].implementation; | 2115 FunctionElement target = elements[call].implementation; |
2109 CallStructure callStructure = | 2116 CallStructure callStructure = |
2110 elements.getSelector(call).callStructure; | 2117 elements.getSelector(call).callStructure; |
2111 Link<ast.Node> arguments = call.arguments; | 2118 Link<ast.Node> arguments = call.arguments; |
2112 List<HInstruction> compiledArguments; | 2119 List<HInstruction> compiledArguments; |
2113 inlinedFrom(constructor, () { | 2120 inlinedFrom(constructor, () { |
2114 compiledArguments = | 2121 compiledArguments = |
2115 makeStaticArgumentList(callStructure, arguments, target); | 2122 makeStaticArgumentList(callStructure, arguments, target); |
2116 }); | 2123 }); |
2117 inlineSuperOrRedirect(target, compiledArguments, constructors, | 2124 inlineSuperOrRedirect( |
2118 fieldValues, constructor); | 2125 backend.frontend.getResolvedAst(target.declaration), |
| 2126 compiledArguments, |
| 2127 constructorResolvedAsts, |
| 2128 fieldValues, |
| 2129 constructor); |
2119 } else { | 2130 } else { |
2120 // A field initializer. | 2131 // A field initializer. |
2121 ast.SendSet init = link.head; | 2132 ast.SendSet init = link.head; |
2122 Link<ast.Node> arguments = init.arguments; | 2133 Link<ast.Node> arguments = init.arguments; |
2123 assert(!arguments.isEmpty && arguments.tail.isEmpty); | 2134 assert(!arguments.isEmpty && arguments.tail.isEmpty); |
2124 inlinedFrom(constructor, () { | 2135 inlinedFrom(constructor, () { |
2125 visit(arguments.head); | 2136 visit(arguments.head); |
2126 }); | 2137 }); |
2127 fieldValues[elements[init]] = pop(); | 2138 fieldValues[elements[init]] = pop(); |
2128 } | 2139 } |
(...skipping 13 matching lines...) Expand all Loading... |
2142 if (target == null) { | 2153 if (target == null) { |
2143 reporter.internalError( | 2154 reporter.internalError( |
2144 superClass, "No default constructor available."); | 2155 superClass, "No default constructor available."); |
2145 } | 2156 } |
2146 List<HInstruction> arguments = CallStructure.NO_ARGS.makeArgumentsList( | 2157 List<HInstruction> arguments = CallStructure.NO_ARGS.makeArgumentsList( |
2147 const Link<ast.Node>(), | 2158 const Link<ast.Node>(), |
2148 target.implementation, | 2159 target.implementation, |
2149 null, | 2160 null, |
2150 handleConstantForOptionalParameter); | 2161 handleConstantForOptionalParameter); |
2151 inlineSuperOrRedirect( | 2162 inlineSuperOrRedirect( |
2152 target, arguments, constructors, fieldValues, constructor); | 2163 backend.frontend.getResolvedAst(target.declaration), |
| 2164 arguments, |
| 2165 constructorResolvedAsts, |
| 2166 fieldValues, |
| 2167 constructor); |
2153 } | 2168 } |
2154 } | 2169 } |
2155 } | 2170 } |
2156 | 2171 |
2157 /** | 2172 /** |
2158 * Run through the fields of [cls] and add their potential | 2173 * Run through the fields of [cls] and add their potential |
2159 * initializers. | 2174 * initializers. |
2160 * | 2175 * |
2161 * Invariant: [classElement] must be an implementation element. | 2176 * Invariant: [classElement] must be an implementation element. |
2162 */ | 2177 */ |
2163 void buildFieldInitializers( | 2178 void buildFieldInitializers( |
2164 ClassElement classElement, Map<Element, HInstruction> fieldValues) { | 2179 ClassElement classElement, Map<Element, HInstruction> fieldValues) { |
2165 assert(invariant(classElement, classElement.isImplementation)); | 2180 assert(invariant(classElement, classElement.isImplementation)); |
2166 classElement.forEachInstanceField( | 2181 classElement.forEachInstanceField( |
2167 (ClassElement enclosingClass, VariableElement member) { | 2182 (ClassElement enclosingClass, FieldElement member) { |
2168 if (compiler.elementHasCompileTimeError(member)) return; | 2183 if (compiler.elementHasCompileTimeError(member)) return; |
2169 reporter.withCurrentElement(member, () { | 2184 reporter.withCurrentElement(member, () { |
2170 ast.Node node = member.node; | 2185 ResolvedAst fieldResolvedAst = backend.frontend.getResolvedAst(member); |
2171 ast.Expression initializer = member.initializer; | 2186 ast.Node node = fieldResolvedAst.node; |
| 2187 ast.Expression initializer = fieldResolvedAst.body; |
2172 if (initializer == null) { | 2188 if (initializer == null) { |
2173 // Unassigned fields of native classes are not initialized to | 2189 // Unassigned fields of native classes are not initialized to |
2174 // prevent overwriting pre-initialized native properties. | 2190 // prevent overwriting pre-initialized native properties. |
2175 if (!backend.isNativeOrExtendsNative(classElement)) { | 2191 if (!backend.isNativeOrExtendsNative(classElement)) { |
2176 fieldValues[member] = graph.addConstantNull(compiler); | 2192 fieldValues[member] = graph.addConstantNull(compiler); |
2177 } | 2193 } |
2178 } else { | 2194 } else { |
2179 ast.Node right = initializer; | 2195 ast.Node right = initializer; |
2180 ResolvedAst savedResolvedAst = resolvedAst; | 2196 ResolvedAst savedResolvedAst = resolvedAst; |
2181 resolvedAst = backend.frontend.getResolvedAst(member); | 2197 resolvedAst = fieldResolvedAst; |
2182 // In case the field initializer uses closures, run the | 2198 // In case the field initializer uses closures, run the |
2183 // closure to class mapper. | 2199 // closure to class mapper. |
2184 compiler.closureToClassMapper | 2200 compiler.closureToClassMapper |
2185 .computeClosureToClassMapping(resolvedAst); | 2201 .computeClosureToClassMapping(resolvedAst); |
2186 inlinedFrom(member, () => right.accept(this)); | 2202 inlinedFrom(member, () => right.accept(this)); |
2187 resolvedAst = savedResolvedAst; | 2203 resolvedAst = savedResolvedAst; |
2188 fieldValues[member] = pop(); | 2204 fieldValues[member] = pop(); |
2189 } | 2205 } |
2190 }); | 2206 }); |
2191 }); | 2207 }); |
2192 } | 2208 } |
2193 | 2209 |
2194 /** | 2210 /** |
2195 * Build the factory function corresponding to the constructor | 2211 * Build the factory function corresponding to the constructor |
2196 * [functionElement]: | 2212 * [functionElement]: |
2197 * - Initialize fields with the values of the field initializers of the | 2213 * - Initialize fields with the values of the field initializers of the |
2198 * current constructor and super constructors or constructors redirected | 2214 * current constructor and super constructors or constructors redirected |
2199 * to, starting from the current constructor. | 2215 * to, starting from the current constructor. |
2200 * - Call the constructor bodies, starting from the constructor(s) in the | 2216 * - Call the constructor bodies, starting from the constructor(s) in the |
2201 * super class(es). | 2217 * super class(es). |
2202 */ | 2218 */ |
2203 HGraph buildFactory(ConstructorElement functionElement) { | 2219 HGraph buildFactory(ResolvedAst resolvedAst) { |
| 2220 ConstructorElement functionElement = resolvedAst.element; |
2204 functionElement = functionElement.implementation; | 2221 functionElement = functionElement.implementation; |
2205 ClassElement classElement = functionElement.enclosingClass.implementation; | 2222 ClassElement classElement = functionElement.enclosingClass.implementation; |
2206 bool isNativeUpgradeFactory = | 2223 bool isNativeUpgradeFactory = |
2207 backend.isNativeOrExtendsNative(classElement) && | 2224 backend.isNativeOrExtendsNative(classElement) && |
2208 !backend.isJsInterop(classElement); | 2225 !backend.isJsInterop(classElement); |
2209 ast.FunctionExpression function = functionElement.node; | 2226 ast.FunctionExpression function; |
| 2227 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 2228 function = resolvedAst.node; |
| 2229 } |
| 2230 |
2210 // Note that constructors (like any other static function) do not need | 2231 // Note that constructors (like any other static function) do not need |
2211 // to deal with optional arguments. It is the callers job to provide all | 2232 // to deal with optional arguments. It is the callers job to provide all |
2212 // arguments as if they were positional. | 2233 // arguments as if they were positional. |
2213 | 2234 |
2214 if (inliningStack.isEmpty) { | 2235 if (inliningStack.isEmpty) { |
2215 // The initializer list could contain closures. | 2236 // The initializer list could contain closures. |
2216 openFunction(functionElement, function); | 2237 openFunction(functionElement, function); |
2217 } | 2238 } |
2218 | 2239 |
2219 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); | 2240 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); |
(...skipping 12 matching lines...) Expand all Loading... |
2232 // If the [element] is a field-parameter then | 2253 // If the [element] is a field-parameter then |
2233 // initialize the field element with its value. | 2254 // initialize the field element with its value. |
2234 InitializingFormalElement fieldParameter = parameter; | 2255 InitializingFormalElement fieldParameter = parameter; |
2235 HInstruction parameterValue = localsHandler.readLocal(fieldParameter); | 2256 HInstruction parameterValue = localsHandler.readLocal(fieldParameter); |
2236 fieldValues[fieldParameter.fieldElement] = parameterValue; | 2257 fieldValues[fieldParameter.fieldElement] = parameterValue; |
2237 } | 2258 } |
2238 }); | 2259 }); |
2239 | 2260 |
2240 // Analyze the constructor and all referenced constructors and collect | 2261 // Analyze the constructor and all referenced constructors and collect |
2241 // initializers and constructor bodies. | 2262 // initializers and constructor bodies. |
2242 List<FunctionElement> constructors = <FunctionElement>[functionElement]; | 2263 List<ResolvedAst> constructorResolvedAsts = <ResolvedAst>[resolvedAst]; |
2243 buildInitializers(functionElement, constructors, fieldValues); | 2264 buildInitializers(functionElement, constructorResolvedAsts, fieldValues); |
2244 | 2265 |
2245 // Call the JavaScript constructor with the fields as argument. | 2266 // Call the JavaScript constructor with the fields as argument. |
2246 List<HInstruction> constructorArguments = <HInstruction>[]; | 2267 List<HInstruction> constructorArguments = <HInstruction>[]; |
2247 List<Element> fields = <Element>[]; | 2268 List<Element> fields = <Element>[]; |
2248 | 2269 |
2249 classElement.forEachInstanceField( | 2270 classElement.forEachInstanceField( |
2250 (ClassElement enclosingClass, VariableElement member) { | 2271 (ClassElement enclosingClass, VariableElement member) { |
2251 HInstruction value = fieldValues[member]; | 2272 HInstruction value = fieldValues[member]; |
2252 if (value == null) { | 2273 if (value == null) { |
2253 // Uninitialized native fields are pre-initialized by the native | 2274 // Uninitialized native fields are pre-initialized by the native |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2362 if (source != null && allIndexed && remainingTypeVariables == 0) { | 2383 if (source != null && allIndexed && remainingTypeVariables == 0) { |
2363 copyRuntimeTypeInfo(source, newObject); | 2384 copyRuntimeTypeInfo(source, newObject); |
2364 } else { | 2385 } else { |
2365 newObject = | 2386 newObject = |
2366 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); | 2387 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); |
2367 } | 2388 } |
2368 } | 2389 } |
2369 | 2390 |
2370 // Generate calls to the constructor bodies. | 2391 // Generate calls to the constructor bodies. |
2371 HInstruction interceptor = null; | 2392 HInstruction interceptor = null; |
2372 for (int index = constructors.length - 1; index >= 0; index--) { | 2393 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { |
2373 FunctionElement constructor = constructors[index]; | 2394 ResolvedAst constructorResolvedAst = constructorResolvedAsts[index]; |
2374 assert(invariant(functionElement, constructor.isImplementation)); | 2395 ConstructorBodyElement body = getConstructorBody(constructorResolvedAst); |
2375 ConstructorBodyElement body = getConstructorBody(constructor); | |
2376 if (body == null) continue; | 2396 if (body == null) continue; |
2377 | 2397 |
2378 List bodyCallInputs = <HInstruction>[]; | 2398 List bodyCallInputs = <HInstruction>[]; |
2379 if (isNativeUpgradeFactory) { | 2399 if (isNativeUpgradeFactory) { |
2380 if (interceptor == null) { | 2400 if (interceptor == null) { |
2381 ConstantValue constant = | 2401 ConstantValue constant = |
2382 new InterceptorConstantValue(classElement.thisType); | 2402 new InterceptorConstantValue(classElement.thisType); |
2383 interceptor = graph.addConstant(constant, compiler); | 2403 interceptor = graph.addConstant(constant, compiler); |
2384 } | 2404 } |
2385 bodyCallInputs.add(interceptor); | 2405 bodyCallInputs.add(interceptor); |
2386 } | 2406 } |
2387 bodyCallInputs.add(newObject); | 2407 bodyCallInputs.add(newObject); |
2388 ResolvedAst resolvedAst = backend.frontend.getResolvedAst(constructor); | 2408 ast.Node node = constructorResolvedAst.node; |
2389 ast.Node node = resolvedAst.node; | |
2390 ClosureClassMap parameterClosureData = | 2409 ClosureClassMap parameterClosureData = |
2391 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 2410 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
2392 | 2411 |
2393 FunctionSignature functionSignature = body.functionSignature; | 2412 FunctionSignature functionSignature = body.functionSignature; |
2394 // Provide the parameters to the generative constructor body. | 2413 // Provide the parameters to the generative constructor body. |
2395 functionSignature.orderedForEachParameter((ParameterElement parameter) { | 2414 functionSignature.orderedForEachParameter((ParameterElement parameter) { |
2396 // If [parameter] is boxed, it will be a field in the box passed as the | 2415 // If [parameter] is boxed, it will be a field in the box passed as the |
2397 // last parameter. So no need to directly pass it. | 2416 // last parameter. So no need to directly pass it. |
2398 if (!localsHandler.isBoxed(parameter)) { | 2417 if (!localsHandler.isBoxed(parameter)) { |
2399 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 2418 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
2400 } | 2419 } |
2401 }); | 2420 }); |
2402 | 2421 |
2403 // If there are locals that escape (ie mutated in closures), we | 2422 // If there are locals that escape (ie mutated in closures), we |
2404 // pass the box to the constructor. | 2423 // pass the box to the constructor. |
2405 // The box must be passed before any type variable. | 2424 // The box must be passed before any type variable. |
2406 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; | 2425 ClosureScope scopeData = parameterClosureData.capturingScopes[node]; |
2407 if (scopeData != null) { | 2426 if (scopeData != null) { |
2408 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); | 2427 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); |
2409 } | 2428 } |
2410 | 2429 |
2411 // Type variables arguments must come after the box (if there is one). | 2430 // Type variables arguments must come after the box (if there is one). |
| 2431 ConstructorElement constructor = |
| 2432 constructorResolvedAst.element.implementation; |
2412 ClassElement currentClass = constructor.enclosingClass; | 2433 ClassElement currentClass = constructor.enclosingClass; |
2413 if (backend.classNeedsRti(currentClass)) { | 2434 if (backend.classNeedsRti(currentClass)) { |
2414 // If [currentClass] needs RTI, we add the type variables as | 2435 // If [currentClass] needs RTI, we add the type variables as |
2415 // parameters of the generative constructor body. | 2436 // parameters of the generative constructor body. |
2416 currentClass.typeVariables.forEach((TypeVariableType argument) { | 2437 currentClass.typeVariables.forEach((TypeVariableType argument) { |
2417 // TODO(johnniwinther): Substitute [argument] with | 2438 // TODO(johnniwinther): Substitute [argument] with |
2418 // `localsHandler.substInContext(argument)`. | 2439 // `localsHandler.substInContext(argument)`. |
2419 bodyCallInputs.add(localsHandler | 2440 bodyCallInputs.add(localsHandler |
2420 .readLocal(localsHandler.getTypeVariableAsLocal(argument))); | 2441 .readLocal(localsHandler.getTypeVariableAsLocal(argument))); |
2421 }); | 2442 }); |
(...skipping 5484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7906 instanceType: instanceType); | 7927 instanceType: instanceType); |
7907 } | 7928 } |
7908 | 7929 |
7909 void leaveInlinedMethod() { | 7930 void leaveInlinedMethod() { |
7910 HInstruction result = localsHandler.readLocal(returnLocal); | 7931 HInstruction result = localsHandler.readLocal(returnLocal); |
7911 AstInliningState state = inliningStack.removeLast(); | 7932 AstInliningState state = inliningStack.removeLast(); |
7912 restoreState(state); | 7933 restoreState(state); |
7913 stack.add(result); | 7934 stack.add(result); |
7914 } | 7935 } |
7915 | 7936 |
7916 void doInline(FunctionElement function) { | 7937 void doInline(ResolvedAst resolvedAst) { |
7917 visitInlinedFunction(function); | 7938 visitInlinedFunction(resolvedAst); |
7918 } | 7939 } |
7919 | 7940 |
7920 void emitReturn(HInstruction value, ast.Node node) { | 7941 void emitReturn(HInstruction value, ast.Node node) { |
7921 if (inliningStack.isEmpty) { | 7942 if (inliningStack.isEmpty) { |
7922 closeAndGotoExit( | 7943 closeAndGotoExit( |
7923 new HReturn(value, sourceInformationBuilder.buildReturn(node))); | 7944 new HReturn(value, sourceInformationBuilder.buildReturn(node))); |
7924 } else { | 7945 } else { |
7925 localsHandler.updateLocal(returnLocal, value); | 7946 localsHandler.updateLocal(returnLocal, value); |
7926 } | 7947 } |
7927 } | 7948 } |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8575 const _LoopTypeVisitor(); | 8596 const _LoopTypeVisitor(); |
8576 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8597 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
8577 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8598 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
8578 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8599 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
8579 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8600 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
8580 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8601 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8581 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8602 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8582 int visitSwitchStatement(ast.SwitchStatement node) => | 8603 int visitSwitchStatement(ast.SwitchStatement node) => |
8583 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8604 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
8584 } | 8605 } |
OLD | NEW |