| 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 | 405 |
| 406 /** | 406 /** |
| 407 * Try to inline [element] within the correct context of the builder. The | 407 * Try to inline [element] within the correct context of the builder. The |
| 408 * insertion point is the state of the builder. | 408 * insertion point is the state of the builder. |
| 409 */ | 409 */ |
| 410 bool tryInlineMethod(MethodElement element, Selector selector, TypeMask mask, | 410 bool tryInlineMethod(MethodElement element, Selector selector, TypeMask mask, |
| 411 List<HInstruction> providedArguments, ast.Node currentNode, | 411 List<HInstruction> providedArguments, ast.Node currentNode, |
| 412 {ResolutionInterfaceType instanceType}) { | 412 {ResolutionInterfaceType instanceType}) { |
| 413 registry.registerStaticUse(new StaticUse.inlining(element)); | 413 registry.registerStaticUse(new StaticUse.inlining(element)); |
| 414 | 414 |
| 415 if (backend.nativeData.isJsInterop(element) && | 415 if (backend.nativeData.isJsInteropMember(element) && |
| 416 !element.isFactoryConstructor) { | 416 !element.isFactoryConstructor) { |
| 417 // We only inline factory JavaScript interop constructors. | 417 // We only inline factory JavaScript interop constructors. |
| 418 return false; | 418 return false; |
| 419 } | 419 } |
| 420 | 420 |
| 421 // Ensure that [element] is an implementation element. | 421 // Ensure that [element] is an implementation element. |
| 422 element = element.implementation; | 422 element = element.implementation; |
| 423 | 423 |
| 424 if (compiler.elementHasCompileTimeError(element)) return false; | 424 if (compiler.elementHasCompileTimeError(element)) return false; |
| 425 | 425 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 442 Elements.isStaticOrTopLevel(function) || | 442 Elements.isStaticOrTopLevel(function) || |
| 443 function.isGenerativeConstructorBody, | 443 function.isGenerativeConstructorBody, |
| 444 message: "Missing selector for inlining of $function.")); | 444 message: "Missing selector for inlining of $function.")); |
| 445 if (selector != null) { | 445 if (selector != null) { |
| 446 if (!selector.applies(function)) return false; | 446 if (!selector.applies(function)) return false; |
| 447 if (mask != null && !mask.canHit(function, selector, closedWorld)) { | 447 if (mask != null && !mask.canHit(function, selector, closedWorld)) { |
| 448 return false; | 448 return false; |
| 449 } | 449 } |
| 450 } | 450 } |
| 451 | 451 |
| 452 if (backend.nativeData.isJsInterop(function)) return false; | 452 if (backend.nativeData.isJsInteropMember(function)) return false; |
| 453 | 453 |
| 454 // Don't inline operator== methods if the parameter can be null. | 454 // Don't inline operator== methods if the parameter can be null. |
| 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 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 * Invariant: [functionElement] must be an implementation element. | 686 * Invariant: [functionElement] must be an implementation element. |
| 687 */ | 687 */ |
| 688 HGraph buildMethod(MethodElement functionElement) { | 688 HGraph buildMethod(MethodElement functionElement) { |
| 689 assert(invariant(functionElement, functionElement.isImplementation)); | 689 assert(invariant(functionElement, functionElement.isImplementation)); |
| 690 graph.calledInLoop = closedWorld.isCalledInLoop(functionElement); | 690 graph.calledInLoop = closedWorld.isCalledInLoop(functionElement); |
| 691 ast.FunctionExpression function = resolvedAst.node; | 691 ast.FunctionExpression function = resolvedAst.node; |
| 692 assert(function != null); | 692 assert(function != null); |
| 693 assert(elements.getFunctionDefinition(function) != null); | 693 assert(elements.getFunctionDefinition(function) != null); |
| 694 openFunction(functionElement, function); | 694 openFunction(functionElement, function); |
| 695 String name = functionElement.name; | 695 String name = functionElement.name; |
| 696 if (backend.nativeData.isJsInterop(functionElement)) { | 696 if (backend.nativeData.isJsInteropMember(functionElement)) { |
| 697 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), | 697 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), |
| 698 sourceInformationBuilder.buildGeneric(function))); | 698 sourceInformationBuilder.buildGeneric(function))); |
| 699 var value = pop(); | 699 var value = pop(); |
| 700 closeAndGotoExit(new HReturn( | 700 closeAndGotoExit(new HReturn( |
| 701 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 701 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
| 702 return closeFunction(); | 702 return closeFunction(); |
| 703 } | 703 } |
| 704 assert(invariant(functionElement, !function.modifiers.isExternal)); | 704 assert(invariant(functionElement, !function.modifiers.isExternal)); |
| 705 | 705 |
| 706 // If [functionElement] is `operator==` we explicitly add a null check at | 706 // If [functionElement] is `operator==` we explicitly add a null check at |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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.nativeData.isNativeOrExtendsNative(classElement) && | 1182 backend.nativeData.isNativeOrExtendsNative(classElement) && |
| 1183 !backend.nativeData.isJsInterop(classElement); | 1183 !backend.nativeData.isJsInteropClass(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 |
| 1193 if (inliningStack.isEmpty) { | 1193 if (inliningStack.isEmpty) { |
| (...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 HInstruction compileArgument(ast.Node argument) { | 2503 HInstruction compileArgument(ast.Node argument) { |
| 2504 visit(argument); | 2504 visit(argument); |
| 2505 return pop(); | 2505 return pop(); |
| 2506 } | 2506 } |
| 2507 | 2507 |
| 2508 return Elements.makeArgumentsList<HInstruction>( | 2508 return Elements.makeArgumentsList<HInstruction>( |
| 2509 callStructure, | 2509 callStructure, |
| 2510 arguments, | 2510 arguments, |
| 2511 element, | 2511 element, |
| 2512 compileArgument, | 2512 compileArgument, |
| 2513 backend.nativeData.isJsInterop(element) | 2513 backend.nativeData.isJsInteropMember(element) |
| 2514 ? handleConstantForOptionalParameterJsInterop | 2514 ? handleConstantForOptionalParameterJsInterop |
| 2515 : handleConstantForOptionalParameter); | 2515 : handleConstantForOptionalParameter); |
| 2516 } | 2516 } |
| 2517 | 2517 |
| 2518 void addGenericSendArgumentsToList( | 2518 void addGenericSendArgumentsToList( |
| 2519 Link<ast.Node> link, List<HInstruction> list) { | 2519 Link<ast.Node> link, List<HInstruction> list) { |
| 2520 for (; !link.isEmpty; link = link.tail) { | 2520 for (; !link.isEmpty; link = link.tail) { |
| 2521 visit(link.head); | 2521 visit(link.head); |
| 2522 list.add(pop()); | 2522 list.add(pop()); |
| 2523 } | 2523 } |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3397 if (constructorImplementation.isMalformed || | 3397 if (constructorImplementation.isMalformed || |
| 3398 !callStructure.signatureApplies(constructorImplementation.type)) { | 3398 !callStructure.signatureApplies(constructorImplementation.type)) { |
| 3399 generateWrongArgumentCountError(send, constructor, send.arguments); | 3399 generateWrongArgumentCountError(send, constructor, send.arguments); |
| 3400 return; | 3400 return; |
| 3401 } | 3401 } |
| 3402 | 3402 |
| 3403 List<HInstruction> inputs = <HInstruction>[]; | 3403 List<HInstruction> inputs = <HInstruction>[]; |
| 3404 if (constructor.isGenerativeConstructor && | 3404 if (constructor.isGenerativeConstructor && |
| 3405 backend.nativeData | 3405 backend.nativeData |
| 3406 .isNativeOrExtendsNative(constructor.enclosingClass) && | 3406 .isNativeOrExtendsNative(constructor.enclosingClass) && |
| 3407 !backend.nativeData.isJsInterop(constructor)) { | 3407 !backend.nativeData.isJsInteropMember(constructor)) { |
| 3408 // Native class generative constructors take a pre-constructed object. | 3408 // Native class generative constructors take a pre-constructed object. |
| 3409 inputs.add(graph.addConstantNull(closedWorld)); | 3409 inputs.add(graph.addConstantNull(closedWorld)); |
| 3410 } | 3410 } |
| 3411 inputs.addAll(makeStaticArgumentList( | 3411 inputs.addAll(makeStaticArgumentList( |
| 3412 callStructure, send.arguments, constructorImplementation)); | 3412 callStructure, send.arguments, constructorImplementation)); |
| 3413 | 3413 |
| 3414 TypeMask elementType = computeType(constructor); | 3414 TypeMask elementType = computeType(constructor); |
| 3415 if (isFixedListConstructorCall) { | 3415 if (isFixedListConstructorCall) { |
| 3416 if (!inputs[0].isNumber(closedWorld)) { | 3416 if (!inputs[0].isNumber(closedWorld)) { |
| 3417 HTypeConversion conversion = new HTypeConversion( | 3417 HTypeConversion conversion = new HTypeConversion( |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4004 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type) | 4004 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type) |
| 4005 ..sourceInformation = sourceInformation); | 4005 ..sourceInformation = sourceInformation); |
| 4006 } else { | 4006 } else { |
| 4007 push(new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted) | 4007 push(new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted) |
| 4008 ..sourceInformation = sourceInformation); | 4008 ..sourceInformation = sourceInformation); |
| 4009 } | 4009 } |
| 4010 } | 4010 } |
| 4011 | 4011 |
| 4012 HForeignCode invokeJsInteropFunction(MethodElement element, | 4012 HForeignCode invokeJsInteropFunction(MethodElement element, |
| 4013 List<HInstruction> arguments, SourceInformation sourceInformation) { | 4013 List<HInstruction> arguments, SourceInformation sourceInformation) { |
| 4014 assert(backend.nativeData.isJsInterop(element)); | 4014 assert(backend.nativeData.isJsInteropMember(element)); |
| 4015 nativeEmitter.nativeMethods.add(element); | 4015 nativeEmitter.nativeMethods.add(element); |
| 4016 | 4016 |
| 4017 if (element.isFactoryConstructor && | 4017 if (element.isFactoryConstructor && |
| 4018 backend.jsInteropAnalysis | 4018 backend.jsInteropAnalysis |
| 4019 .hasAnonymousAnnotation(element.contextClass)) { | 4019 .hasAnonymousAnnotation(element.contextClass)) { |
| 4020 // Factory constructor that is syntactic sugar for creating a JavaScript | 4020 // Factory constructor that is syntactic sugar for creating a JavaScript |
| 4021 // object literal. | 4021 // object literal. |
| 4022 ConstructorElement constructor = element; | 4022 ConstructorElement constructor = element; |
| 4023 FunctionSignature params = constructor.functionSignature; | 4023 FunctionSignature params = constructor.functionSignature; |
| 4024 int i = 0; | 4024 int i = 0; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4122 return; | 4122 return; |
| 4123 } | 4123 } |
| 4124 | 4124 |
| 4125 if (typeMask == null) { | 4125 if (typeMask == null) { |
| 4126 typeMask = TypeMaskFactory.inferredReturnTypeForElement( | 4126 typeMask = TypeMaskFactory.inferredReturnTypeForElement( |
| 4127 element, globalInferenceResults); | 4127 element, globalInferenceResults); |
| 4128 } | 4128 } |
| 4129 bool targetCanThrow = !closedWorld.getCannotThrow(element); | 4129 bool targetCanThrow = !closedWorld.getCannotThrow(element); |
| 4130 // TODO(5346): Try to avoid the need for calling [declaration] before | 4130 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 4131 var instruction; | 4131 var instruction; |
| 4132 if (backend.nativeData.isJsInterop(element)) { | 4132 if (backend.nativeData.isJsInteropMember(element)) { |
| 4133 instruction = | 4133 instruction = |
| 4134 invokeJsInteropFunction(element, arguments, sourceInformation); | 4134 invokeJsInteropFunction(element, arguments, sourceInformation); |
| 4135 } else { | 4135 } else { |
| 4136 // creating an [HInvokeStatic]. | 4136 // creating an [HInvokeStatic]. |
| 4137 instruction = new HInvokeStatic(element, arguments, typeMask, | 4137 instruction = new HInvokeStatic(element, arguments, typeMask, |
| 4138 targetCanThrow: targetCanThrow) | 4138 targetCanThrow: targetCanThrow) |
| 4139 ..sourceInformation = sourceInformation; | 4139 ..sourceInformation = sourceInformation; |
| 4140 if (currentInlinedInstantiations.isNotEmpty) { | 4140 if (currentInlinedInstantiations.isNotEmpty) { |
| 4141 instruction.instantiatedTypes = | 4141 instruction.instantiatedTypes = |
| 4142 new List<ResolutionDartType>.from(currentInlinedInstantiations); | 4142 new List<ResolutionDartType>.from(currentInlinedInstantiations); |
| (...skipping 2585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6728 this.oldReturnLocal, | 6728 this.oldReturnLocal, |
| 6729 this.oldReturnType, | 6729 this.oldReturnType, |
| 6730 this.oldResolvedAst, | 6730 this.oldResolvedAst, |
| 6731 this.oldStack, | 6731 this.oldStack, |
| 6732 this.oldLocalsHandler, | 6732 this.oldLocalsHandler, |
| 6733 this.inTryStatement, | 6733 this.inTryStatement, |
| 6734 this.allFunctionsCalledOnce, | 6734 this.allFunctionsCalledOnce, |
| 6735 this.oldElementInferenceResults) | 6735 this.oldElementInferenceResults) |
| 6736 : super(function); | 6736 : super(function); |
| 6737 } | 6737 } |
| OLD | NEW |