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 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.
| |
| 3062 compiler.enqueuer.codegen.registerDynamicGetter(name, selector); | |
| 3063 } else if (selector.isSetter()) { | |
| 3064 compiler.enqueuer.codegen.registerDynamicSetter(name, selector); | |
| 3065 } else { | |
| 3066 compiler.enqueuer.codegen.registerDynamicInvocation(name, selector); | |
| 3067 } | |
| 3068 } | |
| 3060 HStatic target = new HStatic(element); | 3069 HStatic target = new HStatic(element); |
| 3061 add(target); | 3070 add(target); |
| 3062 HInstruction self = localsHandler.readThis(); | 3071 HInstruction self = localsHandler.readThis(); |
| 3063 Constant nameConstant = constantSystem.createString( | 3072 Constant nameConstant = constantSystem.createString( |
| 3064 new DartString.literal(name.slowToString()), node); | 3073 new DartString.literal(name.slowToString()), node); |
| 3065 | 3074 |
| 3066 String internalName = backend.namer.invocationName(selector); | 3075 String internalName = backend.namer.invocationName(selector); |
| 3067 Constant internalNameConstant = | 3076 Constant internalNameConstant = |
| 3068 constantSystem.createString(new DartString.literal(internalName), node); | 3077 constantSystem.createString(new DartString.literal(internalName), node); |
| 3069 | 3078 |
| 3070 Element createInvocationMirror = backend.getCreateInvocationMirror(); | 3079 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); | 3080 var argumentsInstruction = new HLiteralList(arguments); |
| 3077 add(argumentsInstruction); | 3081 add(argumentsInstruction); |
| 3078 | 3082 |
| 3079 var argumentNames = new List<HInstruction>(); | 3083 var argumentNames = new List<HInstruction>(); |
| 3080 for (SourceString argumentName in selector.namedArguments) { | 3084 for (SourceString argumentName in selector.namedArguments) { |
| 3081 Constant argumentNameConstant = | 3085 Constant argumentNameConstant = |
| 3082 constantSystem.createString(new DartString.literal( | 3086 constantSystem.createString(new DartString.literal( |
| 3083 argumentName.slowToString()), node); | 3087 argumentName.slowToString()), node); |
| 3084 argumentNames.add(graph.addConstant(argumentNameConstant)); | 3088 argumentNames.add(graph.addConstant(argumentNameConstant)); |
| 3085 } | 3089 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 3110 if (element != null && identical(element, currentElement)) { | 3114 if (element != null && identical(element, currentElement)) { |
| 3111 graph.isRecursiveMethod = true; | 3115 graph.isRecursiveMethod = true; |
| 3112 } | 3116 } |
| 3113 super.visitSend(node); | 3117 super.visitSend(node); |
| 3114 } | 3118 } |
| 3115 | 3119 |
| 3116 visitSuperSend(Send node) { | 3120 visitSuperSend(Send node) { |
| 3117 Selector selector = elements.getSelector(node); | 3121 Selector selector = elements.getSelector(node); |
| 3118 Element element = elements[node]; | 3122 Element element = elements[node]; |
| 3119 if (Elements.isUnresolved(element)) { | 3123 if (Elements.isUnresolved(element)) { |
| 3120 return generateSuperNoSuchMethodSend(node); | 3124 List<HInstruction> arguments = <HInstruction>[]; |
| 3125 if (!node.isPropertyAccess) { | |
| 3126 addGenericSendArgumentsToList(node.arguments, arguments); | |
| 3127 } | |
| 3128 return generateSuperNoSuchMethodSend(node, selector, arguments); | |
| 3121 } | 3129 } |
| 3122 // TODO(5346): Try to avoid the need for calling [declaration] before | 3130 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3123 // creating an [HStatic]. | 3131 // creating an [HStatic]. |
| 3124 HInstruction target = new HStatic(element.declaration); | 3132 HInstruction target = new HStatic(element.declaration); |
| 3125 HInstruction context = localsHandler.readThis(); | 3133 HInstruction context = localsHandler.readThis(); |
| 3126 add(target); | 3134 add(target); |
| 3127 var inputs = <HInstruction>[target, context]; | 3135 var inputs = <HInstruction>[target, context]; |
| 3128 if (backend.isInterceptedMethod(element)) { | 3136 if (backend.isInterceptedMethod(element)) { |
| 3129 inputs.add(context); | 3137 inputs.add(context); |
| 3130 } | 3138 } |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3581 | 3589 |
| 3582 visitSendSet(SendSet node) { | 3590 visitSendSet(SendSet node) { |
| 3583 Element element = elements[node]; | 3591 Element element = elements[node]; |
| 3584 if (!Elements.isUnresolved(element) && element.impliesType()) { | 3592 if (!Elements.isUnresolved(element) && element.impliesType()) { |
| 3585 Identifier selector = node.selector; | 3593 Identifier selector = node.selector; |
| 3586 generateThrowNoSuchMethod(node, selector.source.slowToString(), | 3594 generateThrowNoSuchMethod(node, selector.source.slowToString(), |
| 3587 argumentNodes: node.arguments); | 3595 argumentNodes: node.arguments); |
| 3588 return; | 3596 return; |
| 3589 } | 3597 } |
| 3590 Operator op = node.assignmentOperator; | 3598 Operator op = node.assignmentOperator; |
| 3591 if (node.isSuperCall) { | 3599 if (node.isSuperCall) { |
|
kasperl
2013/03/05 07:32:36
Think about if some of this could be shared with t
| |
| 3600 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.
| |
| 3601 List<HInstruction> setterInputs = <HInstruction>[]; | |
| 3602 HInstruction context = localsHandler.readThis(); | |
| 3603 if (!Elements.isUnresolved(element)) { | |
| 3604 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.
| |
| 3605 add(target); | |
| 3606 setterInputs.add(target); | |
| 3607 setterInputs.add(context); | |
| 3608 if (backend.isInterceptedMethod(element)) { | |
| 3609 setterInputs.add(context); | |
| 3610 } | |
| 3611 } | |
| 3612 if (identical(node.assignmentOperator.source.stringValue, '=')) { | |
| 3613 addDynamicSendArgumentsToList(node, setterInputs); | |
| 3614 toPush = setterInputs.last; | |
| 3615 } else { | |
| 3616 Element getter = elements[node.selector]; | |
| 3617 List<HInstruction> getterInputs = <HInstruction>[]; | |
| 3618 if (!Elements.isUnresolved(getter)) { | |
| 3619 HInstruction getterTarget = new HStatic(getter); | |
| 3620 add(getterTarget); | |
| 3621 getterInputs.add(getterTarget); | |
| 3622 getterInputs.add(context); | |
| 3623 if (backend.isInterceptedMethod(getter)) { | |
| 3624 getterInputs.add(context); | |
| 3625 } | |
| 3626 } | |
| 3627 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.
| |
| 3628 if (node.isIndex) { | |
| 3629 visit(arguments.head); | |
| 3630 arguments = arguments.tail; | |
| 3631 HInstruction index = pop(); | |
| 3632 getterInputs.add(index); | |
| 3633 setterInputs.add(index); | |
| 3634 } | |
| 3635 HInstruction getterInstruction; | |
|
kasperl
2013/03/05 07:32:36
Could this (the computation of the getterInstructi
ngeoffray
2013/03/05 08:46:25
Done.
| |
| 3636 if (Elements.isUnresolved(getter)) { | |
| 3637 generateSuperNoSuchMethodSend( | |
| 3638 node, | |
| 3639 elements.getGetterSelectorInComplexSendSet(node), | |
| 3640 getterInputs); | |
| 3641 getterInstruction = pop(); | |
| 3642 } else { | |
| 3643 getterInstruction = new HInvokeSuper(getterInputs); | |
| 3644 add(getterInstruction); | |
| 3645 } | |
| 3646 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.
| |
| 3647 if (node.isPrefix || node.isPostfix) { | |
| 3648 rhs = graph.addConstantInt(1, constantSystem); | |
| 3649 } else { | |
| 3650 visit(arguments.head); | |
| 3651 assert(arguments.tail.isEmpty); | |
| 3652 rhs = pop(); | |
| 3653 } | |
| 3654 visitBinary(getterInstruction, op, rhs, | |
| 3655 elements.getOperatorSelectorInComplexSendSet(node), node); | |
| 3656 setterInputs.add(pop()); | |
| 3657 | |
| 3658 if (node.isPostfix) { | |
| 3659 toPush = getterInstruction; | |
| 3660 } else { | |
| 3661 toPush = setterInputs.last; | |
| 3662 } | |
| 3663 } | |
| 3592 if (Elements.isUnresolved(element)) { | 3664 if (Elements.isUnresolved(element)) { |
| 3593 return generateSuperNoSuchMethodSend(node); | 3665 generateSuperNoSuchMethodSend( |
| 3666 node, elements.getSelector(node), setterInputs); | |
| 3667 pop(); | |
| 3668 } else { | |
| 3669 add(new HInvokeSuper(setterInputs, isSetter: true)); | |
| 3594 } | 3670 } |
| 3595 HInstruction target = new HStatic(element); | 3671 stack.add(toPush); |
| 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) { | 3672 } else if (node.isIndex) { |
| 3606 if (const SourceString("=") == op.source) { | 3673 if (const SourceString("=") == op.source) { |
| 3607 // TODO(kasperl): We temporarily disable inlining because the | 3674 // TODO(kasperl): We temporarily disable inlining because the |
| 3608 // code here cannot deal with it yet. | 3675 // code here cannot deal with it yet. |
| 3609 visitDynamicSend(node, inline: false); | 3676 visitDynamicSend(node, inline: false); |
| 3610 HInvokeDynamicMethod method = pop(); | 3677 HInvokeDynamicMethod method = pop(); |
| 3611 // Push the value. | 3678 // Push the value. |
| 3612 stack.add(method.inputs.last); | 3679 stack.add(method.inputs.last); |
| 3613 } else { | 3680 } else { |
| 3614 visit(node.receiver); | 3681 visit(node.receiver); |
| (...skipping 1420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5035 new HSubGraphBlockInformation(elseBranch.graph)); | 5102 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5036 | 5103 |
| 5037 HBasicBlock conditionStartBlock = conditionBranch.block; | 5104 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5038 conditionStartBlock.setBlockFlow(info, joinBlock); | 5105 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5039 SubGraph conditionGraph = conditionBranch.graph; | 5106 SubGraph conditionGraph = conditionBranch.graph; |
| 5040 HIf branch = conditionGraph.end.last; | 5107 HIf branch = conditionGraph.end.last; |
| 5041 assert(branch is HIf); | 5108 assert(branch is HIf); |
| 5042 branch.blockInformation = conditionStartBlock.blockFlow; | 5109 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5043 } | 5110 } |
| 5044 } | 5111 } |
| OLD | NEW |