| 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 @override | 257 @override |
| 258 MemberElement get sourceElement => sourceElementStack.last; | 258 MemberElement get sourceElement => sourceElementStack.last; |
| 259 | 259 |
| 260 /// Helper to retrieve global inference results for [element] with special | 260 /// Helper to retrieve global inference results for [element] with special |
| 261 /// care for `ConstructorBodyElement`s which don't exist at the time the | 261 /// care for `ConstructorBodyElement`s which don't exist at the time the |
| 262 /// global analysis run. | 262 /// global analysis run. |
| 263 /// | 263 /// |
| 264 /// Note: this helper is used selectively. When we know that we are in a | 264 /// Note: this helper is used selectively. When we know that we are in a |
| 265 /// context were we don't expect to see a constructor body element, we | 265 /// context were we don't expect to see a constructor body element, we |
| 266 /// directly fetch the data from the global inference results. | 266 /// directly fetch the data from the global inference results. |
| 267 GlobalTypeInferenceElementResult _resultOf(AstElement element) => | 267 GlobalTypeInferenceElementResult _resultOf(MemberElement element) => |
| 268 inferenceResults.resultOf( | 268 inferenceResults.resultOfMember( |
| 269 element is ConstructorBodyElementX ? element.constructor : element); | 269 element is ConstructorBodyElementX ? element.constructor : element); |
| 270 | 270 |
| 271 /// Build the graph for [target]. | 271 /// Build the graph for [target]. |
| 272 HGraph build() { | 272 HGraph build() { |
| 273 assert(invariant(target, target.isImplementation)); | 273 assert(invariant(target, target.isImplementation)); |
| 274 HInstruction.idCounter = 0; | 274 HInstruction.idCounter = 0; |
| 275 // TODO(sigmund): remove `result` and return graph directly, need to ensure | 275 // TODO(sigmund): remove `result` and return graph directly, need to ensure |
| 276 // that it can never be null (see result in buildFactory for instance). | 276 // that it can never be null (see result in buildFactory for instance). |
| 277 var result; | 277 var result; |
| 278 if (target.isGenerativeConstructor) { | 278 if (target.isGenerativeConstructor) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 // Generative constructors of native classes should not be called directly | 455 // Generative constructors of native classes should not be called directly |
| 456 // and have an extra argument that causes problems with inlining. | 456 // and have an extra argument that causes problems with inlining. |
| 457 if (function.isGenerativeConstructor && | 457 if (function.isGenerativeConstructor && |
| 458 backend.nativeData.isNativeOrExtendsNative(function.enclosingClass)) { | 458 backend.nativeData.isNativeOrExtendsNative(function.enclosingClass)) { |
| 459 return false; | 459 return false; |
| 460 } | 460 } |
| 461 | 461 |
| 462 // A generative constructor body is not seen by global analysis, | 462 // A generative constructor body is not seen by global analysis, |
| 463 // so we should not query for its type. | 463 // so we should not query for its type. |
| 464 if (!function.isGenerativeConstructorBody) { | 464 if (!function.isGenerativeConstructorBody) { |
| 465 if (inferenceResults.resultOf(function).throwsAlways) { | 465 if (inferenceResults.resultOfMember(function).throwsAlways) { |
| 466 isReachable = false; | 466 isReachable = false; |
| 467 return false; | 467 return false; |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 | 470 |
| 471 return true; | 471 return true; |
| 472 } | 472 } |
| 473 | 473 |
| 474 bool doesNotContainCode() { | 474 bool doesNotContainCode() { |
| 475 // A function with size 1 does not contain any code. | 475 // A function with size 1 does not contain any code. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 return false; | 589 return false; |
| 590 } | 590 } |
| 591 | 591 |
| 592 bool get allInlinedFunctionsCalledOnce { | 592 bool get allInlinedFunctionsCalledOnce { |
| 593 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; | 593 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; |
| 594 } | 594 } |
| 595 | 595 |
| 596 bool isFunctionCalledOnce(MethodElement element) { | 596 bool isFunctionCalledOnce(MethodElement element) { |
| 597 // ConstructorBodyElements are not in the type inference graph. | 597 // ConstructorBodyElements are not in the type inference graph. |
| 598 if (element is ConstructorBodyElement) return false; | 598 if (element is ConstructorBodyElement) return false; |
| 599 return inferenceResults.resultOf(element).isCalledOnce; | 599 return inferenceResults.resultOfMember(element).isCalledOnce; |
| 600 } | 600 } |
| 601 | 601 |
| 602 bool isCalledOnce(MethodElement element) { | 602 bool isCalledOnce(MethodElement element) { |
| 603 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element); | 603 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element); |
| 604 } | 604 } |
| 605 | 605 |
| 606 inlinedFrom(ResolvedAst resolvedAst, f()) { | 606 inlinedFrom(ResolvedAst resolvedAst, f()) { |
| 607 MemberElement element = resolvedAst.element; | 607 MemberElement element = resolvedAst.element; |
| 608 assert(element is FunctionElement || element is VariableElement); | 608 assert(element is FunctionElement || element is VariableElement); |
| 609 return reporter.withCurrentElement(element.implementation, () { | 609 return reporter.withCurrentElement(element.implementation, () { |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 if (parameter.isInitializingFormal) { | 961 if (parameter.isInitializingFormal) { |
| 962 InitializingFormalElement fieldParameterElement = parameter; | 962 InitializingFormalElement fieldParameterElement = parameter; |
| 963 fieldValues[fieldParameterElement.fieldElement] = argument; | 963 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 964 } | 964 } |
| 965 }); | 965 }); |
| 966 | 966 |
| 967 // Build the initializers in the context of the new constructor. | 967 // Build the initializers in the context of the new constructor. |
| 968 ResolvedAst oldResolvedAst = resolvedAst; | 968 ResolvedAst oldResolvedAst = resolvedAst; |
| 969 resolvedAst = callee.resolvedAst; | 969 resolvedAst = callee.resolvedAst; |
| 970 final oldElementInferenceResults = elementInferenceResults; | 970 final oldElementInferenceResults = elementInferenceResults; |
| 971 elementInferenceResults = inferenceResults.resultOf(callee); | 971 elementInferenceResults = inferenceResults.resultOfMember(callee); |
| 972 ClosureClassMap oldClosureData = localsHandler.closureData; | 972 ClosureClassMap oldClosureData = localsHandler.closureData; |
| 973 ClosureClassMap newClosureData = | 973 ClosureClassMap newClosureData = |
| 974 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); | 974 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); |
| 975 localsHandler.closureData = newClosureData; | 975 localsHandler.closureData = newClosureData; |
| 976 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 976 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 977 localsHandler.enterScope(resolvedAst.node, callee); | 977 localsHandler.enterScope(resolvedAst.node, callee); |
| 978 } | 978 } |
| 979 buildInitializers(callee, constructorResolvedAsts, fieldValues); | 979 buildInitializers(callee, constructorResolvedAsts, fieldValues); |
| 980 localsHandler.closureData = oldClosureData; | 980 localsHandler.closureData = oldClosureData; |
| 981 resolvedAst = oldResolvedAst; | 981 resolvedAst = oldResolvedAst; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 // Unassigned fields of native classes are not initialized to | 1136 // Unassigned fields of native classes are not initialized to |
| 1137 // prevent overwriting pre-initialized native properties. | 1137 // prevent overwriting pre-initialized native properties. |
| 1138 if (!backend.nativeData.isNativeOrExtendsNative(classElement)) { | 1138 if (!backend.nativeData.isNativeOrExtendsNative(classElement)) { |
| 1139 fieldValues[member] = graph.addConstantNull(closedWorld); | 1139 fieldValues[member] = graph.addConstantNull(closedWorld); |
| 1140 } | 1140 } |
| 1141 } else { | 1141 } else { |
| 1142 ast.Node right = initializer; | 1142 ast.Node right = initializer; |
| 1143 ResolvedAst savedResolvedAst = resolvedAst; | 1143 ResolvedAst savedResolvedAst = resolvedAst; |
| 1144 resolvedAst = fieldResolvedAst; | 1144 resolvedAst = fieldResolvedAst; |
| 1145 final oldElementInferenceResults = elementInferenceResults; | 1145 final oldElementInferenceResults = elementInferenceResults; |
| 1146 elementInferenceResults = inferenceResults.resultOf(member); | 1146 elementInferenceResults = inferenceResults.resultOfMember(member); |
| 1147 // In case the field initializer uses closures, run the | 1147 // In case the field initializer uses closures, run the |
| 1148 // closure to class mapper. | 1148 // closure to class mapper. |
| 1149 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); | 1149 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); |
| 1150 inlinedFrom(fieldResolvedAst, () => right.accept(this)); | 1150 inlinedFrom(fieldResolvedAst, () => right.accept(this)); |
| 1151 resolvedAst = savedResolvedAst; | 1151 resolvedAst = savedResolvedAst; |
| 1152 elementInferenceResults = oldElementInferenceResults; | 1152 elementInferenceResults = oldElementInferenceResults; |
| 1153 fieldValues[member] = pop(); | 1153 fieldValues[member] = pop(); |
| 1154 } | 1154 } |
| 1155 }); | 1155 }); |
| 1156 }); | 1156 }); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2089 value, prefix, sourceInformation, compiler, closedWorld); | 2089 value, prefix, sourceInformation, compiler, closedWorld); |
| 2090 } else { | 2090 } else { |
| 2091 instruction = graph.addConstant(value, closedWorld, | 2091 instruction = graph.addConstant(value, closedWorld, |
| 2092 sourceInformation: sourceInformation); | 2092 sourceInformation: sourceInformation); |
| 2093 } | 2093 } |
| 2094 stack.add(instruction); | 2094 stack.add(instruction); |
| 2095 // The inferrer may have found a better type than the constant | 2095 // The inferrer may have found a better type than the constant |
| 2096 // handler in the case of lists, because the constant handler | 2096 // handler in the case of lists, because the constant handler |
| 2097 // does not look at elements in the list. | 2097 // does not look at elements in the list. |
| 2098 TypeMask type = | 2098 TypeMask type = |
| 2099 TypeMaskFactory.inferredTypeForElement(field, globalInferenceResults); | 2099 TypeMaskFactory.inferredTypeForMember(field, globalInferenceResults); |
| 2100 if (!type.containsAll(closedWorld) && !instruction.isConstantNull()) { | 2100 if (!type.containsAll(closedWorld) && !instruction.isConstantNull()) { |
| 2101 // TODO(13429): The inferrer should know that an element | 2101 // TODO(13429): The inferrer should know that an element |
| 2102 // cannot be null. | 2102 // cannot be null. |
| 2103 instruction.instructionType = type.nonNullable(); | 2103 instruction.instructionType = type.nonNullable(); |
| 2104 } | 2104 } |
| 2105 } | 2105 } |
| 2106 | 2106 |
| 2107 @override | 2107 @override |
| 2108 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) { | 2108 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) { |
| 2109 generateIsDeferredLoadedCheckIfNeeded(prefix, node); | 2109 generateIsDeferredLoadedCheckIfNeeded(prefix, node); |
| 2110 } | 2110 } |
| 2111 | 2111 |
| 2112 /// Read a static or top level [field]. | 2112 /// Read a static or top level [field]. |
| 2113 void generateStaticFieldGet(ast.Send node, FieldElement field) { | 2113 void generateStaticFieldGet(ast.Send node, FieldElement field) { |
| 2114 ConstantExpression constant = field.constant; | 2114 ConstantExpression constant = field.constant; |
| 2115 SourceInformation sourceInformation = | 2115 SourceInformation sourceInformation = |
| 2116 sourceInformationBuilder.buildGet(node); | 2116 sourceInformationBuilder.buildGet(node); |
| 2117 if (constant != null) { | 2117 if (constant != null) { |
| 2118 if (!field.isAssignable) { | 2118 if (!field.isAssignable) { |
| 2119 // A static final or const. Get its constant value and inline it if | 2119 // A static final or const. Get its constant value and inline it if |
| 2120 // the value can be compiled eagerly. | 2120 // the value can be compiled eagerly. |
| 2121 generateStaticConstGet(node, field, constant, sourceInformation); | 2121 generateStaticConstGet(node, field, constant, sourceInformation); |
| 2122 } else { | 2122 } else { |
| 2123 // TODO(5346): Try to avoid the need for calling [declaration] before | 2123 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 2124 // creating an [HStatic]. | 2124 // creating an [HStatic]. |
| 2125 HInstruction instruction = new HStatic( | 2125 HInstruction instruction = new HStatic( |
| 2126 field, | 2126 field, |
| 2127 TypeMaskFactory.inferredTypeForElement( | 2127 TypeMaskFactory.inferredTypeForMember( |
| 2128 field, globalInferenceResults)) | 2128 field, globalInferenceResults)) |
| 2129 ..sourceInformation = sourceInformation; | 2129 ..sourceInformation = sourceInformation; |
| 2130 push(instruction); | 2130 push(instruction); |
| 2131 } | 2131 } |
| 2132 } else { | 2132 } else { |
| 2133 HInstruction instruction = new HLazyStatic(field, | 2133 HInstruction instruction = new HLazyStatic(field, |
| 2134 TypeMaskFactory.inferredTypeForElement(field, globalInferenceResults)) | 2134 TypeMaskFactory.inferredTypeForMember(field, globalInferenceResults)) |
| 2135 ..sourceInformation = sourceInformation; | 2135 ..sourceInformation = sourceInformation; |
| 2136 push(instruction); | 2136 push(instruction); |
| 2137 } | 2137 } |
| 2138 } | 2138 } |
| 2139 | 2139 |
| 2140 /// Generate a getter invocation of the static or top level [getter]. | 2140 /// Generate a getter invocation of the static or top level [getter]. |
| 2141 void generateStaticGetterGet(ast.Send node, MethodElement getter) { | 2141 void generateStaticGetterGet(ast.Send node, MethodElement getter) { |
| 2142 SourceInformation sourceInformation = | 2142 SourceInformation sourceInformation = |
| 2143 sourceInformationBuilder.buildGet(node); | 2143 sourceInformationBuilder.buildGet(node); |
| 2144 if (getter.isDeferredLoaderGetter) { | 2144 if (getter.isDeferredLoaderGetter) { |
| (...skipping 2009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4154 if (backend.interceptorData.isInterceptedSelector(selector) && | 4154 if (backend.interceptorData.isInterceptedSelector(selector) && |
| 4155 // Fields don't need an interceptor; consider generating HFieldGet/Set | 4155 // Fields don't need an interceptor; consider generating HFieldGet/Set |
| 4156 // instead. | 4156 // instead. |
| 4157 element.kind != ElementKind.FIELD) { | 4157 element.kind != ElementKind.FIELD) { |
| 4158 inputs.add(invokeInterceptor(receiver)); | 4158 inputs.add(invokeInterceptor(receiver)); |
| 4159 } | 4159 } |
| 4160 inputs.add(receiver); | 4160 inputs.add(receiver); |
| 4161 inputs.addAll(arguments); | 4161 inputs.addAll(arguments); |
| 4162 TypeMask type; | 4162 TypeMask type; |
| 4163 if (!element.isGetter && selector.isGetter) { | 4163 if (!element.isGetter && selector.isGetter) { |
| 4164 type = TypeMaskFactory.inferredTypeForElement( | 4164 type = TypeMaskFactory.inferredTypeForMember( |
| 4165 element, globalInferenceResults); | 4165 element, globalInferenceResults); |
| 4166 } else if (element.isFunction) { | 4166 } else if (element.isFunction) { |
| 4167 type = TypeMaskFactory.inferredReturnTypeForElement( | 4167 type = TypeMaskFactory.inferredReturnTypeForElement( |
| 4168 element, globalInferenceResults); | 4168 element, globalInferenceResults); |
| 4169 } else { | 4169 } else { |
| 4170 type = closedWorld.commonMasks.dynamicType; | 4170 type = closedWorld.commonMasks.dynamicType; |
| 4171 } | 4171 } |
| 4172 HInstruction instruction = new HInvokeSuper(element, currentNonClosureClass, | 4172 HInstruction instruction = new HInvokeSuper(element, currentNonClosureClass, |
| 4173 selector, inputs, type, sourceInformation, | 4173 selector, inputs, type, sourceInformation, |
| 4174 isSetter: selector.isSetter || selector.isIndexSet); | 4174 isSetter: selector.isSetter || selector.isIndexSet); |
| (...skipping 2584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6759 this.oldReturnLocal, | 6759 this.oldReturnLocal, |
| 6760 this.oldReturnType, | 6760 this.oldReturnType, |
| 6761 this.oldResolvedAst, | 6761 this.oldResolvedAst, |
| 6762 this.oldStack, | 6762 this.oldStack, |
| 6763 this.oldLocalsHandler, | 6763 this.oldLocalsHandler, |
| 6764 this.inTryStatement, | 6764 this.inTryStatement, |
| 6765 this.allFunctionsCalledOnce, | 6765 this.allFunctionsCalledOnce, |
| 6766 this.oldElementInferenceResults) | 6766 this.oldElementInferenceResults) |
| 6767 : super(function); | 6767 : super(function); |
| 6768 } | 6768 } |
| OLD | NEW |