Chromium Code Reviews| Index: pkg/compiler/lib/src/ssa/builder.dart |
| diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart |
| index 0ef26591b908ce4d5ecb0c34336f8993d993030a..f1089f9d06fa3da7d54b8914bee1bbf0dec090ff 100644 |
| --- a/pkg/compiler/lib/src/ssa/builder.dart |
| +++ b/pkg/compiler/lib/src/ssa/builder.dart |
| @@ -3508,37 +3508,6 @@ class SsaBuilder extends NewResolvedVisitor { |
| generateStaticGetterGet(node, getter); |
| } |
| - void generatePossiblyConditionalInstanceSetter(ast.Send send, |
| - HInstruction pushReceiver(), |
| - HInstruction pushValue(), |
| - {Selector selector, |
| - ast.Node location}) { |
| - if (send.isConditional) { |
| - SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); |
| - // compile e?.x = e2 to: |
| - // |
| - // t1 = e |
| - // if (t1 == null) |
| - // result = t1 // same as result = null |
| - // else |
| - // result = e.x = e2 |
| - HInstruction receiver; |
| - brancher.handleConditional( |
| - () { |
| - receiver = pushReceiver(); |
| - pushCheckNull(receiver); |
| - }, |
| - () => stack.add(receiver), |
| - () => generateInstanceSetterWithCompiledReceiver( |
| - send, receiver, pushValue(), |
| - selector: selector, location: location)); |
| - } else { |
| - generateInstanceSetterWithCompiledReceiver( |
| - send, pushReceiver(), pushValue(), |
| - selector: selector, location: location); |
| - } |
| - } |
| - |
| void generateInstanceSetterWithCompiledReceiver(ast.Send send, |
| HInstruction receiver, |
| HInstruction value, |
| @@ -3986,7 +3955,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| } |
| } |
| - void handleForeingJsGetFlag(ast.Send node) { |
| + void handleForeignJsGetFlag(ast.Send node) { |
| List<ast.Node> arguments = node.arguments.toList(); |
| ast.Node argument; |
| switch (arguments.length) { |
| @@ -4285,7 +4254,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| } else if (name == 'JS_BUILTIN') { |
| handleForeignJsBuiltin(node); |
| } else if (name == 'JS_GET_FLAG') { |
| - handleForeingJsGetFlag(node); |
| + handleForeignJsGetFlag(node); |
| } else if (name == 'JS_EFFECT') { |
| stack.add(graph.addConstantNull(compiler)); |
| } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| @@ -5625,231 +5594,489 @@ class SsaBuilder extends NewResolvedVisitor { |
| location: node.assignmentOperator); |
| } |
| - @override |
| - handleSendSet(ast.SendSet node) { |
| - generateIsDeferredLoadedCheckOfSend(node); |
| + void handleSuperSendSet(ast.SendSet node) { |
| Element element = elements[node]; |
| - if (!Elements.isUnresolved(element) && element.impliesType) { |
| - ast.Identifier selector = node.selector; |
| - generateThrowNoSuchMethod(node, selector.source, |
| - argumentNodes: node.arguments); |
| - return; |
| + List<HInstruction> setterInputs = <HInstruction>[]; |
| + void generateSuperSendSet() { |
| + Selector setterSelector = elements.getSelector(node); |
| + if (Elements.isUnresolved(element) |
| + || !setterSelector.applies(element, compiler.world)) { |
| + generateSuperNoSuchMethodSend( |
| + node, setterSelector, setterInputs); |
| + pop(); |
| + } else { |
| + add(buildInvokeSuper(setterSelector, element, setterInputs)); |
| + } |
| } |
| - ast.Operator op = node.assignmentOperator; |
| - if (node.isSuperCall) { |
| - List<HInstruction> setterInputs = <HInstruction>[]; |
| - void generateSuperSendSet() { |
| - Selector setterSelector = elements.getSelector(node); |
| - if (Elements.isUnresolved(element) |
| - || !setterSelector.applies(element, compiler.world)) { |
| - generateSuperNoSuchMethodSend( |
| - node, setterSelector, setterInputs); |
| - pop(); |
| - } else { |
| - add(buildInvokeSuper(setterSelector, element, setterInputs)); |
| - } |
| + if (identical(node.assignmentOperator.source, '=')) { |
| + addDynamicSendArgumentsToList(node, setterInputs); |
| + generateSuperSendSet(); |
| + stack.add(setterInputs.last); |
| + } else { |
| + Element getter = elements[node.selector]; |
| + List<HInstruction> getterInputs = <HInstruction>[]; |
| + Link<ast.Node> arguments = node.arguments; |
| + if (node.isIndex) { |
| + // If node is of the from [:super.foo[0] += 2:], the send has |
|
karlklose
2015/06/17 07:51:01
'from' -> 'from'.
Johnni Winther
2015/06/17 09:36:28
Done.
|
| + // 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); |
| } |
| - if (identical(node.assignmentOperator.source, '=')) { |
| - addDynamicSendArgumentsToList(node, setterInputs); |
| - generateSuperSendSet(); |
| - stack.add(setterInputs.last); |
| + HInstruction getterInstruction; |
| + Selector getterSelector = |
| + elements.getGetterSelectorInComplexSendSet(node); |
| + if (Elements.isUnresolved(getter)) { |
| + generateSuperNoSuchMethodSend( |
| + node, |
| + getterSelector, |
| + getterInputs); |
| + getterInstruction = pop(); |
| } else { |
| - Element getter = elements[node.selector]; |
| - List<HInstruction> getterInputs = <HInstruction>[]; |
| - Link<ast.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; |
| - Selector getterSelector = |
| - elements.getGetterSelectorInComplexSendSet(node); |
| - if (Elements.isUnresolved(getter)) { |
| - generateSuperNoSuchMethodSend( |
| - node, |
| - getterSelector, |
| - getterInputs); |
| - getterInstruction = pop(); |
| - } else { |
| - getterInstruction = buildInvokeSuper( |
| - getterSelector, getter, getterInputs); |
| - add(getterInstruction); |
| - } |
| + getterInstruction = buildInvokeSuper( |
| + getterSelector, getter, getterInputs); |
| + add(getterInstruction); |
| + } |
| - if (node.isIfNullAssignment) { |
| - SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| - brancher.handleIfNull(() => stack.add(getterInstruction), |
| - () { |
| - addDynamicSendArgumentsToList(node, setterInputs); |
| - generateSuperSendSet(); |
| - stack.add(setterInputs.last); |
| - }); |
| + if (node.isIfNullAssignment) { |
| + SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| + brancher.handleIfNull(() => stack.add(getterInstruction), |
| + () { |
| + addDynamicSendArgumentsToList(node, setterInputs); |
| + generateSuperSendSet(); |
| + stack.add(setterInputs.last); |
| + }); |
| + } else { |
| + handleComplexOperatorSend(node, getterInstruction, arguments); |
| + setterInputs.add(pop()); |
| + generateSuperSendSet(); |
| + stack.add(node.isPostfix ? getterInstruction : setterInputs.last); |
| + } |
| + } |
| + } |
| + |
| + @override |
| + void visitIndexSet( |
| + ast.SendSet node, |
| + ast.Node receiver, |
| + ast.Node index, |
| + ast.Node rhs, |
| + _) { |
| + generateDynamicSend(node); |
| + } |
| + |
| + void handleIndexSendSet(ast.SendSet node) { |
| + ast.Operator op = node.assignmentOperator; |
| + if ("=" == op.source) { |
| + internalError(node, "Unexpected index set."); |
| + } else { |
| + visit(node.receiver); |
| + HInstruction receiver = pop(); |
| + Link<ast.Node> arguments = node.arguments; |
| + HInstruction index; |
| + if (node.isIndex) { |
| + visit(arguments.head); |
| + arguments = arguments.tail; |
| + index = pop(); |
| + } |
| + |
| + pushInvokeDynamic( |
| + node, |
| + elements.getGetterSelectorInComplexSendSet(node), |
| + [receiver, index]); |
| + HInstruction getterInstruction = pop(); |
| + if (node.isIfNullAssignment) { |
| + // Compile x[i] ??= e as: |
| + // t1 = x[i] |
| + // if (t1 == null) |
| + // t1 = x[i] = e; |
| + // result = t1 |
| + SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| + brancher.handleIfNull(() => stack.add(getterInstruction), |
| + () { |
| + visit(arguments.head); |
| + HInstruction value = pop(); |
| + pushInvokeDynamic( |
| + node, elements.getSelector(node), [receiver, index, value]); |
| + pop(); |
| + stack.add(value); |
| + }); |
| + } else { |
| + handleComplexOperatorSend(node, getterInstruction, arguments); |
| + HInstruction value = pop(); |
| + pushInvokeDynamic( |
| + node, elements.getSelector(node), [receiver, index, value]); |
| + pop(); |
| + if (node.isPostfix) { |
| + stack.add(getterInstruction); |
| } else { |
| - handleComplexOperatorSend(node, getterInstruction, arguments); |
| - setterInputs.add(pop()); |
| - generateSuperSendSet(); |
| - stack.add(node.isPostfix ? getterInstruction : setterInputs.last); |
| + stack.add(value); |
| } |
| } |
| - } else if (node.isIndex) { |
| - if ("=" == op.source) { |
| - generateDynamicSend(node); |
| + } |
| + } |
| + |
| + @override |
| + void visitThisPropertySet( |
| + ast.SendSet node, |
| + Selector selector, |
| + ast.Node rhs, |
| + _) { |
| + generateInstanceSetterWithCompiledReceiver( |
| + node, |
| + localsHandler.readThis(), |
| + visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitDynamicPropertySet( |
| + ast.SendSet node, |
| + ast.Node receiver, |
| + Selector selector, |
| + ast.Node rhs, |
| + _) { |
| + generateInstanceSetterWithCompiledReceiver( |
| + node, |
| + generateInstanceSendReceiver(node), |
| + visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitIfNotNullDynamicPropertySet( |
| + ast.SendSet node, |
| + ast.Node receiver, |
| + Selector selector, |
| + ast.Node rhs, |
| + _) { |
| + // compile e?.x = e2 to: |
| + // |
| + // t1 = e |
| + // if (t1 == null) |
| + // result = t1 // same as result = null |
| + // else |
| + // result = e.x = e2 |
| + HInstruction receiverInstruction; |
| + SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| + brancher.handleConditional( |
| + () { |
| + receiverInstruction = generateInstanceSendReceiver(node); |
| + pushCheckNull(receiverInstruction); |
| + }, |
| + () => stack.add(receiverInstruction), |
| + () { |
| + generateInstanceSetterWithCompiledReceiver( |
| + node, |
| + receiverInstruction, |
| + visitAndPop(rhs)); |
| + }); |
| + } |
| + |
| + @override |
| + void visitParameterSet( |
| + ast.SendSet node, |
| + ParameterElement parameter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, parameter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitFinalParameterSet( |
| + ast.SendSet node, |
| + ParameterElement parameter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, parameter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitLocalVariableSet( |
| + ast.SendSet node, |
| + LocalVariableElement variable, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, variable, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitFinalLocalVariableSet( |
| + ast.SendSet node, |
| + LocalVariableElement variable, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, variable, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitLocalFunctionSet( |
| + ast.SendSet node, |
| + LocalFunctionElement function, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, function, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitTopLevelFieldSet( |
| + ast.SendSet node, |
| + FieldElement field, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, field, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitFinalTopLevelFieldSet( |
| + ast.SendSet node, |
| + FieldElement field, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, field, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitTopLevelGetterSet( |
| + ast.SendSet node, |
| + GetterElement getter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, getter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitTopLevelSetterSet( |
| + ast.SendSet node, |
| + SetterElement setter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, setter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitTopLevelFunctionSet( |
| + ast.SendSet node, |
| + MethodElement function, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, function, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitStaticFieldSet( |
| + ast.SendSet node, |
| + FieldElement field, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, field, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitFinalStaticFieldSet( |
| + ast.SendSet node, |
| + FieldElement field, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, field, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitStaticGetterSet( |
| + ast.SendSet node, |
| + GetterElement getter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, getter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitStaticSetterSet( |
| + ast.SendSet node, |
| + SetterElement setter, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, setter, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitStaticFunctionSet( |
| + ast.SendSet node, |
| + MethodElement function, |
| + ast.Node rhs, |
| + _) { |
| + generateNonInstanceSetter(node, function, visitAndPop(rhs)); |
| + } |
| + |
| + @override |
| + void visitUnresolvedSet( |
| + ast.SendSet node, |
| + Element element, |
| + ast.Node rhs, |
| + _) { |
| + if (node.isSuperCall) { |
| + // TODO(johnniwinther): Remove this when final super field assignment is |
| + // not an unresolved set. |
| + handleSuperSendSet(node); |
| + } else { |
| + generateNonInstanceSetter(node, element, visitAndPop(rhs)); |
| + } |
| + } |
| + |
| + @override |
| + void visitClassTypeLiteralSet( |
| + ast.SendSet node, |
| + TypeConstantExpression constant, |
| + ast.Node rhs, |
| + _) { |
| + generateThrowNoSuchMethod(node, constant.type.name, |
| + argumentNodes: node.arguments); |
| + } |
| + |
| + @override |
| + void visitTypedefTypeLiteralSet( |
| + ast.SendSet node, |
| + TypeConstantExpression constant, |
| + ast.Node rhs, |
| + _) { |
| + generateThrowNoSuchMethod(node, constant.type.name, |
| + argumentNodes: node.arguments); |
| + } |
| + |
| + @override |
| + void visitDynamicTypeLiteralSet( |
| + ast.SendSet node, |
| + TypeConstantExpression constant, |
| + ast.Node rhs, |
| + _) { |
| + generateThrowNoSuchMethod(node, constant.type.name, |
| + argumentNodes: node.arguments); |
| + } |
| + |
| + @override |
| + void visitTypeVariableTypeLiteralSet( |
| + ast.SendSet node, |
| + TypeVariableElement element, |
| + ast.Node rhs, |
| + _) { |
| + generateThrowNoSuchMethod(node, element.name, |
| + argumentNodes: node.arguments); |
| + } |
| + |
| + void handleCompoundSendSet(ast.SendSet node) { |
| + Element element = elements[node]; |
| + Element getter = elements[node.selector]; |
| + |
| + if (!Elements.isUnresolved(getter) && getter.impliesType) { |
| + if (node.isIfNullAssignment) { |
| + // C ??= x is compiled just as C. |
| + stack.add(addConstant(node.selector)); |
| } else { |
| - visit(node.receiver); |
| - HInstruction receiver = pop(); |
| - Link<ast.Node> arguments = node.arguments; |
| - HInstruction index; |
| - if (node.isIndex) { |
| - visit(arguments.head); |
| - arguments = arguments.tail; |
| - index = pop(); |
| - } |
| + ast.Identifier selector = node.selector; |
| + generateThrowNoSuchMethod(node, selector.source, |
| + argumentNodes: node.arguments); |
| + } |
| + return; |
| + } |
| - pushInvokeDynamic( |
| - node, |
| - elements.getGetterSelectorInComplexSendSet(node), |
| - [receiver, index]); |
| + if (Elements.isInstanceSend(node, elements)) { |
| + void generateAssignment(HInstruction receiver) { |
| + // desugars `e.x op= e2` to `e.x = e.x op e2` |
| + generateInstanceGetterWithCompiledReceiver( |
| + node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
| HInstruction getterInstruction = pop(); |
| if (node.isIfNullAssignment) { |
| - // Compile x[i] ??= e as: |
| - // t1 = x[i] |
| - // if (t1 == null) |
| - // t1 = x[i] = e; |
| - // result = t1 |
| SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| brancher.handleIfNull(() => stack.add(getterInstruction), |
| () { |
| - visit(arguments.head); |
| - HInstruction value = pop(); |
| - pushInvokeDynamic( |
| - node, elements.getSelector(node), [receiver, index, value]); |
| - pop(); |
| - stack.add(value); |
| + visit(node.arguments.head); |
| + generateInstanceSetterWithCompiledReceiver( |
| + node, receiver, pop()); |
| }); |
| } else { |
| - handleComplexOperatorSend(node, getterInstruction, arguments); |
| + handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| HInstruction value = pop(); |
| - pushInvokeDynamic( |
| - node, elements.getSelector(node), [receiver, index, value]); |
| + generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
| + } |
| + if (node.isPostfix) { |
| pop(); |
| - if (node.isPostfix) { |
| - stack.add(getterInstruction); |
| - } else { |
| - stack.add(value); |
| - } |
| + stack.add(getterInstruction); |
| } |
| } |
| - } else if ("=" == op.source) { |
| - Link<ast.Node> link = node.arguments; |
| - assert(!link.isEmpty && link.tail.isEmpty); |
| - if (Elements.isInstanceSend(node, elements)) { |
| - generatePossiblyConditionalInstanceSetter(node, |
| - () => generateInstanceSendReceiver(node), |
| - () => visitAndPop(link.head)); |
| + if (node.isConditional) { |
| + // generate `e?.x op= e2` as: |
| + // t1 = e |
| + // t1 == null ? t1 : (t1.x = t1.x op e2); |
| + HInstruction receiver; |
| + SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| + brancher.handleConditional( |
| + () { |
| + receiver = generateInstanceSendReceiver(node); |
| + pushCheckNull(receiver); |
| + }, |
| + () => stack.add(receiver), |
| + () => generateAssignment(receiver)); |
| } else { |
| - visit(link.head); |
| - generateNonInstanceSetter(node, element, pop()); |
| + generateAssignment(generateInstanceSendReceiver(node)); |
| } |
| + return; |
| + } |
| + |
| + if (getter.isErroneous) { |
| + generateStaticUnresolvedGet(node, getter); |
| + } else if (getter.isField) { |
| + generateStaticFieldGet(node, getter); |
| + } else if (getter.isGetter) { |
| + generateStaticGetterGet(node, getter); |
| + } else if (getter.isFunction) { |
| + generateStaticFunctionGet(node, getter); |
| + } else if (getter.isLocal) { |
| + handleLocalGet(getter); |
| + } else { |
| + internalError(node, "Unexpected getter: $getter"); |
| + } |
| + HInstruction getterInstruction = pop(); |
| + if (node.isIfNullAssignment) { |
| + SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| + brancher.handleIfNull(() => stack.add(getterInstruction), |
| + () { |
| + visit(node.arguments.head); |
| + generateNonInstanceSetter(node, element, pop()); |
| + }); |
| + } else { |
| + handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| + HInstruction value = pop(); |
| + generateNonInstanceSetter(node, element, value); |
| + } |
| + if (node.isPostfix) { |
| + pop(); |
| + stack.add(getterInstruction); |
| + } |
| + } |
| + |
| + @override |
| + handleSendSet(ast.SendSet node) { |
| + ast.Operator op = node.assignmentOperator; |
| + generateIsDeferredLoadedCheckOfSend(node); |
| + Element element = elements[node]; |
| + if (!Elements.isUnresolved(element) && element.impliesType) { |
| + ast.Identifier selector = node.selector; |
| + generateThrowNoSuchMethod(node, selector.source, |
| + argumentNodes: node.arguments); |
| + } else if (node.isSuperCall) { |
| + handleSuperSendSet(node); |
| + } else if (node.isIndex) { |
| + handleIndexSendSet(node); |
| + } else if ("=" == op.source) { |
| + internalError(node, "Unexpected assignment."); |
| } else if (identical(op.source, "is")) { |
| compiler.internalError(op, "is-operator as SendSet."); |
| } else { |
| assert("++" == op.source || "--" == op.source || |
| node.assignmentOperator.source.endsWith("=")); |
| - |
| - Element getter = elements[node.selector]; |
| - |
| - if (!Elements.isUnresolved(getter) && getter.impliesType) { |
| - if (node.isIfNullAssignment) { |
| - // C ??= x is compiled just as C. |
| - stack.add(addConstant(node.selector)); |
| - } else { |
| - ast.Identifier selector = node.selector; |
| - generateThrowNoSuchMethod(node, selector.source, |
| - argumentNodes: node.arguments); |
| - } |
| - return; |
| - } |
| - |
| - if (Elements.isInstanceSend(node, elements)) { |
| - void generateAssignment(HInstruction receiver) { |
| - // desugars `e.x op= e2` to `e.x = e.x op e2` |
| - generateInstanceGetterWithCompiledReceiver( |
| - node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
| - HInstruction getterInstruction = pop(); |
| - if (node.isIfNullAssignment) { |
| - SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| - brancher.handleIfNull(() => stack.add(getterInstruction), |
| - () { |
| - visit(node.arguments.head); |
| - generateInstanceSetterWithCompiledReceiver( |
| - node, receiver, pop()); |
| - }); |
| - } else { |
| - handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| - HInstruction value = pop(); |
| - generateInstanceSetterWithCompiledReceiver(node, receiver, value); |
| - } |
| - if (node.isPostfix) { |
| - pop(); |
| - stack.add(getterInstruction); |
| - } |
| - } |
| - if (node.isConditional) { |
| - // generate `e?.x op= e2` as: |
| - // t1 = e |
| - // t1 == null ? t1 : (t1.x = t1.x op e2); |
| - HInstruction receiver; |
| - SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| - brancher.handleConditional( |
| - () { |
| - receiver = generateInstanceSendReceiver(node); |
| - pushCheckNull(receiver); |
| - }, |
| - () => stack.add(receiver), |
| - () => generateAssignment(receiver)); |
| - } else { |
| - generateAssignment(generateInstanceSendReceiver(node)); |
| - } |
| - return; |
| - } |
| - |
| - if (getter.isErroneous) { |
| - generateStaticUnresolvedGet(node, getter); |
| - } else if (getter.isField) { |
| - generateStaticFieldGet(node, getter); |
| - } else if (getter.isGetter) { |
| - generateStaticGetterGet(node, getter); |
| - } else if (getter.isFunction) { |
| - generateStaticFunctionGet(node, getter); |
| - } else if (getter.isLocal) { |
| - handleLocalGet(getter); |
| - } else { |
| - internalError(node, "Unexpected getter: $getter"); |
| - } |
| - HInstruction getterInstruction = pop(); |
| - if (node.isIfNullAssignment) { |
| - SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| - brancher.handleIfNull(() => stack.add(getterInstruction), |
| - () { |
| - visit(node.arguments.head); |
| - generateNonInstanceSetter(node, element, pop()); |
| - }); |
| - } else { |
| - handleComplexOperatorSend(node, getterInstruction, node.arguments); |
| - HInstruction value = pop(); |
| - generateNonInstanceSetter(node, element, value); |
| - } |
| - if (node.isPostfix) { |
| - pop(); |
| - stack.add(getterInstruction); |
| - } |
| + handleCompoundSendSet(node); |
| } |
| } |