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 |