| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 List<HInstruction> completeSendArgumentsList( | 1112 List<HInstruction> completeSendArgumentsList( |
| 1113 FunctionElement function, | 1113 FunctionElement function, |
| 1114 Selector selector, | 1114 Selector selector, |
| 1115 List<HInstruction> providedArguments, | 1115 List<HInstruction> providedArguments, |
| 1116 ast.Node currentNode) { | 1116 ast.Node currentNode) { |
| 1117 assert(invariant(function, function.isImplementation)); | 1117 assert(invariant(function, function.isImplementation)); |
| 1118 assert(providedArguments != null); | 1118 assert(providedArguments != null); |
| 1119 | 1119 |
| 1120 bool isInstanceMember = function.isInstanceMember; | 1120 bool isInstanceMember = function.isInstanceMember; |
| 1121 // For static calls, [providedArguments] is complete, default arguments | 1121 // For static calls, [providedArguments] is complete, default arguments |
| 1122 // have been included if necessary, see [addStaticSendArgumentsToList]. | 1122 // have been included if necessary, see [makeStaticArgumentList]. |
| 1123 if (!isInstanceMember | 1123 if (!isInstanceMember |
| 1124 || currentNode == null // In erroneous code, currentNode can be null. | 1124 || currentNode == null // In erroneous code, currentNode can be null. |
| 1125 || providedArgumentsKnownToBeComplete(currentNode) | 1125 || providedArgumentsKnownToBeComplete(currentNode) |
| 1126 || function.isGenerativeConstructorBody | 1126 || function.isGenerativeConstructorBody |
| 1127 || selector.isGetter) { | 1127 || selector.isGetter) { |
| 1128 // For these cases, the provided argument list is known to be complete. | 1128 // For these cases, the provided argument list is known to be complete. |
| 1129 return providedArguments; | 1129 return providedArguments; |
| 1130 } else { | 1130 } else { |
| 1131 return completeDynamicSendArgumentsList( | 1131 return completeDynamicSendArgumentsList( |
| 1132 selector, function, providedArguments); | 1132 selector, function, providedArguments); |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 assert(link.head is ast.Send); | 1840 assert(link.head is ast.Send); |
| 1841 if (link.head is !ast.SendSet) { | 1841 if (link.head is !ast.SendSet) { |
| 1842 // A super initializer or constructor redirection. | 1842 // A super initializer or constructor redirection. |
| 1843 foundSuperOrRedirect = true; | 1843 foundSuperOrRedirect = true; |
| 1844 ast.Send call = link.head; | 1844 ast.Send call = link.head; |
| 1845 assert(ast.Initializers.isSuperConstructorCall(call) || | 1845 assert(ast.Initializers.isSuperConstructorCall(call) || |
| 1846 ast.Initializers.isConstructorRedirect(call)); | 1846 ast.Initializers.isConstructorRedirect(call)); |
| 1847 FunctionElement target = elements[call].implementation; | 1847 FunctionElement target = elements[call].implementation; |
| 1848 Selector selector = elements.getSelector(call); | 1848 Selector selector = elements.getSelector(call); |
| 1849 Link<ast.Node> arguments = call.arguments; | 1849 Link<ast.Node> arguments = call.arguments; |
| 1850 List<HInstruction> compiledArguments = new List<HInstruction>(); | 1850 List<HInstruction> compiledArguments; |
| 1851 inlinedFrom(constructor, () { | 1851 inlinedFrom(constructor, () { |
| 1852 addStaticSendArgumentsToList(selector, | 1852 compiledArguments = |
| 1853 arguments, | 1853 makeStaticArgumentList(selector, arguments, target); |
| 1854 target, | |
| 1855 compiledArguments); | |
| 1856 }); | 1854 }); |
| 1857 inlineSuperOrRedirect(target, | 1855 inlineSuperOrRedirect(target, |
| 1858 compiledArguments, | 1856 compiledArguments, |
| 1859 constructors, | 1857 constructors, |
| 1860 fieldValues, | 1858 fieldValues, |
| 1861 constructor); | 1859 constructor); |
| 1862 } else { | 1860 } else { |
| 1863 // A field initializer. | 1861 // A field initializer. |
| 1864 ast.SendSet init = link.head; | 1862 ast.SendSet init = link.head; |
| 1865 Link<ast.Node> arguments = init.arguments; | 1863 Link<ast.Node> arguments = init.arguments; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1881 assert(superClass != null); | 1879 assert(superClass != null); |
| 1882 assert(superClass.resolutionState == STATE_DONE); | 1880 assert(superClass.resolutionState == STATE_DONE); |
| 1883 Selector selector = | 1881 Selector selector = |
| 1884 new Selector.callDefaultConstructor(enclosingClass.library); | 1882 new Selector.callDefaultConstructor(enclosingClass.library); |
| 1885 // TODO(johnniwinther): Should we find injected constructors as well? | 1883 // TODO(johnniwinther): Should we find injected constructors as well? |
| 1886 FunctionElement target = superClass.lookupConstructor(selector); | 1884 FunctionElement target = superClass.lookupConstructor(selector); |
| 1887 if (target == null) { | 1885 if (target == null) { |
| 1888 compiler.internalError(superClass, | 1886 compiler.internalError(superClass, |
| 1889 "No default constructor available."); | 1887 "No default constructor available."); |
| 1890 } | 1888 } |
| 1891 List<HInstruction> arguments = <HInstruction>[]; | 1889 List<HInstruction> arguments = |
| 1892 selector.addArgumentsToList(const Link<ast.Node>(), | 1890 selector.makeArgumentsList2(const Link<ast.Node>(), |
| 1893 arguments, | 1891 target.implementation, |
| 1894 target.implementation, | 1892 null, |
| 1895 null, | 1893 handleConstantForOptionalParameter); |
| 1896 handleConstantForOptionalParameter, | |
| 1897 compiler.world); | |
| 1898 inlineSuperOrRedirect(target, | 1894 inlineSuperOrRedirect(target, |
| 1899 arguments, | 1895 arguments, |
| 1900 constructors, | 1896 constructors, |
| 1901 fieldValues, | 1897 fieldValues, |
| 1902 constructor); | 1898 constructor); |
| 1903 } | 1899 } |
| 1904 } | 1900 } |
| 1905 } | 1901 } |
| 1906 | 1902 |
| 1907 /** | 1903 /** |
| (...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3442 // of instructions, in an order that can be shared with | 3438 // of instructions, in an order that can be shared with |
| 3443 // selectors with the same named arguments. | 3439 // selectors with the same named arguments. |
| 3444 List<String> orderedNames = selector.getOrderedNamedArguments(); | 3440 List<String> orderedNames = selector.getOrderedNamedArguments(); |
| 3445 for (String name in orderedNames) { | 3441 for (String name in orderedNames) { |
| 3446 list.add(instructions[name]); | 3442 list.add(instructions[name]); |
| 3447 } | 3443 } |
| 3448 } | 3444 } |
| 3449 } | 3445 } |
| 3450 | 3446 |
| 3451 /** | 3447 /** |
| 3452 * Returns true if the arguments were compatible with the function signature. | 3448 * Returns a list with the evaluated [arguments] in the normalized order. |
| 3453 * | 3449 * |
| 3450 * Precondition: `this.applies(element, world)`. |
| 3454 * Invariant: [element] must be an implementation element. | 3451 * Invariant: [element] must be an implementation element. |
| 3455 */ | 3452 */ |
| 3456 bool addStaticSendArgumentsToList(Selector selector, | 3453 List<HInstruction> makeStaticArgumentList(Selector selector, |
| 3457 Link<ast.Node> arguments, | 3454 Link<ast.Node> arguments, |
| 3458 FunctionElement element, | 3455 FunctionElement element) { |
| 3459 List<HInstruction> list) { | |
| 3460 assert(invariant(element, element.isImplementation)); | 3456 assert(invariant(element, element.isImplementation)); |
| 3461 | 3457 |
| 3462 HInstruction compileArgument(ast.Node argument) { | 3458 HInstruction compileArgument(ast.Node argument) { |
| 3463 visit(argument); | 3459 visit(argument); |
| 3464 return pop(); | 3460 return pop(); |
| 3465 } | 3461 } |
| 3466 | 3462 |
| 3467 return selector.addArgumentsToList(arguments, | 3463 return selector.makeArgumentsList2(arguments, |
| 3468 list, | |
| 3469 element, | 3464 element, |
| 3470 compileArgument, | 3465 compileArgument, |
| 3471 handleConstantForOptionalParameter, | 3466 handleConstantForOptionalParameter); |
| 3472 compiler.world); | |
| 3473 } | 3467 } |
| 3474 | 3468 |
| 3475 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis
t) { | 3469 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis
t) { |
| 3476 for (; !link.isEmpty; link = link.tail) { | 3470 for (; !link.isEmpty; link = link.tail) { |
| 3477 visit(link.head); | 3471 visit(link.head); |
| 3478 list.add(pop()); | 3472 list.add(pop()); |
| 3479 } | 3473 } |
| 3480 } | 3474 } |
| 3481 | 3475 |
| 3482 visitDynamicSend(ast.Send node) { | 3476 visitDynamicSend(ast.Send node) { |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3974 addGenericSendArgumentsToList(node.arguments, arguments); | 3968 addGenericSendArgumentsToList(node.arguments, arguments); |
| 3975 } | 3969 } |
| 3976 return generateSuperNoSuchMethodSend(node, selector, arguments); | 3970 return generateSuperNoSuchMethodSend(node, selector, arguments); |
| 3977 } | 3971 } |
| 3978 List<HInstruction> inputs = <HInstruction>[]; | 3972 List<HInstruction> inputs = <HInstruction>[]; |
| 3979 if (node.isPropertyAccess) { | 3973 if (node.isPropertyAccess) { |
| 3980 push(buildInvokeSuper(selector, element, inputs)); | 3974 push(buildInvokeSuper(selector, element, inputs)); |
| 3981 } else if (element.isFunction || element.isGenerativeConstructor) { | 3975 } else if (element.isFunction || element.isGenerativeConstructor) { |
| 3982 if (selector.applies(element, compiler.world)) { | 3976 if (selector.applies(element, compiler.world)) { |
| 3983 // TODO(5347): Try to avoid the need for calling [implementation] before | 3977 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 3984 // calling [addStaticSendArgumentsToList]. | 3978 // calling [makeStaticArgumentList]. |
| 3985 FunctionElement function = element.implementation; | 3979 FunctionElement function = element.implementation; |
| 3986 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 3980 assert(selector.applies(function, compiler.world)); |
| 3987 function, inputs); | 3981 inputs = makeStaticArgumentList(selector, |
| 3988 assert(succeeded); | 3982 node.arguments, |
| 3983 function); |
| 3989 push(buildInvokeSuper(selector, element, inputs)); | 3984 push(buildInvokeSuper(selector, element, inputs)); |
| 3990 } else if (element.isGenerativeConstructor) { | 3985 } else if (element.isGenerativeConstructor) { |
| 3991 generateWrongArgumentCountError(node, element, node.arguments); | 3986 generateWrongArgumentCountError(node, element, node.arguments); |
| 3992 } else { | 3987 } else { |
| 3993 addGenericSendArgumentsToList(node.arguments, inputs); | 3988 addGenericSendArgumentsToList(node.arguments, inputs); |
| 3994 generateSuperNoSuchMethodSend(node, selector, inputs); | 3989 generateSuperNoSuchMethodSend(node, selector, inputs); |
| 3995 } | 3990 } |
| 3996 } else { | 3991 } else { |
| 3997 HInstruction target = buildInvokeSuper(selector, element, inputs); | 3992 HInstruction target = buildInvokeSuper(selector, element, inputs); |
| 3998 add(target); | 3993 add(target); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4256 | 4251 |
| 4257 if (checkTypeVariableBounds(node, type)) return; | 4252 if (checkTypeVariableBounds(node, type)) return; |
| 4258 | 4253 |
| 4259 var inputs = <HInstruction>[]; | 4254 var inputs = <HInstruction>[]; |
| 4260 if (constructor.isGenerativeConstructor && | 4255 if (constructor.isGenerativeConstructor && |
| 4261 Elements.isNativeOrExtendsNative(constructor.enclosingClass)) { | 4256 Elements.isNativeOrExtendsNative(constructor.enclosingClass)) { |
| 4262 // Native class generative constructors take a pre-constructed object. | 4257 // Native class generative constructors take a pre-constructed object. |
| 4263 inputs.add(graph.addConstantNull(compiler)); | 4258 inputs.add(graph.addConstantNull(compiler)); |
| 4264 } | 4259 } |
| 4265 // TODO(5347): Try to avoid the need for calling [implementation] before | 4260 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4266 // calling [addStaticSendArgumentsToList]. | 4261 // calling [makeStaticArgumentList]. |
| 4267 bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, | 4262 if (!selector.applies(constructor.implementation, compiler.world)) { |
| 4268 constructor.implementation, | |
| 4269 inputs); | |
| 4270 if (!succeeded) { | |
| 4271 generateWrongArgumentCountError(send, constructor, send.arguments); | 4263 generateWrongArgumentCountError(send, constructor, send.arguments); |
| 4272 return; | 4264 return; |
| 4273 } | 4265 } |
| 4266 inputs.addAll(makeStaticArgumentList(selector, |
| 4267 send.arguments, |
| 4268 constructor.implementation)); |
| 4274 | 4269 |
| 4275 if (constructor.isFactoryConstructor && | 4270 if (constructor.isFactoryConstructor && |
| 4276 !expectedType.typeArguments.isEmpty) { | 4271 !expectedType.typeArguments.isEmpty) { |
| 4277 registry.registerFactoryWithTypeArguments(); | 4272 registry.registerFactoryWithTypeArguments(); |
| 4278 } | 4273 } |
| 4279 | 4274 |
| 4280 TypeMask elementType = computeType(constructor); | 4275 TypeMask elementType = computeType(constructor); |
| 4281 if (isFixedListConstructorCall) { | 4276 if (isFixedListConstructorCall) { |
| 4282 if (!inputs[0].isNumber(compiler)) { | 4277 if (!inputs[0].isNumber(compiler)) { |
| 4283 HTypeConversion conversion = new HTypeConversion( | 4278 HTypeConversion conversion = new HTypeConversion( |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4445 // An erroneous element indicates that the funciton could not be resolved | 4440 // An erroneous element indicates that the funciton could not be resolved |
| 4446 // (a warning has been issued). | 4441 // (a warning has been issued). |
| 4447 generateThrowNoSuchMethod(node, | 4442 generateThrowNoSuchMethod(node, |
| 4448 noSuchMethodTargetSymbolString(element), | 4443 noSuchMethodTargetSymbolString(element), |
| 4449 argumentNodes: node.arguments); | 4444 argumentNodes: node.arguments); |
| 4450 return; | 4445 return; |
| 4451 } | 4446 } |
| 4452 invariant(element, !element.isGenerativeConstructor); | 4447 invariant(element, !element.isGenerativeConstructor); |
| 4453 generateIsDeferredLoadedCheckIfNeeded(node); | 4448 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4454 if (element.isFunction) { | 4449 if (element.isFunction) { |
| 4455 var inputs = <HInstruction>[]; | |
| 4456 // TODO(5347): Try to avoid the need for calling [implementation] before | 4450 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4457 // calling [addStaticSendArgumentsToList]. | 4451 // calling [makeStaticArgumentList]. |
| 4458 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 4452 if (!selector.applies(element.implementation, compiler.world)) { |
| 4459 element.implementation, | |
| 4460 inputs); | |
| 4461 if (!succeeded) { | |
| 4462 generateWrongArgumentCountError(node, element, node.arguments); | 4453 generateWrongArgumentCountError(node, element, node.arguments); |
| 4463 return; | 4454 return; |
| 4464 } | 4455 } |
| 4465 | 4456 |
| 4457 List<HInstruction> inputs = |
| 4458 makeStaticArgumentList(selector, |
| 4459 node.arguments, |
| 4460 element.implementation); |
| 4461 |
| 4466 if (element == compiler.identicalFunction) { | 4462 if (element == compiler.identicalFunction) { |
| 4467 pushWithPosition( | 4463 pushWithPosition( |
| 4468 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); | 4464 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); |
| 4469 return; | 4465 return; |
| 4470 } | 4466 } |
| 4471 | 4467 |
| 4472 pushInvokeStatic(node, element, inputs); | 4468 pushInvokeStatic(node, element, inputs); |
| 4473 } else { | 4469 } else { |
| 4474 generateGetter(node, element); | 4470 generateGetter(node, element); |
| 4475 List<HInstruction> inputs = <HInstruction>[pop()]; | 4471 List<HInstruction> inputs = <HInstruction>[pop()]; |
| (...skipping 2134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6610 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6606 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6611 unaliased.accept(this, builder); | 6607 unaliased.accept(this, builder); |
| 6612 } | 6608 } |
| 6613 | 6609 |
| 6614 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6610 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6615 JavaScriptBackend backend = builder.compiler.backend; | 6611 JavaScriptBackend backend = builder.compiler.backend; |
| 6616 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6612 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 6617 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6613 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 6618 } | 6614 } |
| 6619 } | 6615 } |
| OLD | NEW |