| 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 |