| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library simple_types_inferrer; | 5 library simple_types_inferrer; |
| 6 | 6 |
| 7 import '../closure.dart' show ClosureRepresentationInfo; | 7 import '../closure.dart' show ClosureRepresentationInfo; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart' show Identifiers, Selectors; | 9 import '../common/names.dart' show Identifiers, Selectors; |
| 10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 MemberElement analyzedElement, | 81 MemberElement analyzedElement, |
| 82 this.resolvedAst, | 82 this.resolvedAst, |
| 83 this.outermostElement, | 83 this.outermostElement, |
| 84 InferrerEngine inferrer, | 84 InferrerEngine inferrer, |
| 85 this.compiler, | 85 this.compiler, |
| 86 this.locals) | 86 this.locals) |
| 87 : this.analyzedElement = analyzedElement, | 87 : this.analyzedElement = analyzedElement, |
| 88 this.inferrer = inferrer, | 88 this.inferrer = inferrer, |
| 89 this.types = inferrer.types, | 89 this.types = inferrer.types, |
| 90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { | 90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { |
| 91 assert(analyzedElement.isDeclaration); |
| 91 assert(outermostElement != null); | 92 assert(outermostElement != null); |
| 93 assert(outermostElement.isDeclaration); |
| 92 if (locals != null) return; | 94 if (locals != null) return; |
| 93 ast.Node node; | 95 ast.Node node; |
| 94 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 96 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 95 node = resolvedAst.node; | 97 node = resolvedAst.node; |
| 96 } | 98 } |
| 97 FieldInitializationScope fieldScope = | 99 FieldInitializationScope fieldScope = |
| 98 analyzedElement.isGenerativeConstructor | 100 analyzedElement.isGenerativeConstructor |
| 99 ? new FieldInitializationScope(types) | 101 ? new FieldInitializationScope(types) |
| 100 : null; | 102 : null; |
| 101 locals = | 103 locals = |
| 102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); | 104 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); |
| 103 } | 105 } |
| 104 | 106 |
| 105 ElementGraphBuilder(MemberElement element, ResolvedAst resolvedAst, | 107 ElementGraphBuilder(MemberElement element, ResolvedAst resolvedAst, |
| 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) | 108 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) |
| 107 : this.internal(element, resolvedAst, element.memberContext, inferrer, | 109 : this.internal(element, resolvedAst, element.memberContext.declaration, |
| 108 compiler, handler); | 110 inferrer, compiler, handler); |
| 109 | 111 |
| 110 TreeElements get elements => resolvedAst.elements; | 112 TreeElements get elements => resolvedAst.elements; |
| 111 | 113 |
| 112 bool accumulateIsChecks = false; | 114 bool accumulateIsChecks = false; |
| 113 bool conditionIsSimple = false; | 115 bool conditionIsSimple = false; |
| 114 List<ast.Send> isChecks; | 116 List<ast.Send> isChecks; |
| 115 int loopLevel = 0; | 117 int loopLevel = 0; |
| 116 | 118 |
| 117 bool get inLoop => loopLevel > 0; | 119 bool get inLoop => loopLevel > 0; |
| 118 bool get isThisExposed { | 120 bool get isThisExposed { |
| (...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 closureData.forEachCapturedVariable((variable, field) { | 918 closureData.forEachCapturedVariable((variable, field) { |
| 917 locals.setCaptured(variable, field); | 919 locals.setCaptured(variable, field); |
| 918 }); | 920 }); |
| 919 closureData.forEachBoxedVariable((variable, field) { | 921 closureData.forEachBoxedVariable((variable, field) { |
| 920 locals.setCapturedAndBoxed(variable, field); | 922 locals.setCapturedAndBoxed(variable, field); |
| 921 }); | 923 }); |
| 922 if (analyzedElement.isField) { | 924 if (analyzedElement.isField) { |
| 923 return visit(initializer); | 925 return visit(initializer); |
| 924 } | 926 } |
| 925 | 927 |
| 926 MethodElement function = analyzedElement; | 928 MethodElement function = analyzedElement.implementation; |
| 927 FunctionSignature signature = function.functionSignature; | 929 FunctionSignature signature = function.functionSignature; |
| 928 signature.forEachOptionalParameter((FormalElement _element) { | 930 signature.forEachOptionalParameter((FormalElement _element) { |
| 929 ParameterElement element = _element; | 931 ParameterElement parameter = _element; |
| 930 ast.Expression defaultValue = element.initializer; | 932 ast.Expression defaultValue = parameter.initializer; |
| 931 // TODO(25566): The default value of a parameter of a redirecting factory | 933 // TODO(25566): The default value of a parameter of a redirecting factory |
| 932 // constructor comes from the corresponding parameter of the target. | 934 // constructor comes from the corresponding parameter of the target. |
| 933 | 935 |
| 934 // If this is a default value from a different context (because | 936 // If this is a default value from a different context (because |
| 935 // the current function is synthetic, e.g., a constructor from | 937 // the current function is synthetic, e.g., a constructor from |
| 936 // a mixin application), we have to start a new inferrer visitor | 938 // a mixin application), we have to start a new inferrer visitor |
| 937 // with the correct context. | 939 // with the correct context. |
| 938 // TODO(johnniwinther): Remove once function signatures are fixed. | 940 // TODO(johnniwinther): Remove once function signatures are fixed. |
| 939 ElementGraphBuilder visitor = this; | 941 ElementGraphBuilder visitor = this; |
| 940 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; | 942 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(parameter)) return; |
| 941 | 943 |
| 942 FunctionElement declaration = element.functionDeclaration; | 944 FunctionElement declaration = parameter.functionDeclaration.declaration; |
| 943 MethodElement declarationMethod = declaration is LocalFunctionElement | 945 MethodElement declarationMethod = declaration is LocalFunctionElement |
| 944 ? declaration.callMethod | 946 ? declaration.callMethod |
| 945 : declaration; | 947 : declaration; |
| 946 bool needNewContext = declarationMethod != analyzedElement; | 948 bool needNewContext = declarationMethod != analyzedElement; |
| 947 if (needNewContext) { | 949 if (needNewContext) { |
| 948 assert( | 950 assert( |
| 949 declarationMethod is ConstructorElement, | 951 declarationMethod is ConstructorElement, |
| 950 failedAt( | 952 failedAt( |
| 951 element, | 953 parameter, |
| 952 "Unexpected function declaration " | 954 "Unexpected function declaration " |
| 953 "${declarationMethod}, expected ${analyzedElement}.")); | 955 "${declarationMethod}, expected ${analyzedElement}.")); |
| 954 visitor = new ElementGraphBuilder(declarationMethod, | 956 visitor = new ElementGraphBuilder(declarationMethod, |
| 955 element.functionDeclaration.resolvedAst, compiler, inferrer); | 957 parameter.functionDeclaration.resolvedAst, compiler, inferrer); |
| 956 } | 958 } |
| 957 TypeInformation type = | 959 TypeInformation type = |
| 958 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); | 960 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); |
| 959 inferrer.setDefaultTypeOfParameter(element, type); | 961 inferrer.setDefaultTypeOfParameter(parameter, type); |
| 960 }); | 962 }); |
| 961 | 963 |
| 962 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { | 964 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { |
| 963 // Native methods do not have a body, and we currently just say | 965 // Native methods do not have a body, and we currently just say |
| 964 // they return dynamic. | 966 // they return dynamic. |
| 965 return types.dynamicType; | 967 return types.dynamicType; |
| 966 } | 968 } |
| 967 | 969 |
| 968 if (analyzedElement.isGenerativeConstructor) { | 970 if (analyzedElement.isGenerativeConstructor) { |
| 969 isThisExposed = false; | 971 isThisExposed = false; |
| (...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 analyzeSuperConstructorCall(constructor, arguments); | 2310 analyzeSuperConstructorCall(constructor, arguments); |
| 2309 } | 2311 } |
| 2310 } | 2312 } |
| 2311 // If we are looking at a new expression on a forwarding factory, we have to | 2313 // If we are looking at a new expression on a forwarding factory, we have to |
| 2312 // forward the call to the effective target of the factory. | 2314 // forward the call to the effective target of the factory. |
| 2313 // TODO(herhut): Remove the loop once effectiveTarget forwards to patches. | 2315 // TODO(herhut): Remove the loop once effectiveTarget forwards to patches. |
| 2314 while (target.isFactoryConstructor) { | 2316 while (target.isFactoryConstructor) { |
| 2315 if (!target.isRedirectingFactory) break; | 2317 if (!target.isRedirectingFactory) break; |
| 2316 target = target.effectiveTarget.implementation; | 2318 target = target.effectiveTarget.implementation; |
| 2317 } | 2319 } |
| 2318 if (compiler.backend.isForeign(closedWorld.commonElements, target)) { | 2320 if (closedWorld.commonElements.isForeign(target)) { |
| 2319 return handleForeignSend(node, target); | 2321 return handleForeignSend(node, target); |
| 2320 } | 2322 } |
| 2321 Selector selector = elements.getSelector(node); | 2323 Selector selector = elements.getSelector(node); |
| 2322 CallStructure callStructure = selector.callStructure; | 2324 CallStructure callStructure = selector.callStructure; |
| 2323 TypeMask mask = memberData.typeOfSend(node); | 2325 TypeMask mask = memberData.typeOfSend(node); |
| 2324 // In erroneous code the number of arguments in the selector might not | 2326 // In erroneous code the number of arguments in the selector might not |
| 2325 // match the function element. | 2327 // match the function element. |
| 2326 // TODO(polux): return nonNullEmpty and check it doesn'TypeInformation break
anything | 2328 // TODO(polux): return nonNullEmpty and check it doesn'TypeInformation break
anything |
| 2327 if (target.isMalformed || | 2329 if (target.isMalformed || |
| 2328 !callStructure.signatureApplies(target.parameterStructure)) { | 2330 !callStructure.signatureApplies(target.parameterStructure)) { |
| 2329 return types.dynamicType; | 2331 return types.dynamicType; |
| 2330 } | 2332 } |
| 2331 | 2333 |
| 2332 TypeInformation returnType = | 2334 TypeInformation returnType = |
| 2333 handleStaticSend(node, selector, mask, target, arguments); | 2335 handleStaticSend(node, selector, mask, target.declaration, arguments); |
| 2334 if (Elements.isGrowableListConstructorCall( | 2336 if (Elements.isGrowableListConstructorCall( |
| 2335 constructor, node, closedWorld.commonElements)) { | 2337 constructor, node, closedWorld.commonElements)) { |
| 2336 return inferrer.concreteTypes.putIfAbsent( | 2338 return inferrer.concreteTypes.putIfAbsent( |
| 2337 node, | 2339 node, |
| 2338 () => types.allocateList(types.growableListType, node, | 2340 () => types.allocateList(types.growableListType, node, |
| 2339 outermostElement, types.nonNullEmpty(), 0)); | 2341 outermostElement, types.nonNullEmpty(), 0)); |
| 2340 } else if (Elements.isFixedListConstructorCall( | 2342 } else if (Elements.isFixedListConstructorCall( |
| 2341 constructor, node, closedWorld.commonElements) || | 2343 constructor, node, closedWorld.commonElements) || |
| 2342 Elements.isFilledListConstructorCall( | 2344 Elements.isFilledListConstructorCall( |
| 2343 constructor, node, closedWorld.commonElements)) { | 2345 constructor, node, closedWorld.commonElements)) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2396 inferrer.typeOfMember(element), | 2398 inferrer.typeOfMember(element), |
| 2397 outermostElement, | 2399 outermostElement, |
| 2398 arguments, | 2400 arguments, |
| 2399 sideEffects, | 2401 sideEffects, |
| 2400 inLoop); | 2402 inLoop); |
| 2401 } | 2403 } |
| 2402 | 2404 |
| 2403 /// Handle invocation of a top level or static [function]. | 2405 /// Handle invocation of a top level or static [function]. |
| 2404 TypeInformation handleStaticFunctionInvoke( | 2406 TypeInformation handleStaticFunctionInvoke( |
| 2405 ast.Send node, MethodElement function) { | 2407 ast.Send node, MethodElement function) { |
| 2406 if (compiler.backend.isForeign(closedWorld.commonElements, function)) { | 2408 if (closedWorld.commonElements.isForeign(function)) { |
| 2407 return handleForeignSend(node, function); | 2409 return handleForeignSend(node, function); |
| 2408 } | 2410 } |
| 2409 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 2411 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
| 2410 Selector selector = elements.getSelector(node); | 2412 Selector selector = elements.getSelector(node); |
| 2411 TypeMask mask = memberData.typeOfSend(node); | 2413 TypeMask mask = memberData.typeOfSend(node); |
| 2412 return handleStaticSend(node, selector, mask, function, arguments); | 2414 return handleStaticSend(node, selector, mask, function, arguments); |
| 2413 } | 2415 } |
| 2414 | 2416 |
| 2415 /// Handle an static invocation of an unresolved target or with incompatible | 2417 /// Handle an static invocation of an unresolved target or with incompatible |
| 2416 /// arguments to a resolved target. | 2418 /// arguments to a resolved target. |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2716 LocalFunctionElement function, | 2718 LocalFunctionElement function, |
| 2717 ast.NodeList arguments, | 2719 ast.NodeList arguments, |
| 2718 CallStructure callStructure, | 2720 CallStructure callStructure, |
| 2719 _) { | 2721 _) { |
| 2720 analyzeArguments(node.arguments); | 2722 analyzeArguments(node.arguments); |
| 2721 return types.dynamicType; | 2723 return types.dynamicType; |
| 2722 } | 2724 } |
| 2723 | 2725 |
| 2724 TypeInformation handleStaticSend(ast.Node node, Selector selector, | 2726 TypeInformation handleStaticSend(ast.Node node, Selector selector, |
| 2725 TypeMask mask, MemberElement element, ArgumentsTypes arguments) { | 2727 TypeMask mask, MemberElement element, ArgumentsTypes arguments) { |
| 2728 assert(element.isDeclaration); |
| 2726 assert(!element.isFactoryConstructor || | 2729 assert(!element.isFactoryConstructor || |
| 2727 !(element as ConstructorElement).isRedirectingFactory); | 2730 !(element as ConstructorElement).isRedirectingFactory); |
| 2728 // Erroneous elements may be unresolved, for example missing getters. | 2731 // Erroneous elements may be unresolved, for example missing getters. |
| 2729 if (Elements.isUnresolved(element)) return types.dynamicType; | 2732 if (Elements.isUnresolved(element)) return types.dynamicType; |
| 2730 // TODO(herhut): should we follow redirecting constructors here? We would | 2733 // TODO(herhut): should we follow redirecting constructors here? We would |
| 2731 // need to pay attention if the constructor is pointing to an erroneous | 2734 // need to pay attention if the constructor is pointing to an erroneous |
| 2732 // element. | 2735 // element. |
| 2733 return inferrer.registerCalledMember(node, selector, mask, outermostElement, | 2736 return inferrer.registerCalledMember(node, selector, mask, outermostElement, |
| 2734 element, arguments, sideEffects, inLoop); | 2737 element, arguments, sideEffects, inLoop); |
| 2735 } | 2738 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2807 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 2810 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
| 2808 } | 2811 } |
| 2809 | 2812 |
| 2810 void recordReturnType(TypeInformation type) { | 2813 void recordReturnType(TypeInformation type) { |
| 2811 returnType = | 2814 returnType = |
| 2812 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); | 2815 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); |
| 2813 } | 2816 } |
| 2814 | 2817 |
| 2815 TypeInformation synthesizeForwardingCall( | 2818 TypeInformation synthesizeForwardingCall( |
| 2816 Spannable node, ConstructorElement element) { | 2819 Spannable node, ConstructorElement element) { |
| 2817 element = element.implementation; | 2820 assert(element.isDeclaration); |
| 2818 MethodElement function = analyzedElement; | 2821 MethodElement function = analyzedElement.implementation; |
| 2819 FunctionSignature signature = function.functionSignature; | 2822 FunctionSignature signature = function.functionSignature; |
| 2820 FunctionSignature calleeSignature = element.functionSignature; | 2823 FunctionSignature calleeSignature = element.functionSignature; |
| 2821 if (!calleeSignature.isCompatibleWith(signature)) { | 2824 if (!calleeSignature.isCompatibleWith(signature)) { |
| 2822 return types.nonNullEmpty(); | 2825 return types.nonNullEmpty(); |
| 2823 } | 2826 } |
| 2824 | 2827 |
| 2825 List<TypeInformation> unnamed = <TypeInformation>[]; | 2828 List<TypeInformation> unnamed = <TypeInformation>[]; |
| 2826 signature.forEachRequiredParameter((FormalElement _element) { | 2829 signature.forEachRequiredParameter((FormalElement _element) { |
| 2827 ParameterElement element = _element; | 2830 ParameterElement element = _element; |
| 2828 assert(locals.use(element) != null); | 2831 assert(locals.use(element) != null); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2939 Selector moveNextSelector = Selectors.moveNext; | 2942 Selector moveNextSelector = Selectors.moveNext; |
| 2940 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); | 2943 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); |
| 2941 | 2944 |
| 2942 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, | 2945 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, |
| 2943 iteratorMask, expressionType, new ArgumentsTypes.empty()); | 2946 iteratorMask, expressionType, new ArgumentsTypes.empty()); |
| 2944 | 2947 |
| 2945 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 2948 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
| 2946 moveNextSelector, moveNextMask); | 2949 moveNextSelector, moveNextMask); |
| 2947 } | 2950 } |
| 2948 } | 2951 } |
| OLD | NEW |