Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 12374094: Implement complex super assignment. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 3028 matching lines...) Expand 10 before | Expand all | Expand 10 after
3039 stack.add(addConstantString(node, backend.namer.operatorIsPrefix())); 3039 stack.add(addConstantString(node, backend.namer.operatorIsPrefix()));
3040 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) { 3040 } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
3041 stack.add(addConstantString(node, backend.namer.operatorAsPrefix())); 3041 stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
3042 } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) { 3042 } else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) {
3043 handleForeignDartObjectJsConstructorFunction(node); 3043 handleForeignDartObjectJsConstructorFunction(node);
3044 } else { 3044 } else {
3045 throw "Unknown foreign: ${selector}"; 3045 throw "Unknown foreign: ${selector}";
3046 } 3046 }
3047 } 3047 }
3048 3048
3049 generateSuperNoSuchMethodSend(Send node) { 3049 generateSuperNoSuchMethodSend(Send node,
3050 Selector selector = elements.getSelector(node); 3050 Selector selector,
3051 List<HInstruction> arguments) {
3051 SourceString name = selector.name; 3052 SourceString name = selector.name;
3052 3053
3053 ClassElement cls = currentElement.getEnclosingClass(); 3054 ClassElement cls = currentElement.getEnclosingClass();
3054 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); 3055 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD);
3055 if (element.enclosingElement.declaration != compiler.objectClass) { 3056 if (element.enclosingElement.declaration != compiler.objectClass) {
3056 // Register the call as dynamic if [:noSuchMethod:] on the super class 3057 // Register the call as dynamic if [:noSuchMethod:] on the super class
3057 // is _not_ the default implementation from [:Object:]. 3058 // is _not_ the default implementation from [:Object:], in case
3058 compiler.enqueuer.codegen.registerDynamicInvocation(name, selector); 3059 // the [:noSuchMethod:] implementation does an [:invokeOn:] on
3059 } 3060 // the invocation mirror.
3061 compiler.enqueuer.codegen.registerSelectorUse(selector);
3062 }
3060 HStatic target = new HStatic(element); 3063 HStatic target = new HStatic(element);
3061 add(target); 3064 add(target);
3062 HInstruction self = localsHandler.readThis(); 3065 HInstruction self = localsHandler.readThis();
3063 Constant nameConstant = constantSystem.createString( 3066 Constant nameConstant = constantSystem.createString(
3064 new DartString.literal(name.slowToString()), node); 3067 new DartString.literal(name.slowToString()), node);
3065 3068
3066 String internalName = backend.namer.invocationName(selector); 3069 String internalName = backend.namer.invocationName(selector);
3067 Constant internalNameConstant = 3070 Constant internalNameConstant =
3068 constantSystem.createString(new DartString.literal(internalName), node); 3071 constantSystem.createString(new DartString.literal(internalName), node);
3069 3072
3070 Element createInvocationMirror = backend.getCreateInvocationMirror(); 3073 Element createInvocationMirror = backend.getCreateInvocationMirror();
3071
3072 var arguments = new List<HInstruction>();
3073 if (node.argumentsNode != null) {
3074 addGenericSendArgumentsToList(node.arguments, arguments);
3075 }
3076 var argumentsInstruction = new HLiteralList(arguments); 3074 var argumentsInstruction = new HLiteralList(arguments);
3077 add(argumentsInstruction); 3075 add(argumentsInstruction);
3078 3076
3079 var argumentNames = new List<HInstruction>(); 3077 var argumentNames = new List<HInstruction>();
3080 for (SourceString argumentName in selector.namedArguments) { 3078 for (SourceString argumentName in selector.namedArguments) {
3081 Constant argumentNameConstant = 3079 Constant argumentNameConstant =
3082 constantSystem.createString(new DartString.literal( 3080 constantSystem.createString(new DartString.literal(
3083 argumentName.slowToString()), node); 3081 argumentName.slowToString()), node);
3084 argumentNames.add(graph.addConstant(argumentNameConstant)); 3082 argumentNames.add(graph.addConstant(argumentNameConstant));
3085 } 3083 }
(...skipping 24 matching lines...) Expand all
3110 if (element != null && identical(element, currentElement)) { 3108 if (element != null && identical(element, currentElement)) {
3111 graph.isRecursiveMethod = true; 3109 graph.isRecursiveMethod = true;
3112 } 3110 }
3113 super.visitSend(node); 3111 super.visitSend(node);
3114 } 3112 }
3115 3113
3116 visitSuperSend(Send node) { 3114 visitSuperSend(Send node) {
3117 Selector selector = elements.getSelector(node); 3115 Selector selector = elements.getSelector(node);
3118 Element element = elements[node]; 3116 Element element = elements[node];
3119 if (Elements.isUnresolved(element)) { 3117 if (Elements.isUnresolved(element)) {
3120 return generateSuperNoSuchMethodSend(node); 3118 List<HInstruction> arguments = <HInstruction>[];
3119 if (!node.isPropertyAccess) {
3120 addGenericSendArgumentsToList(node.arguments, arguments);
3121 }
3122 return generateSuperNoSuchMethodSend(node, selector, arguments);
3121 } 3123 }
3122 // TODO(5346): Try to avoid the need for calling [declaration] before 3124 List<HInstruction> inputs = buildSuperAccessorInputs(element);
3123 // creating an [HStatic].
3124 HInstruction target = new HStatic(element.declaration);
3125 HInstruction context = localsHandler.readThis();
3126 add(target);
3127 var inputs = <HInstruction>[target, context];
3128 if (backend.isInterceptedMethod(element)) {
3129 inputs.add(context);
3130 }
3131 if (node.isPropertyAccess) { 3125 if (node.isPropertyAccess) {
3132 push(new HInvokeSuper(inputs)); 3126 push(new HInvokeSuper(inputs));
3133 } else if (element.isFunction() || element.isGenerativeConstructor()) { 3127 } else if (element.isFunction() || element.isGenerativeConstructor()) {
3134 // TODO(5347): Try to avoid the need for calling [implementation] before 3128 // TODO(5347): Try to avoid the need for calling [implementation] before
3135 // calling [addStaticSendArgumentsToList]. 3129 // calling [addStaticSendArgumentsToList].
3136 FunctionElement function = element.implementation; 3130 FunctionElement function = element.implementation;
3137 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 3131 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
3138 function, inputs); 3132 function, inputs);
3139 if (!succeeded) { 3133 if (!succeeded) {
3140 generateWrongArgumentCountError(node, element, node.arguments); 3134 generateWrongArgumentCountError(node, element, node.arguments);
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
3572 bool isIntercepted = interceptedClasses != null; 3566 bool isIntercepted = interceptedClasses != null;
3573 if (isIntercepted) { 3567 if (isIntercepted) {
3574 assert(!interceptedClasses.isEmpty); 3568 assert(!interceptedClasses.isEmpty);
3575 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); 3569 inputs.add(invokeInterceptor(interceptedClasses, receiver, node));
3576 } 3570 }
3577 inputs.add(receiver); 3571 inputs.add(receiver);
3578 inputs.addAll(arguments); 3572 inputs.addAll(arguments);
3579 return new HInvokeDynamicMethod(selector, inputs, isIntercepted); 3573 return new HInvokeDynamicMethod(selector, inputs, isIntercepted);
3580 } 3574 }
3581 3575
3576 void handleComplexOperatorSend(SendSet node,
3577 HInstruction receiver,
3578 Link<Node> arguments) {
3579 HInstruction rhs;
3580 if (node.isPrefix || node.isPostfix) {
3581 rhs = graph.addConstantInt(1, constantSystem);
3582 } else {
3583 visit(arguments.head);
3584 assert(arguments.tail.isEmpty);
3585 rhs = pop();
3586 }
3587 visitBinary(receiver, node.assignmentOperator, rhs,
3588 elements.getOperatorSelectorInComplexSendSet(node), node);
3589 }
3590
3591 List<HInstruction> buildSuperAccessorInputs(Element element) {
3592 List<HInstruction> inputs = <HInstruction>[];
3593 if (Elements.isUnresolved(element)) return inputs;
3594 // TODO(5346): Try to avoid the need for calling [declaration] before
3595 // creating an [HStatic].
3596 HInstruction target = new HStatic(element.declaration);
3597 add(target);
3598 inputs.add(target);
3599 HInstruction context = localsHandler.readThis();
3600 inputs.add(context);
3601 if (backend.isInterceptedMethod(element)) {
3602 inputs.add(context);
3603 }
3604 return inputs;
3605 }
3606
kasperl 2013/03/05 08:57:42 Too many newlines.
3607
3582 visitSendSet(SendSet node) { 3608 visitSendSet(SendSet node) {
3583 Element element = elements[node]; 3609 Element element = elements[node];
3584 if (!Elements.isUnresolved(element) && element.impliesType()) { 3610 if (!Elements.isUnresolved(element) && element.impliesType()) {
3585 Identifier selector = node.selector; 3611 Identifier selector = node.selector;
3586 generateThrowNoSuchMethod(node, selector.source.slowToString(), 3612 generateThrowNoSuchMethod(node, selector.source.slowToString(),
3587 argumentNodes: node.arguments); 3613 argumentNodes: node.arguments);
3588 return; 3614 return;
3589 } 3615 }
3590 Operator op = node.assignmentOperator; 3616 Operator op = node.assignmentOperator;
3591 if (node.isSuperCall) { 3617 if (node.isSuperCall) {
3618 HInstruction result;
3619 List<HInstruction> setterInputs = buildSuperAccessInputs(element);
3620 if (identical(node.assignmentOperator.source.stringValue, '=')) {
3621 addDynamicSendArgumentsToList(node, setterInputs);
3622 result = setterInputs.last;
3623 } else {
3624 Element getter = elements[node.selector];
3625 List<HInstruction> getterInputs = buildSuperAccessInputs(getter);
3626 Link<Node> arguments = node.arguments;
3627 if (node.isIndex) {
3628 // If node is of the from [:super.foo[0] += 2:], the send has
3629 // two arguments: the index and the left hand side. We get
3630 // the index and add it as input of the getter and the
3631 // setter.
3632 visit(arguments.head);
3633 arguments = arguments.tail;
3634 HInstruction index = pop();
3635 getterInputs.add(index);
3636 setterInputs.add(index);
3637 }
3638 HInstruction getterInstruction;
3639 if (Elements.isUnresolved(getter)) {
3640 generateSuperNoSuchMethodSend(
3641 node,
3642 elements.getGetterSelectorInComplexSendSet(node),
3643 getterInputs);
3644 getterInstruction = pop();
3645 } else {
3646 getterInstruction = new HInvokeSuper(getterInputs);
3647 add(getterInstruction);
3648 }
3649 handleComplexOperatorSend(node, getterInstruction, arguments);
3650 setterInputs.add(pop());
3651
3652 if (node.isPostfix) {
3653 result = getterInstruction;
3654 } else {
3655 result = setterInputs.last;
3656 }
3657 }
3592 if (Elements.isUnresolved(element)) { 3658 if (Elements.isUnresolved(element)) {
3593 return generateSuperNoSuchMethodSend(node); 3659 generateSuperNoSuchMethodSend(
3660 node, elements.getSelector(node), setterInputs);
3661 pop();
3662 } else {
3663 add(new HInvokeSuper(setterInputs, isSetter: true));
3594 } 3664 }
3595 HInstruction target = new HStatic(element); 3665 stack.add(result);
3596 HInstruction context = localsHandler.readThis();
3597 add(target);
3598 var inputs = <HInstruction>[target, context];
3599 addDynamicSendArgumentsToList(node, inputs);
3600 if (!identical(node.assignmentOperator.source.stringValue, '=')) {
3601 compiler.unimplemented('complex super assignment',
3602 node: node.assignmentOperator);
3603 }
3604 push(new HInvokeSuper(inputs, isSetter: true));
3605 } else if (node.isIndex) { 3666 } else if (node.isIndex) {
3606 if (const SourceString("=") == op.source) { 3667 if (const SourceString("=") == op.source) {
3607 // TODO(kasperl): We temporarily disable inlining because the 3668 // TODO(kasperl): We temporarily disable inlining because the
3608 // code here cannot deal with it yet. 3669 // code here cannot deal with it yet.
3609 visitDynamicSend(node, inline: false); 3670 visitDynamicSend(node, inline: false);
3610 HInvokeDynamicMethod method = pop(); 3671 HInvokeDynamicMethod method = pop();
3611 // Push the value. 3672 // Push the value.
3612 stack.add(method.inputs.last); 3673 stack.add(method.inputs.last);
3613 } else { 3674 } else {
3614 visit(node.receiver); 3675 visit(node.receiver);
3615 HInstruction receiver = pop(); 3676 HInstruction receiver = pop();
3616 visit(node.argumentsNode); 3677 Link<Node> arguments = node.arguments;
3617 HInstruction value;
3618 HInstruction index; 3678 HInstruction index;
3619 // Compound assignments are considered as being prefix. 3679 if (node.isIndex) {
3620 bool isCompoundAssignment = op.source.stringValue.endsWith('='); 3680 visit(arguments.head);
3621 bool isPrefix = !node.isPostfix; 3681 arguments = arguments.tail;
3622 if (isCompoundAssignment) {
3623 value = pop();
3624 index = pop(); 3682 index = pop();
3625 } else {
3626 index = pop();
3627 value = graph.addConstantInt(1, constantSystem);
3628 } 3683 }
3629 3684
3630 HInvokeDynamicMethod left = buildInvokeDynamic( 3685 HInvokeDynamicMethod getterInstruction = buildInvokeDynamic(
3631 node, 3686 node,
3632 elements.getGetterSelectorInComplexSendSet(node), 3687 elements.getGetterSelectorInComplexSendSet(node),
3633 receiver, 3688 receiver,
3634 <HInstruction>[index]); 3689 <HInstruction>[index]);
3635 add(left); 3690 add(getterInstruction);
3636 visitBinary(left, op, value, 3691
3637 elements.getOperatorSelectorInComplexSendSet(node), node); 3692 handleComplexOperatorSend(node, getterInstruction, arguments);
3638 value = pop(); 3693 HInstruction value = pop();
3694
3639 HInvokeDynamicMethod assign = buildInvokeDynamic( 3695 HInvokeDynamicMethod assign = buildInvokeDynamic(
3640 node, elements.getSelector(node), receiver, [index, value]); 3696 node, elements.getSelector(node), receiver, [index, value]);
3641 add(assign); 3697 add(assign);
3642 if (isPrefix) { 3698
3699 if (node.isPostfix) {
3700 stack.add(getterInstruction);
3701 } else {
3643 stack.add(value); 3702 stack.add(value);
3644 } else {
3645 stack.add(left);
3646 } 3703 }
3647 } 3704 }
3648 } else if (const SourceString("=") == op.source) { 3705 } else if (const SourceString("=") == op.source) {
3649 Link<Node> link = node.arguments; 3706 Link<Node> link = node.arguments;
3650 assert(!link.isEmpty && link.tail.isEmpty); 3707 assert(!link.isEmpty && link.tail.isEmpty);
3651 visit(link.head); 3708 visit(link.head);
3652 HInstruction value = pop(); 3709 HInstruction value = pop();
3653 generateSetter(node, element, value); 3710 generateSetter(node, element, value);
3654 } else if (identical(op.source.stringValue, "is")) { 3711 } else if (identical(op.source.stringValue, "is")) {
3655 compiler.internalError("is-operator as SendSet", node: op); 3712 compiler.internalError("is-operator as SendSet", node: op);
3656 } else { 3713 } else {
3657 assert(const SourceString("++") == op.source || 3714 assert(const SourceString("++") == op.source ||
3658 const SourceString("--") == op.source || 3715 const SourceString("--") == op.source ||
3659 node.assignmentOperator.source.stringValue.endsWith("=")); 3716 node.assignmentOperator.source.stringValue.endsWith("="));
3660 bool isCompoundAssignment = !node.arguments.isEmpty;
3661 bool isPrefix = !node.isPostfix; // Compound assignments are prefix.
3662 3717
3663 // [receiver] is only used if the node is an instance send. 3718 // [receiver] is only used if the node is an instance send.
3664 HInstruction receiver = null; 3719 HInstruction receiver = null;
3665 if (Elements.isInstanceSend(node, elements)) { 3720 if (Elements.isInstanceSend(node, elements)) {
3666 receiver = generateInstanceSendReceiver(node); 3721 receiver = generateInstanceSendReceiver(node);
3667 generateInstanceGetterWithCompiledReceiver( 3722 generateInstanceGetterWithCompiledReceiver(
3668 node, elements.getGetterSelectorInComplexSendSet(node), receiver); 3723 node, elements.getGetterSelectorInComplexSendSet(node), receiver);
3669 } else { 3724 } else {
3670 generateGetter(node, elements[node.selector]); 3725 generateGetter(node, elements[node.selector]);
3671 } 3726 }
3672 HInstruction left = pop(); 3727 HInstruction getterInstruction = pop();
3673 HInstruction right; 3728 handleComplexOperatorSend(node, getterInstruction, node.arguments);
3674 if (isCompoundAssignment) { 3729 HInstruction value = pop();
3675 visit(node.argumentsNode); 3730 assert(value != null);
3676 right = pop();
3677 } else {
3678 right = graph.addConstantInt(1, constantSystem);
3679 }
3680 visitBinary(left, op, right,
3681 elements.getOperatorSelectorInComplexSendSet(node), node);
3682 HInstruction operation = pop();
3683 assert(operation != null);
3684 if (Elements.isInstanceSend(node, elements)) { 3731 if (Elements.isInstanceSend(node, elements)) {
3685 assert(receiver != null); 3732 assert(receiver != null);
3686 generateInstanceSetterWithCompiledReceiver(node, receiver, operation); 3733 generateInstanceSetterWithCompiledReceiver(node, receiver, value);
3687 } else { 3734 } else {
3688 assert(receiver == null); 3735 assert(receiver == null);
3689 generateSetter(node, element, operation); 3736 generateSetter(node, element, value);
3690 } 3737 }
3691 if (!isPrefix) { 3738 if (!node.isPostfix) {
3692 pop(); 3739 pop();
3693 stack.add(left); 3740 stack.add(getterInstruction);
3694 } 3741 }
3695 } 3742 }
3696 } 3743 }
3697 3744
3698 void visitLiteralInt(LiteralInt node) { 3745 void visitLiteralInt(LiteralInt node) {
3699 stack.add(graph.addConstantInt(node.value, constantSystem)); 3746 stack.add(graph.addConstantInt(node.value, constantSystem));
3700 } 3747 }
3701 3748
3702 void visitLiteralDouble(LiteralDouble node) { 3749 void visitLiteralDouble(LiteralDouble node) {
3703 stack.add(graph.addConstantDouble(node.value, constantSystem)); 3750 stack.add(graph.addConstantDouble(node.value, constantSystem));
(...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after
5035 new HSubGraphBlockInformation(elseBranch.graph)); 5082 new HSubGraphBlockInformation(elseBranch.graph));
5036 5083
5037 HBasicBlock conditionStartBlock = conditionBranch.block; 5084 HBasicBlock conditionStartBlock = conditionBranch.block;
5038 conditionStartBlock.setBlockFlow(info, joinBlock); 5085 conditionStartBlock.setBlockFlow(info, joinBlock);
5039 SubGraph conditionGraph = conditionBranch.graph; 5086 SubGraph conditionGraph = conditionBranch.graph;
5040 HIf branch = conditionGraph.end.last; 5087 HIf branch = conditionGraph.end.last;
5041 assert(branch is HIf); 5088 assert(branch is HIf);
5042 branch.blockInformation = conditionStartBlock.blockFlow; 5089 branch.blockInformation = conditionStartBlock.blockFlow;
5043 } 5090 }
5044 } 5091 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698