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 |