Chromium Code Reviews| Index: dart/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart |
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/dart/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart |
| index 1b2e54a4301a98ea27236684b1c94b01af9cdeb8..94ad5a4d0496654aace1b516a6a7d8284fc04aeb 100644 |
| --- a/dart/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart |
| +++ b/dart/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart |
| @@ -129,17 +129,13 @@ class ContainerBuilder extends CodeEmitterHelper { |
| jsAst.Fun function = js.fun(parametersBuffer, body); |
| defineStub(invocationName, function); |
| - |
| - String reflectionName = task.getReflectionName(selector, invocationName); |
| - if (reflectionName != null) { |
| - var reflectable = |
| - js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| - defineStub('+$reflectionName', reflectable); |
| - } |
| } |
| void addParameterStubs(FunctionElement member, |
| DefineStubFunction defineStub) { |
| + // Bound closures are generated dynamically. |
| + if (member.enclosingElement.isClosure()) return; |
| + |
| // We fill the lists depending on the selector. For example, |
| // take method foo: |
| // foo(a, b, {c, d}); |
| @@ -169,92 +165,27 @@ class ContainerBuilder extends CodeEmitterHelper { |
| // 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>(); |
| - bool isClosureInvocation = |
| - member.name == namer.closureInvocationSelectorName; |
| - if (backend.isNeededForReflection(member) || |
| - (compiler.enabledFunctionApply && isClosureInvocation)) { |
| - // If [Function.apply] is called, we pessimistically compile all |
| - // possible stubs for this closure. |
| - FunctionSignature signature = member.computeSignature(compiler); |
| - Set<Selector> selectors = signature.optionalParametersAreNamed |
| - ? computeSeenNamedSelectors(member) |
| - : computeOptionalSelectors(signature, member); |
| - for (Selector selector in selectors) { |
| - addParameterStub(member, selector, defineStub, generatedStubNames); |
| - } |
| - if (signature.optionalParametersAreNamed && isClosureInvocation) { |
| - addCatchAllParameterStub(member, signature, defineStub); |
| - } |
| - } else { |
| - Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| + Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| + if (selectors == null) { |
| + selectors = compiler.codegenWorld.invokedNames[ |
| + namer.closureInvocationSelectorName]; |
|
kasperl
2013/10/21 10:25:44
Cache namer.closureInvocationSelectorName in a loc
ahe
2013/12/06 15:57:53
The code is now so distant that I don't think it h
|
| if (selectors == null) return; |
| - for (Selector selector in selectors) { |
| - if (!selector.applies(member, compiler)) continue; |
| - addParameterStub(member, selector, defineStub, generatedStubNames); |
| + } else { |
| + Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ |
| + namer.closureInvocationSelectorName]; |
| + if (callSelectors != null) { |
| + selectors = new Set<Selector>.from(selectors)..addAll(callSelectors); |
|
kasperl
2013/10/21 10:25:44
Can you use Set.union here?
ahe
2013/10/22 10:52:34
Oh yeah! I didn't know about that method :-)
|
| } |
| } |
| - } |
| - |
| - Set<Selector> computeSeenNamedSelectors(FunctionElement element) { |
| - Set<Selector> selectors = compiler.codegenWorld.invokedNames[element.name]; |
| - Set<Selector> result = new Set<Selector>(); |
| - if (selectors == null) return result; |
| for (Selector selector in selectors) { |
| - if (!selector.applies(element, compiler)) continue; |
| - result.add(selector); |
| - } |
| - return result; |
| - } |
| - |
| - void addCatchAllParameterStub(FunctionElement member, |
| - FunctionSignature signature, |
| - DefineStubFunction defineStub) { |
| - // See Primities.applyFunction in js_helper.dart for details. |
| - List<jsAst.Property> properties = <jsAst.Property>[]; |
| - for (Element element in signature.orderedOptionalParameters) { |
| - String jsName = backend.namer.safeName(element.name.slowToString()); |
| - Constant value = compiler.constantHandler.initialVariableValues[element]; |
| - jsAst.Expression reference = null; |
| - if (value == null) { |
| - reference = new jsAst.LiteralNull(); |
| - } else { |
| - reference = task.constantReference(value); |
| - } |
| - properties.add(new jsAst.Property(js.string(jsName), reference)); |
| - } |
| - defineStub( |
| - backend.namer.callCatchAllName, |
| - js.fun([], js.return_(new jsAst.ObjectInitializer(properties)))); |
| - } |
| - |
| - /** |
| - * 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>[])); |
| + if (!selector.applies(member, compiler)) continue; |
| + // TODO(ahe): Is the last argument to [addParameterStub] needed? |
| + addParameterStub(member, selector, defineStub, new Set<String>()); |
| } |
| - return selectors; |
| } |
| void emitStaticFunctionGetters(CodeBuffer eagerBuffer) { |
| + return; |
| task.addComment('Static function getters', task.mainBuffer); |
| for (FunctionElement element in |
| Elements.sortedByPosition(staticGetters.keys)) { |
| @@ -579,10 +510,6 @@ class ContainerBuilder extends CodeEmitterHelper { |
| if (selectors != null && !selectors.isEmpty) { |
| emitCallStubForGetter(member, selectors, builder.addProperty); |
| } |
| - } else if (member.isFunction()) { |
| - if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { |
| - emitDynamicFunctionGetter(member, builder.addProperty); |
| - } |
| } |
| } |
| @@ -608,34 +535,70 @@ class ContainerBuilder extends CodeEmitterHelper { |
| jsAst.Expression code = backend.generatedCode[member]; |
| if (code == null) return; |
| String name = namer.getNameOfMember(member); |
| - if (backend.isInterceptedMethod(member)) { |
| - task.interceptorEmitter.interceptorInvocationNames.add(name); |
| + task.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); |
| + FunctionSignature parameters = member.computeSignature(compiler); |
| + bool needsStubs = !parameters.optionalParameters.isEmpty; |
| + bool canTearOff = false; |
|
kasperl
2013/10/21 10:25:44
Consider only using tearOffName (null could repres
ahe
2013/12/06 15:57:53
I forgot about this comment, but I'm weary of chan
|
| + String tearOffName; |
| + if (member.isInstanceMember()) { |
| + // Careful with operators. |
| + canTearOff = compiler.codegenWorld.hasInvokedGetter(member, compiler); |
| + tearOffName = namer.getterName(member); |
| + } else { |
| + canTearOff = |
| + compiler.codegenWorld.staticFunctionsNeedingGetter.contains(member); |
| + tearOffName = namer.getStaticClosureName(member); |
| } |
| - code = task.metadataEmitter.extendWithMetadata(member, code); |
| - builder.addProperty(name, code); |
| - String reflectionName = task.getReflectionName(member, name); |
| - if (reflectionName != null) { |
| - var reflectable = |
| - js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| - builder.addProperty('+$reflectionName', reflectable); |
| - jsAst.Node defaultValues = |
| - task.metadataEmitter.reifyDefaultArguments(member); |
| - if (defaultValues != null) { |
| - String unmangledName = member.name.slowToString(); |
| - builder.addProperty('*$unmangledName', defaultValues); |
| - } |
| + |
| + if (!canTearOff && !needsStubs && !backend.isNeededForReflection(member)) { |
| + builder.addProperty(name, code); |
| + addBailout(member, builder); |
| + return; |
| + } |
| + // This element is needed for reflection or needs additional stubs. So we |
| + // need to retain additional information. |
| + |
| + List expressions = []; |
| + |
| + bool canBeReflected = backend.isAccessibleByReflection(member); |
| + expressions |
| + ..add(code) |
| + ..add(member.isAccessor() ? js("null") : js.string(tearOffName)) |
| + // TODO(ahe): Obtain proper name. |
| + ..add(js.string("call\$${parameters.requiredParameterCount}")) |
| + ..add(canBeReflected ? parameters.requiredParameterCount + 1 : 0) |
| + ..add(parameters.optionalParameterCount) |
| + ..addAll(task.metadataEmitter.reifyDefaultArguments(member)); |
| + |
| + if (needsStubs) { |
| + addParameterStubs(member, (String name, jsAst.Fun function) { |
| + expressions.add(function); |
| + expressions.add(js.string(name)); |
| + // TODO(ahe): Obtain proper call name. |
| + expressions.add(js.string("call\$${function.params.length}")); |
| + }); |
| + } |
| + |
| + if (canBeReflected) { |
| + expressions |
| + ..add(js.string(member.name.slowToString())) |
| + ..addAll(task.metadataEmitter.computeMetadata(member)); |
| } |
| - code = backend.generatedBailoutCode[member]; |
| + |
| + builder.addProperty(name, js.toExpression(expressions)); |
| + |
| + addBailout(member, builder); |
| + |
| + // if (canTearOff) { |
| + // emitDynamicFunctionGetter(member, builder.addProperty); |
| + // } |
| + } |
| + |
| + void addBailout(FunctionElement member, ClassBuilder builder) { |
| + jsAst.Expression code = backend.generatedBailoutCode[member]; |
| if (code != null) { |
| builder.addProperty(namer.getBailoutName(member), code); |
| } |
| - if (member.isInstanceMember()) { |
| - // TODO(ahe): Where is this done for static/top-level methods? |
| - FunctionSignature parameters = member.computeSignature(compiler); |
| - if (!parameters.optionalParameters.isEmpty) { |
| - addParameterStubs(member, builder.addProperty); |
| - } |
| - } |
| } |
| void addMemberField(VariableElement member, ClassBuilder builder) { |