Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 19425) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
| @@ -3046,17 +3046,26 @@ |
| } |
| } |
| - generateSuperNoSuchMethodSend(Send node) { |
| - Selector selector = elements.getSelector(node); |
| + generateSuperNoSuchMethodSend(Send node, |
| + Selector selector, |
| + List<HInstruction> arguments) { |
| SourceString name = selector.name; |
| ClassElement cls = currentElement.getEnclosingClass(); |
| Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| if (element.enclosingElement.declaration != compiler.objectClass) { |
| // Register the call as dynamic if [:noSuchMethod:] on the super class |
| - // is _not_ the default implementation from [:Object:]. |
| - compiler.enqueuer.codegen.registerDynamicInvocation(name, selector); |
| - } |
| + // is _not_ the default implementation from [:Object:], in case |
| + // the [:noSuchMethod:] implementation does an [:invokeOn:] on |
| + // the invocation mirror. |
| + if (selector.isGetter()) { |
|
kasperl
2013/03/05 07:32:36
Could this logic be moved to the enqueuer? If we h
ngeoffray
2013/03/05 08:46:25
Done.
|
| + compiler.enqueuer.codegen.registerDynamicGetter(name, selector); |
| + } else if (selector.isSetter()) { |
| + compiler.enqueuer.codegen.registerDynamicSetter(name, selector); |
| + } else { |
| + compiler.enqueuer.codegen.registerDynamicInvocation(name, selector); |
| + } |
| + } |
| HStatic target = new HStatic(element); |
| add(target); |
| HInstruction self = localsHandler.readThis(); |
| @@ -3068,11 +3077,6 @@ |
| constantSystem.createString(new DartString.literal(internalName), node); |
| Element createInvocationMirror = backend.getCreateInvocationMirror(); |
| - |
| - var arguments = new List<HInstruction>(); |
| - if (node.argumentsNode != null) { |
| - addGenericSendArgumentsToList(node.arguments, arguments); |
| - } |
| var argumentsInstruction = new HLiteralList(arguments); |
| add(argumentsInstruction); |
| @@ -3117,7 +3121,11 @@ |
| Selector selector = elements.getSelector(node); |
| Element element = elements[node]; |
| if (Elements.isUnresolved(element)) { |
| - return generateSuperNoSuchMethodSend(node); |
| + List<HInstruction> arguments = <HInstruction>[]; |
| + if (!node.isPropertyAccess) { |
| + addGenericSendArgumentsToList(node.arguments, arguments); |
| + } |
| + return generateSuperNoSuchMethodSend(node, selector, arguments); |
| } |
| // TODO(5346): Try to avoid the need for calling [declaration] before |
| // creating an [HStatic]. |
| @@ -3589,19 +3597,78 @@ |
| } |
| Operator op = node.assignmentOperator; |
| if (node.isSuperCall) { |
|
kasperl
2013/03/05 07:32:36
Think about if some of this could be shared with t
|
| + HInstruction toPush; |
|
kasperl
2013/03/05 07:32:36
I'd call this the value/result or something like t
ngeoffray
2013/03/05 08:46:25
Done.
|
| + List<HInstruction> setterInputs = <HInstruction>[]; |
| + HInstruction context = localsHandler.readThis(); |
| + if (!Elements.isUnresolved(element)) { |
| + HInstruction target = new HStatic(element); |
|
kasperl
2013/03/05 07:32:36
Is any of this refactorable? The resolved target/g
ngeoffray
2013/03/05 08:46:25
Done.
|
| + add(target); |
| + setterInputs.add(target); |
| + setterInputs.add(context); |
| + if (backend.isInterceptedMethod(element)) { |
| + setterInputs.add(context); |
| + } |
| + } |
| + if (identical(node.assignmentOperator.source.stringValue, '=')) { |
| + addDynamicSendArgumentsToList(node, setterInputs); |
| + toPush = setterInputs.last; |
| + } else { |
| + Element getter = elements[node.selector]; |
| + List<HInstruction> getterInputs = <HInstruction>[]; |
| + if (!Elements.isUnresolved(getter)) { |
| + HInstruction getterTarget = new HStatic(getter); |
| + add(getterTarget); |
| + getterInputs.add(getterTarget); |
| + getterInputs.add(context); |
| + if (backend.isInterceptedMethod(getter)) { |
| + getterInputs.add(context); |
| + } |
| + } |
| + Link<Node> arguments = node.arguments; |
|
kasperl
2013/03/05 07:32:36
Add a comment that explains what you're dealing wi
ngeoffray
2013/03/05 08:46:25
Done.
|
| + if (node.isIndex) { |
| + visit(arguments.head); |
| + arguments = arguments.tail; |
| + HInstruction index = pop(); |
| + getterInputs.add(index); |
| + setterInputs.add(index); |
| + } |
| + HInstruction getterInstruction; |
|
kasperl
2013/03/05 07:32:36
Could this (the computation of the getterInstructi
ngeoffray
2013/03/05 08:46:25
Done.
|
| + if (Elements.isUnresolved(getter)) { |
| + generateSuperNoSuchMethodSend( |
| + node, |
| + elements.getGetterSelectorInComplexSendSet(node), |
| + getterInputs); |
| + getterInstruction = pop(); |
| + } else { |
| + getterInstruction = new HInvokeSuper(getterInputs); |
| + add(getterInstruction); |
| + } |
| + HInstruction rhs; |
|
kasperl
2013/03/05 07:32:36
Do we have code like this elsewhere in the builder
ngeoffray
2013/03/05 08:46:25
Yes, refactored.
|
| + if (node.isPrefix || node.isPostfix) { |
| + rhs = graph.addConstantInt(1, constantSystem); |
| + } else { |
| + visit(arguments.head); |
| + assert(arguments.tail.isEmpty); |
| + rhs = pop(); |
| + } |
| + visitBinary(getterInstruction, op, rhs, |
| + elements.getOperatorSelectorInComplexSendSet(node), node); |
| + setterInputs.add(pop()); |
| + |
| + if (node.isPostfix) { |
| + toPush = getterInstruction; |
| + } else { |
| + toPush = setterInputs.last; |
| + } |
| + } |
| if (Elements.isUnresolved(element)) { |
| - return generateSuperNoSuchMethodSend(node); |
| + generateSuperNoSuchMethodSend( |
| + node, elements.getSelector(node), setterInputs); |
| + pop(); |
| + } else { |
| + add(new HInvokeSuper(setterInputs, isSetter: true)); |
| } |
| - HInstruction target = new HStatic(element); |
| - HInstruction context = localsHandler.readThis(); |
| - add(target); |
| - var inputs = <HInstruction>[target, context]; |
| - addDynamicSendArgumentsToList(node, inputs); |
| - if (!identical(node.assignmentOperator.source.stringValue, '=')) { |
| - compiler.unimplemented('complex super assignment', |
| - node: node.assignmentOperator); |
| - } |
| - push(new HInvokeSuper(inputs, isSetter: true)); |
| + stack.add(toPush); |
| } else if (node.isIndex) { |
| if (const SourceString("=") == op.source) { |
| // TODO(kasperl): We temporarily disable inlining because the |