Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 19450) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
| @@ -3046,17 +3046,20 @@ |
| } |
| } |
| - 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. |
| + compiler.enqueuer.codegen.registerSelectorUse(selector); |
| + } |
| HStatic target = new HStatic(element); |
| add(target); |
| HInstruction self = localsHandler.readThis(); |
| @@ -3068,11 +3071,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,17 +3115,13 @@ |
| 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]. |
| - HInstruction target = new HStatic(element.declaration); |
| - HInstruction context = localsHandler.readThis(); |
| - add(target); |
| - var inputs = <HInstruction>[target, context]; |
| - if (backend.isInterceptedMethod(element)) { |
| - inputs.add(context); |
| - } |
| + List<HInstruction> inputs = buildSuperAccessorInputs(element); |
| if (node.isPropertyAccess) { |
| push(new HInvokeSuper(inputs)); |
| } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| @@ -3579,6 +3573,38 @@ |
| return new HInvokeDynamicMethod(selector, inputs, isIntercepted); |
| } |
| + void handleComplexOperatorSend(SendSet node, |
| + HInstruction receiver, |
| + Link<Node> arguments) { |
| + HInstruction rhs; |
| + if (node.isPrefix || node.isPostfix) { |
| + rhs = graph.addConstantInt(1, constantSystem); |
| + } else { |
| + visit(arguments.head); |
| + assert(arguments.tail.isEmpty); |
| + rhs = pop(); |
| + } |
| + visitBinary(receiver, node.assignmentOperator, rhs, |
| + elements.getOperatorSelectorInComplexSendSet(node), node); |
| + } |
| + |
| + List<HInstruction> buildSuperAccessorInputs(Element element) { |
| + List<HInstruction> inputs = <HInstruction>[]; |
| + if (Elements.isUnresolved(element)) return inputs; |
| + // TODO(5346): Try to avoid the need for calling [declaration] before |
| + // creating an [HStatic]. |
| + HInstruction target = new HStatic(element.declaration); |
| + add(target); |
| + inputs.add(target); |
| + HInstruction context = localsHandler.readThis(); |
| + inputs.add(context); |
| + if (backend.isInterceptedMethod(element)) { |
| + inputs.add(context); |
| + } |
| + return inputs; |
| + } |
| + |
|
kasperl
2013/03/05 08:57:42
Too many newlines.
|
| + |
| visitSendSet(SendSet node) { |
| Element element = elements[node]; |
| if (!Elements.isUnresolved(element) && element.impliesType()) { |
| @@ -3589,19 +3615,54 @@ |
| } |
| Operator op = node.assignmentOperator; |
| if (node.isSuperCall) { |
| + HInstruction result; |
| + List<HInstruction> setterInputs = buildSuperAccessInputs(element); |
| + if (identical(node.assignmentOperator.source.stringValue, '=')) { |
| + addDynamicSendArgumentsToList(node, setterInputs); |
| + result = setterInputs.last; |
| + } else { |
| + Element getter = elements[node.selector]; |
| + List<HInstruction> getterInputs = buildSuperAccessInputs(getter); |
| + Link<Node> arguments = node.arguments; |
| + if (node.isIndex) { |
| + // If node is of the from [:super.foo[0] += 2:], the send has |
| + // two arguments: the index and the left hand side. We get |
| + // the index and add it as input of the getter and the |
| + // setter. |
| + visit(arguments.head); |
| + arguments = arguments.tail; |
| + HInstruction index = pop(); |
| + getterInputs.add(index); |
| + setterInputs.add(index); |
| + } |
| + HInstruction getterInstruction; |
| + if (Elements.isUnresolved(getter)) { |
| + generateSuperNoSuchMethodSend( |
| + node, |
| + elements.getGetterSelectorInComplexSendSet(node), |
| + getterInputs); |
| + getterInstruction = pop(); |
| + } else { |
| + getterInstruction = new HInvokeSuper(getterInputs); |
| + add(getterInstruction); |
| + } |
| + handleComplexOperatorSend(node, getterInstruction, arguments); |
| + setterInputs.add(pop()); |
| + |
| + if (node.isPostfix) { |
| + result = getterInstruction; |
| + } else { |
| + result = 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(result); |
| } else if (node.isIndex) { |
| if (const SourceString("=") == op.source) { |
| // TODO(kasperl): We temporarily disable inlining because the |
| @@ -3613,36 +3674,32 @@ |
| } else { |
| visit(node.receiver); |
| HInstruction receiver = pop(); |
| - visit(node.argumentsNode); |
| - HInstruction value; |
| + Link<Node> arguments = node.arguments; |
| HInstruction index; |
| - // Compound assignments are considered as being prefix. |
| - bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| - bool isPrefix = !node.isPostfix; |
| - if (isCompoundAssignment) { |
| - value = pop(); |
| + if (node.isIndex) { |
| + visit(arguments.head); |
| + arguments = arguments.tail; |
| index = pop(); |
| - } else { |
| - index = pop(); |
| - value = graph.addConstantInt(1, constantSystem); |
| } |
| - HInvokeDynamicMethod left = buildInvokeDynamic( |
| + HInvokeDynamicMethod getterInstruction = buildInvokeDynamic( |
| node, |
| elements.getGetterSelectorInComplexSendSet(node), |
| receiver, |
| <HInstruction>[index]); |
| - add(left); |
| - visitBinary(left, op, value, |
| - elements.getOperatorSelectorInComplexSendSet(node), node); |
| - value = pop(); |
| + add(getterInstruction); |
| + |
| + handleComplexOperatorSend(node, getterInstruction, arguments); |
| + HInstruction value = pop(); |
| + |
| HInvokeDynamicMethod assign = buildInvokeDynamic( |
| node, elements.getSelector(node), receiver, [index, value]); |
| add(assign); |
| - if (isPrefix) { |
| + |
| + if (node.isPostfix) { |
| + stack.add(getterInstruction); |
| + } else { |
| stack.add(value); |
| - } else { |
| - stack.add(left); |
| } |
| } |
| } else if (const SourceString("=") == op.source) { |
| @@ -3657,8 +3714,6 @@ |
| assert(const SourceString("++") == op.source || |
| const SourceString("--") == op.source || |
| node.assignmentOperator.source.stringValue.endsWith("=")); |
| - bool isCompoundAssignment = !node.arguments.isEmpty; |
| - bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| // [receiver] is only used if the node is an instance send. |
| HInstruction receiver = null; |
| @@ -3669,28 +3724,20 @@ |
| } else { |
| generateGetter(node, elements[node.selector]); |
| } |
| - HInstruction left = pop(); |
| - HInstruction right; |
| - if (isCompoundAssignment) { |
| - visit(node.argumentsNode); |
| - right = pop(); |
| - } else { |
| - right = graph.addConstantInt(1, constantSystem); |
| - } |
| - visitBinary(left, op, right, |
| - elements.getOperatorSelectorInComplexSendSet(node), node); |
| - HInstruction operation = pop(); |
| - assert(operation != null); |
| + HInstruction getterInstruction = pop(); |
| + handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| + HInstruction value = pop(); |
| + assert(value != null); |
| if (Elements.isInstanceSend(node, elements)) { |
| assert(receiver != null); |
| - generateInstanceSetterWithCompiledReceiver(node, receiver, operation); |
| + generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
| } else { |
| assert(receiver == null); |
| - generateSetter(node, element, operation); |
| + generateSetter(node, element, value); |
| } |
| - if (!isPrefix) { |
| + if (!node.isPostfix) { |
| pop(); |
| - stack.add(left); |
| + stack.add(getterInstruction); |
| } |
| } |
| } |