Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |