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 2281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2292 Element fieldCheck = | 2292 Element fieldCheck = |
2293 parameterClosureData.parametersWithSentinel[element]; | 2293 parameterClosureData.parametersWithSentinel[element]; |
2294 stack.add(localsHandler.readLocal(fieldCheck)); | 2294 stack.add(localsHandler.readLocal(fieldCheck)); |
2295 return; | 2295 return; |
2296 } | 2296 } |
2297 assert(node.argumentsNode is Prefix); | 2297 assert(node.argumentsNode is Prefix); |
2298 visit(node.receiver); | 2298 visit(node.receiver); |
2299 assert(!identical(op.token.kind, PLUS_TOKEN)); | 2299 assert(!identical(op.token.kind, PLUS_TOKEN)); |
2300 HInstruction operand = pop(); | 2300 HInstruction operand = pop(); |
2301 | 2301 |
2302 HInstruction target = | |
2303 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | |
2304 add(target); | |
2305 HInvokeUnary result; | |
2306 String value = op.source.stringValue; | |
2307 switch (value) { | |
2308 case "-": result = new HNegate(target, operand); break; | |
2309 case "~": result = new HBitNot(target, operand); break; | |
2310 default: | |
2311 compiler.internalError('Unexpected unary operator: $value.', node: op); | |
2312 break; | |
2313 } | |
2314 // See if we can constant-fold right away. This avoids rewrites later on. | 2302 // See if we can constant-fold right away. This avoids rewrites later on. |
2315 if (operand is HConstant) { | 2303 if (operand is HConstant) { |
2304 UnaryOperation operation; | |
2305 String value = op.source.stringValue; | |
2306 switch (value) { | |
2307 case '-': operation = constantSystem.negate; break; | |
kasperl
2013/01/15 07:06:12
Maybe this code would be nicer to have on the cons
ngeoffray
2013/01/15 08:56:09
Done.
| |
2308 case '~': operation = constantSystem.bitNot; break; | |
2309 default: | |
2310 compiler.internalError('Unexpected unary operator: $value.', | |
2311 node: op); | |
2312 break; | |
2313 } | |
2314 | |
2316 HConstant constant = operand; | 2315 HConstant constant = operand; |
2317 Constant folded = | 2316 Constant folded = operation.fold(constant.constant); |
2318 result.operation(constantSystem).fold(constant.constant); | |
2319 if (folded != null) { | 2317 if (folded != null) { |
2320 stack.add(graph.addConstant(folded)); | 2318 stack.add(graph.addConstant(folded)); |
2321 return; | 2319 return; |
2322 } | 2320 } |
2323 } | 2321 } |
2322 | |
2323 HInvokeDynamicMethod result | |
2324 = buildInvokeDynamic(node, elements.getSelector(node), operand, []); | |
kasperl
2013/01/15 07:06:12
We usually put = on the previous line.
ngeoffray
2013/01/15 08:56:09
Done.
| |
2324 pushWithPosition(result, node); | 2325 pushWithPosition(result, node); |
2325 } | 2326 } |
2326 | 2327 |
2327 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 2328 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
2328 Element element = interceptors.getOperatorInterceptor(op); | 2329 Element element = interceptors.getOperatorInterceptor(op); |
2329 assert(element != null); | 2330 assert(element != null); |
2330 HInstruction target = new HStatic(element); | 2331 HInstruction target = new HStatic(element); |
2331 add(target); | 2332 add(target); |
2332 switch (op.source.stringValue) { | 2333 switch (op.source.stringValue) { |
2333 case "+": | 2334 case "+": |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3633 // on type arguments. | 3634 // on type arguments. |
3634 generateRuntimeError(node, '$type is malformed: $reasons'); | 3635 generateRuntimeError(node, '$type is malformed: $reasons'); |
3635 } else { | 3636 } else { |
3636 // TODO(karlklose): move this type registration to the codegen. | 3637 // TODO(karlklose): move this type registration to the codegen. |
3637 compiler.codegenWorld.instantiatedTypes.add(type); | 3638 compiler.codegenWorld.instantiatedTypes.add(type); |
3638 visitNewSend(node.send, type); | 3639 visitNewSend(node.send, type); |
3639 } | 3640 } |
3640 } | 3641 } |
3641 } | 3642 } |
3642 | 3643 |
3643 HInvokeDynamicMethod buildInvokeDynamicWithOneArgument( | 3644 HInvokeDynamicMethod buildInvokeDynamic(Node node, |
3644 Node node, Selector selector, HInstruction receiver, HInstruction arg0) { | 3645 Selector selector, |
3646 HInstruction receiver, | |
3647 List<HInstruction> arguments) { | |
3645 Set<ClassElement> interceptedClasses = | 3648 Set<ClassElement> interceptedClasses = |
3646 getInterceptedClassesOn(node, selector); | 3649 getInterceptedClassesOn(node, selector); |
3647 List<HInstruction> inputs = <HInstruction>[]; | 3650 List<HInstruction> inputs = <HInstruction>[]; |
3648 if (interceptedClasses != null) { | 3651 if (interceptedClasses != null) { |
3649 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); | 3652 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); |
3650 } | 3653 } |
3651 inputs.add(receiver); | 3654 inputs.add(receiver); |
3652 inputs.add(arg0); | 3655 inputs.addAll(arguments); |
3653 return new HInvokeDynamicMethod(selector, inputs); | 3656 return new HInvokeDynamicMethod(selector, inputs); |
3654 } | 3657 } |
3655 | 3658 |
3656 visitSendSet(SendSet node) { | 3659 visitSendSet(SendSet node) { |
3657 Element element = elements[node]; | 3660 Element element = elements[node]; |
3658 if (!Elements.isUnresolved(element) && element.impliesType()) { | 3661 if (!Elements.isUnresolved(element) && element.impliesType()) { |
3659 Identifier selector = node.selector; | 3662 Identifier selector = node.selector; |
3660 generateThrowNoSuchMethod(node, selector.source.slowToString(), | 3663 generateThrowNoSuchMethod(node, selector.source.slowToString(), |
3661 argumentNodes: node.arguments); | 3664 argumentNodes: node.arguments); |
3662 return; | 3665 return; |
3663 } | 3666 } |
3664 Operator op = node.assignmentOperator; | 3667 Operator op = node.assignmentOperator; |
3665 if (node.isSuperCall) { | 3668 if (node.isSuperCall) { |
3666 if (element == null) return generateSuperNoSuchMethodSend(node); | 3669 if (element == null) return generateSuperNoSuchMethodSend(node); |
3667 HInstruction target = new HStatic(element); | 3670 HInstruction target = new HStatic(element); |
3668 HInstruction context = localsHandler.readThis(); | 3671 HInstruction context = localsHandler.readThis(); |
3669 add(target); | 3672 add(target); |
3670 var inputs = <HInstruction>[target, context]; | 3673 var inputs = <HInstruction>[target, context]; |
3671 addDynamicSendArgumentsToList(node, inputs); | 3674 addDynamicSendArgumentsToList(node, inputs); |
3672 if (!identical(node.assignmentOperator.source.stringValue, '=')) { | 3675 if (!identical(node.assignmentOperator.source.stringValue, '=')) { |
3673 compiler.unimplemented('complex super assignment', | 3676 compiler.unimplemented('complex super assignment', |
3674 node: node.assignmentOperator); | 3677 node: node.assignmentOperator); |
3675 } | 3678 } |
3676 push(new HInvokeSuper(inputs, isSetter: true)); | 3679 push(new HInvokeSuper(inputs, isSetter: true)); |
3677 } else if (node.isIndex) { | 3680 } else if (node.isIndex) { |
3678 if (!methodInterceptionEnabled) { | 3681 if (!methodInterceptionEnabled) { |
3679 assert(identical(op.source.stringValue, '=')); | 3682 assert(identical(op.source.stringValue, '=')); |
3680 visitDynamicSend(node); | 3683 visitDynamicSend(node); |
3684 } else if (const SourceString("=") == op.source) { | |
3685 visitDynamicSend(node); | |
3686 HInvokeDynamicMethod method = pop(); | |
3687 // Push the value. | |
3688 stack.add(method.inputs.last); | |
3681 } else { | 3689 } else { |
3682 HStatic target = new HStatic( | |
3683 interceptors.getIndexAssignmentInterceptor()); | |
3684 add(target); | |
3685 visit(node.receiver); | 3690 visit(node.receiver); |
3686 HInstruction receiver = pop(); | 3691 HInstruction receiver = pop(); |
3687 visit(node.argumentsNode); | 3692 visit(node.argumentsNode); |
3688 if (const SourceString("=") == op.source) { | 3693 HInstruction value; |
3689 HInstruction value = pop(); | 3694 HInstruction index; |
3690 HInstruction index = pop(); | 3695 // Compound assignments are considered as being prefix. |
3691 add(new HIndexAssign(target, receiver, index, value)); | 3696 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
3697 bool isPrefix = !node.isPostfix; | |
3698 Element getter = elements[node.selector]; | |
3699 if (isCompoundAssignment) { | |
3700 value = pop(); | |
3701 index = pop(); | |
3702 } else { | |
3703 index = pop(); | |
3704 value = graph.addConstantInt(1, constantSystem); | |
3705 } | |
3706 | |
3707 HInvokeDynamicMethod left = buildInvokeDynamic( | |
3708 node, new Selector.index(), receiver, [index]); | |
3709 add(left); | |
3710 visitBinary(left, op, value); | |
3711 value = pop(); | |
3712 HInvokeDynamicMethod assign = buildInvokeDynamic( | |
3713 node, new Selector.indexSet(), receiver, [index, value]); | |
3714 add(assign); | |
3715 if (isPrefix) { | |
3692 stack.add(value); | 3716 stack.add(value); |
3693 } else { | 3717 } else { |
3694 HInstruction value; | 3718 stack.add(left); |
3695 HInstruction index; | |
3696 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | |
3697 // Compound assignments are considered as being prefix. | |
3698 bool isPrefix = !node.isPostfix; | |
3699 Element getter = elements[node.selector]; | |
3700 if (isCompoundAssignment) { | |
3701 value = pop(); | |
3702 index = pop(); | |
3703 } else { | |
3704 index = pop(); | |
3705 value = graph.addConstantInt(1, constantSystem); | |
3706 } | |
3707 | |
3708 HInvokeDynamicMethod left = buildInvokeDynamicWithOneArgument( | |
3709 node, new Selector.index(), receiver, index); | |
3710 add(left); | |
3711 Element opElement = elements[op]; | |
3712 visitBinary(left, op, value); | |
3713 value = pop(); | |
3714 HInstruction assign = new HIndexAssign( | |
3715 target, receiver, index, value); | |
3716 add(assign); | |
3717 if (isPrefix) { | |
3718 stack.add(value); | |
3719 } else { | |
3720 stack.add(left); | |
3721 } | |
3722 } | 3719 } |
3723 } | 3720 } |
3724 } else if (const SourceString("=") == op.source) { | 3721 } else if (const SourceString("=") == op.source) { |
3725 Element element = elements[node]; | 3722 Element element = elements[node]; |
3726 Link<Node> link = node.arguments; | 3723 Link<Node> link = node.arguments; |
3727 assert(!link.isEmpty && link.tail.isEmpty); | 3724 assert(!link.isEmpty && link.tail.isEmpty); |
3728 visit(link.head); | 3725 visit(link.head); |
3729 HInstruction value = pop(); | 3726 HInstruction value = pop(); |
3730 generateSetter(node, element, value); | 3727 generateSetter(node, element, value); |
3731 } else if (identical(op.source.stringValue, "is")) { | 3728 } else if (identical(op.source.stringValue, "is")) { |
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5101 new HSubGraphBlockInformation(elseBranch.graph)); | 5098 new HSubGraphBlockInformation(elseBranch.graph)); |
5102 | 5099 |
5103 HBasicBlock conditionStartBlock = conditionBranch.block; | 5100 HBasicBlock conditionStartBlock = conditionBranch.block; |
5104 conditionStartBlock.setBlockFlow(info, joinBlock); | 5101 conditionStartBlock.setBlockFlow(info, joinBlock); |
5105 SubGraph conditionGraph = conditionBranch.graph; | 5102 SubGraph conditionGraph = conditionBranch.graph; |
5106 HIf branch = conditionGraph.end.last; | 5103 HIf branch = conditionGraph.end.last; |
5107 assert(branch is HIf); | 5104 assert(branch is HIf); |
5108 branch.blockInformation = conditionStartBlock.blockFlow; | 5105 branch.blockInformation = conditionStartBlock.blockFlow; |
5109 } | 5106 } |
5110 } | 5107 } |
OLD | NEW |