Chromium Code Reviews| Index: lib/compiler/implementation/js_backend/emitter.dart |
| =================================================================== |
| --- lib/compiler/implementation/js_backend/emitter.dart (revision 13369) |
| +++ lib/compiler/implementation/js_backend/emitter.dart (working copy) |
| @@ -476,20 +476,97 @@ |
| // |
| // We need to generate a stub for (5) because the order of the |
| // stub arguments and the real method may be different. |
| - Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| - if (selectors == null) return; |
| - // Keep a cache of which stubs have already been generated, to |
| - // avoid duplicates. Note that even if selectors are |
| - // canonicalized, we would still need this cache: a typed selector |
| - // on A and a typed selector on B could yield the same stub. |
| Set<String> generatedStubNames = new Set<String>(); |
| - for (Selector selector in selectors) { |
| - if (!selector.applies(member, compiler)) continue; |
| - addParameterStub( |
| - member, selector, defineInstanceMember, generatedStubNames); |
| + if (compiler.enabledFunctionApply |
| + && member.name == Namer.CLOSURE_INVOCATION_NAME) { |
| + // If [Function.apply] is called, we pessimistically compile all |
| + // possible stubs for this closure. |
| + // TODO(5074): This functionality only supports the new |
| + // parameter specification, and this comment should be removed |
| + // once the old specification is not supported. |
| + FunctionSignature signature = member.computeSignature(compiler); |
| + Set<Selector> selectors = signature.optionalParametersAreNamed |
| + ? computeNamedSelectors(signature, member) |
| + : computeOptionalSelectors(signature, member); |
| + for (Selector selector in selectors) { |
| + addParameterStub( |
| + member, selector, defineInstanceMember, generatedStubNames); |
| + } |
| + } else { |
| + Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| + if (selectors == null) return; |
| + // Keep a cache of which stubs have already been generated, to |
|
kasperl
2012/10/09 11:35:18
Where did the cache move? I guess the comment need
ngeoffray
2012/10/09 11:56:58
Done.
|
| + // avoid duplicates. Note that even if selectors are |
| + // canonicalized, we would still need this cache: a typed selector |
| + // on A and a typed selector on B could yield the same stub. |
| + for (Selector selector in selectors) { |
| + if (!selector.applies(member, compiler)) continue; |
| + addParameterStub( |
| + member, selector, defineInstanceMember, generatedStubNames); |
| + } |
| } |
| } |
| + /** |
| + * Compute the set of possible selectors in the presence of named |
| + * parameters. |
| + */ |
| + Set<Selector> computeNamedSelectors(FunctionSignature signature, |
| + FunctionElement element) { |
| + Set<Selector> selectors = new Set<Selector>(); |
| + // Add the selector that does not have any optional argument. |
| + selectors.add(new Selector(SelectorKind.CALL, |
| + element.name, |
| + element.getLibrary(), |
| + signature.requiredParameterCount, |
| + <SourceString>[])); |
| + |
| + // For each optional parameter, we iterator over the set of |
| + // already computed selectors and create new selectors with that |
| + // parameter now being passed. |
| + signature.forEachOptionalParameter((Element element) { |
| + // We will iterate over the set and add new selectors. Make a copy |
| + // of a set to not change it while iterating. |
| + Set<Selector> newSet = new Set<Selector>.from(selectors); |
|
kasperl
2012/10/09 11:35:18
Wouldn't it be simpler to collect the new selector
ngeoffray
2012/10/09 11:56:58
Good point. Done.
|
| + newSet.forEach((Selector other) { |
| + List<SourceString> namedArguments = [element.name]; |
| + namedArguments.addAll(other.namedArguments); |
| + selectors.add(new Selector(other.kind, |
| + other.name, |
| + other.library, |
| + other.argumentCount + 1, |
| + namedArguments)); |
| + }); |
| + }); |
| + return selectors; |
| + } |
| + |
| + /** |
| + * Compute the set of possible selectors in the presence of optional |
| + * non-named parameters. |
| + */ |
| + Set<Selector> computeOptionalSelectors(FunctionSignature signature, |
| + FunctionElement element) { |
| + Set<Selector> selectors = new Set<Selector>(); |
| + // Add the selector that does not have any optional argument. |
| + selectors.add(new Selector(SelectorKind.CALL, |
| + element.name, |
| + element.getLibrary(), |
| + signature.requiredParameterCount, |
| + <SourceString>[])); |
| + |
| + // For each optional parameter, we increment the number of passed |
| + // argument. |
| + for (int i = 1; i <= signature.optionalParameterCount; i++) { |
| + selectors.add(new Selector(SelectorKind.CALL, |
| + element.name, |
| + element.getLibrary(), |
| + signature.requiredParameterCount + i, |
| + <SourceString>[])); |
| + } |
| + return selectors; |
| + } |
| + |
| bool instanceFieldNeedsGetter(Element member) { |
| assert(member.isField()); |
| return compiler.codegenWorld.hasInvokedGetter(member, compiler); |