| 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 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 if (function.name == '==') { | 455 if (function.name == '==') { |
| 456 if (function.enclosingClass != commonElements.objectClass && | 456 if (function.enclosingClass != commonElements.objectClass && |
| 457 providedArguments[1].canBeNull()) { | 457 providedArguments[1].canBeNull()) { |
| 458 return false; | 458 return false; |
| 459 } | 459 } |
| 460 } | 460 } |
| 461 | 461 |
| 462 // Generative constructors of native classes should not be called directly | 462 // Generative constructors of native classes should not be called directly |
| 463 // and have an extra argument that causes problems with inlining. | 463 // and have an extra argument that causes problems with inlining. |
| 464 if (function.isGenerativeConstructor && | 464 if (function.isGenerativeConstructor && |
| 465 backend.isNativeOrExtendsNative(function.enclosingClass)) { | 465 backend.nativeData.isNativeOrExtendsNative(function.enclosingClass)) { |
| 466 return false; | 466 return false; |
| 467 } | 467 } |
| 468 | 468 |
| 469 // A generative constructor body is not seen by global analysis, | 469 // A generative constructor body is not seen by global analysis, |
| 470 // so we should not query for its type. | 470 // so we should not query for its type. |
| 471 if (!function.isGenerativeConstructorBody) { | 471 if (!function.isGenerativeConstructorBody) { |
| 472 if (inferenceResults.resultOf(function).throwsAlways) { | 472 if (inferenceResults.resultOf(function).throwsAlways) { |
| 473 isReachable = false; | 473 isReachable = false; |
| 474 return false; | 474 return false; |
| 475 } | 475 } |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 assert(invariant(classElement, classElement.isImplementation)); | 1137 assert(invariant(classElement, classElement.isImplementation)); |
| 1138 classElement.forEachInstanceField( | 1138 classElement.forEachInstanceField( |
| 1139 (ClassElement enclosingClass, FieldElement member) { | 1139 (ClassElement enclosingClass, FieldElement member) { |
| 1140 if (compiler.elementHasCompileTimeError(member)) return; | 1140 if (compiler.elementHasCompileTimeError(member)) return; |
| 1141 reporter.withCurrentElement(member, () { | 1141 reporter.withCurrentElement(member, () { |
| 1142 ResolvedAst fieldResolvedAst = member.resolvedAst; | 1142 ResolvedAst fieldResolvedAst = member.resolvedAst; |
| 1143 ast.Expression initializer = fieldResolvedAst.body; | 1143 ast.Expression initializer = fieldResolvedAst.body; |
| 1144 if (initializer == null) { | 1144 if (initializer == null) { |
| 1145 // Unassigned fields of native classes are not initialized to | 1145 // Unassigned fields of native classes are not initialized to |
| 1146 // prevent overwriting pre-initialized native properties. | 1146 // prevent overwriting pre-initialized native properties. |
| 1147 if (!backend.isNativeOrExtendsNative(classElement)) { | 1147 if (!backend.nativeData.isNativeOrExtendsNative(classElement)) { |
| 1148 fieldValues[member] = graph.addConstantNull(closedWorld); | 1148 fieldValues[member] = graph.addConstantNull(closedWorld); |
| 1149 } | 1149 } |
| 1150 } else { | 1150 } else { |
| 1151 ast.Node right = initializer; | 1151 ast.Node right = initializer; |
| 1152 ResolvedAst savedResolvedAst = resolvedAst; | 1152 ResolvedAst savedResolvedAst = resolvedAst; |
| 1153 resolvedAst = fieldResolvedAst; | 1153 resolvedAst = fieldResolvedAst; |
| 1154 final oldElementInferenceResults = elementInferenceResults; | 1154 final oldElementInferenceResults = elementInferenceResults; |
| 1155 elementInferenceResults = inferenceResults.resultOf(member); | 1155 elementInferenceResults = inferenceResults.resultOf(member); |
| 1156 // In case the field initializer uses closures, run the | 1156 // In case the field initializer uses closures, run the |
| 1157 // closure to class mapper. | 1157 // closure to class mapper. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1172 * current constructor and super constructors or constructors redirected | 1172 * current constructor and super constructors or constructors redirected |
| 1173 * to, starting from the current constructor. | 1173 * to, starting from the current constructor. |
| 1174 * - Call the constructor bodies, starting from the constructor(s) in the | 1174 * - Call the constructor bodies, starting from the constructor(s) in the |
| 1175 * super class(es). | 1175 * super class(es). |
| 1176 */ | 1176 */ |
| 1177 HGraph buildFactory(ResolvedAst resolvedAst) { | 1177 HGraph buildFactory(ResolvedAst resolvedAst) { |
| 1178 ConstructorElement functionElement = resolvedAst.element; | 1178 ConstructorElement functionElement = resolvedAst.element; |
| 1179 functionElement = functionElement.implementation; | 1179 functionElement = functionElement.implementation; |
| 1180 ClassElement classElement = functionElement.enclosingClass.implementation; | 1180 ClassElement classElement = functionElement.enclosingClass.implementation; |
| 1181 bool isNativeUpgradeFactory = | 1181 bool isNativeUpgradeFactory = |
| 1182 backend.isNativeOrExtendsNative(classElement) && | 1182 backend.nativeData.isNativeOrExtendsNative(classElement) && |
| 1183 !backend.isJsInterop(classElement); | 1183 !backend.isJsInterop(classElement); |
| 1184 ast.FunctionExpression function; | 1184 ast.FunctionExpression function; |
| 1185 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 1185 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 1186 function = resolvedAst.node; | 1186 function = resolvedAst.node; |
| 1187 } | 1187 } |
| 1188 | 1188 |
| 1189 // Note that constructors (like any other static function) do not need | 1189 // Note that constructors (like any other static function) do not need |
| 1190 // to deal with optional arguments. It is the callers job to provide all | 1190 // to deal with optional arguments. It is the callers job to provide all |
| 1191 // arguments as if they were positional. | 1191 // arguments as if they were positional. |
| 1192 | 1192 |
| (...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3399 // calling [makeStaticArgumentList]. | 3399 // calling [makeStaticArgumentList]. |
| 3400 constructorImplementation = constructor.implementation; | 3400 constructorImplementation = constructor.implementation; |
| 3401 if (constructorImplementation.isMalformed || | 3401 if (constructorImplementation.isMalformed || |
| 3402 !callStructure.signatureApplies(constructorImplementation.type)) { | 3402 !callStructure.signatureApplies(constructorImplementation.type)) { |
| 3403 generateWrongArgumentCountError(send, constructor, send.arguments); | 3403 generateWrongArgumentCountError(send, constructor, send.arguments); |
| 3404 return; | 3404 return; |
| 3405 } | 3405 } |
| 3406 | 3406 |
| 3407 List<HInstruction> inputs = <HInstruction>[]; | 3407 List<HInstruction> inputs = <HInstruction>[]; |
| 3408 if (constructor.isGenerativeConstructor && | 3408 if (constructor.isGenerativeConstructor && |
| 3409 backend.isNativeOrExtendsNative(constructor.enclosingClass) && | 3409 backend.nativeData |
| 3410 .isNativeOrExtendsNative(constructor.enclosingClass) && |
| 3410 !backend.isJsInterop(constructor)) { | 3411 !backend.isJsInterop(constructor)) { |
| 3411 // Native class generative constructors take a pre-constructed object. | 3412 // Native class generative constructors take a pre-constructed object. |
| 3412 inputs.add(graph.addConstantNull(closedWorld)); | 3413 inputs.add(graph.addConstantNull(closedWorld)); |
| 3413 } | 3414 } |
| 3414 inputs.addAll(makeStaticArgumentList( | 3415 inputs.addAll(makeStaticArgumentList( |
| 3415 callStructure, send.arguments, constructorImplementation)); | 3416 callStructure, send.arguments, constructorImplementation)); |
| 3416 | 3417 |
| 3417 TypeMask elementType = computeType(constructor); | 3418 TypeMask elementType = computeType(constructor); |
| 3418 if (isFixedListConstructorCall) { | 3419 if (isFixedListConstructorCall) { |
| 3419 if (!inputs[0].isNumber(closedWorld)) { | 3420 if (!inputs[0].isNumber(closedWorld)) { |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3958 return closedWorld.isSubtypeOf( | 3959 return closedWorld.isSubtypeOf( |
| 3959 element.enclosingClass, helpers.jsMutableIndexableClass); | 3960 element.enclosingClass, helpers.jsMutableIndexableClass); |
| 3960 } else { | 3961 } else { |
| 3961 return false; | 3962 return false; |
| 3962 } | 3963 } |
| 3963 } | 3964 } |
| 3964 | 3965 |
| 3965 bool isOptimizableOperation(Selector selector, Element element) { | 3966 bool isOptimizableOperation(Selector selector, Element element) { |
| 3966 ClassElement cls = element.enclosingClass; | 3967 ClassElement cls = element.enclosingClass; |
| 3967 if (isOptimizableOperationOnIndexable(selector, element)) return true; | 3968 if (isOptimizableOperationOnIndexable(selector, element)) return true; |
| 3968 if (!backend.interceptedClasses.contains(cls)) return false; | 3969 if (!backend.interceptorData.interceptedClasses.contains(cls)) |
| 3970 return false; |
| 3969 if (selector.isOperator) return true; | 3971 if (selector.isOperator) return true; |
| 3970 if (selector.isSetter) return true; | 3972 if (selector.isSetter) return true; |
| 3971 if (selector.isIndex) return true; | 3973 if (selector.isIndex) return true; |
| 3972 if (selector.isIndexSet) return true; | 3974 if (selector.isIndexSet) return true; |
| 3973 if (element == helpers.jsArrayAdd || | 3975 if (element == helpers.jsArrayAdd || |
| 3974 element == helpers.jsArrayRemoveLast || | 3976 element == helpers.jsArrayRemoveLast || |
| 3975 element == helpers.jsStringSplit) { | 3977 element == helpers.jsStringSplit) { |
| 3976 return true; | 3978 return true; |
| 3977 } | 3979 } |
| 3978 return false; | 3980 return false; |
| 3979 } | 3981 } |
| 3980 | 3982 |
| 3981 MemberElement element = closedWorld.locateSingleElement(selector, mask); | 3983 MemberElement element = closedWorld.locateSingleElement(selector, mask); |
| 3982 if (element != null && | 3984 if (element != null && |
| 3983 !element.isField && | 3985 !element.isField && |
| 3984 !(element.isGetter && selector.isCall) && | 3986 !(element.isGetter && selector.isCall) && |
| 3985 !(element.isFunction && selector.isGetter) && | 3987 !(element.isFunction && selector.isGetter) && |
| 3986 !isOptimizableOperation(selector, element)) { | 3988 !isOptimizableOperation(selector, element)) { |
| 3987 if (tryInlineMethod(element, selector, mask, arguments, node)) { | 3989 if (tryInlineMethod(element, selector, mask, arguments, node)) { |
| 3988 return; | 3990 return; |
| 3989 } | 3991 } |
| 3990 } | 3992 } |
| 3991 | 3993 |
| 3992 HInstruction receiver = arguments[0]; | 3994 HInstruction receiver = arguments[0]; |
| 3993 List<HInstruction> inputs = <HInstruction>[]; | 3995 List<HInstruction> inputs = <HInstruction>[]; |
| 3994 bool isIntercepted = backend.isInterceptedSelector(selector); | 3996 bool isIntercepted = |
| 3997 backend.interceptorData.isInterceptedSelector(selector); |
| 3995 if (isIntercepted) { | 3998 if (isIntercepted) { |
| 3996 inputs.add(invokeInterceptor(receiver)); | 3999 inputs.add(invokeInterceptor(receiver)); |
| 3997 } | 4000 } |
| 3998 inputs.addAll(arguments); | 4001 inputs.addAll(arguments); |
| 3999 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 4002 TypeMask type = TypeMaskFactory.inferredTypeForSelector( |
| 4000 selector, mask, globalInferenceResults); | 4003 selector, mask, globalInferenceResults); |
| 4001 if (selector.isGetter) { | 4004 if (selector.isGetter) { |
| 4002 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type) | 4005 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type) |
| 4003 ..sourceInformation = sourceInformation); | 4006 ..sourceInformation = sourceInformation); |
| 4004 } else if (selector.isSetter) { | 4007 } else if (selector.isSetter) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4150 } | 4153 } |
| 4151 } | 4154 } |
| 4152 | 4155 |
| 4153 HInstruction buildInvokeSuper( | 4156 HInstruction buildInvokeSuper( |
| 4154 Selector selector, MemberElement element, List<HInstruction> arguments, | 4157 Selector selector, MemberElement element, List<HInstruction> arguments, |
| 4155 [SourceInformation sourceInformation]) { | 4158 [SourceInformation sourceInformation]) { |
| 4156 HInstruction receiver = localsHandler.readThis(); | 4159 HInstruction receiver = localsHandler.readThis(); |
| 4157 // TODO(5346): Try to avoid the need for calling [declaration] before | 4160 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 4158 // creating an [HStatic]. | 4161 // creating an [HStatic]. |
| 4159 List<HInstruction> inputs = <HInstruction>[]; | 4162 List<HInstruction> inputs = <HInstruction>[]; |
| 4160 if (backend.isInterceptedSelector(selector) && | 4163 if (backend.interceptorData.isInterceptedSelector(selector) && |
| 4161 // Fields don't need an interceptor; consider generating HFieldGet/Set | 4164 // Fields don't need an interceptor; consider generating HFieldGet/Set |
| 4162 // instead. | 4165 // instead. |
| 4163 element.kind != ElementKind.FIELD) { | 4166 element.kind != ElementKind.FIELD) { |
| 4164 inputs.add(invokeInterceptor(receiver)); | 4167 inputs.add(invokeInterceptor(receiver)); |
| 4165 } | 4168 } |
| 4166 inputs.add(receiver); | 4169 inputs.add(receiver); |
| 4167 inputs.addAll(arguments); | 4170 inputs.addAll(arguments); |
| 4168 TypeMask type; | 4171 TypeMask type; |
| 4169 if (!element.isGetter && selector.isGetter) { | 4172 if (!element.isGetter && selector.isGetter) { |
| 4170 type = TypeMaskFactory.inferredTypeForElement( | 4173 type = TypeMaskFactory.inferredTypeForElement( |
| (...skipping 2557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6728 this.oldReturnLocal, | 6731 this.oldReturnLocal, |
| 6729 this.oldReturnType, | 6732 this.oldReturnType, |
| 6730 this.oldResolvedAst, | 6733 this.oldResolvedAst, |
| 6731 this.oldStack, | 6734 this.oldStack, |
| 6732 this.oldLocalsHandler, | 6735 this.oldLocalsHandler, |
| 6733 this.inTryStatement, | 6736 this.inTryStatement, |
| 6734 this.allFunctionsCalledOnce, | 6737 this.allFunctionsCalledOnce, |
| 6735 this.oldElementInferenceResults) | 6738 this.oldElementInferenceResults) |
| 6736 : super(function); | 6739 : super(function); |
| 6737 } | 6740 } |
| OLD | NEW |