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 = constantSystem.lookupUnary(op.source); |
2316 HConstant constant = operand; | 2305 HConstant constant = operand; |
2317 Constant folded = | 2306 Constant folded = operation.fold(constant.constant); |
2318 result.operation(constantSystem).fold(constant.constant); | |
2319 if (folded != null) { | 2307 if (folded != null) { |
2320 stack.add(graph.addConstant(folded)); | 2308 stack.add(graph.addConstant(folded)); |
2321 return; | 2309 return; |
2322 } | 2310 } |
2323 } | 2311 } |
| 2312 |
| 2313 HInvokeDynamicMethod result = |
| 2314 buildInvokeDynamic(node, elements.getSelector(node), operand, []); |
2324 pushWithPosition(result, node); | 2315 pushWithPosition(result, node); |
2325 } | 2316 } |
2326 | 2317 |
2327 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 2318 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
2328 Element element = interceptors.getOperatorInterceptor(op); | 2319 Element element = interceptors.getOperatorInterceptor(op); |
2329 assert(element != null); | 2320 assert(element != null); |
2330 HInstruction target = new HStatic(element); | 2321 HInstruction target = new HStatic(element); |
2331 add(target); | 2322 add(target); |
2332 switch (op.source.stringValue) { | 2323 switch (op.source.stringValue) { |
2333 case "+": | 2324 case "+": |
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3633 // on type arguments. | 3624 // on type arguments. |
3634 generateRuntimeError(node, '$type is malformed: $reasons'); | 3625 generateRuntimeError(node, '$type is malformed: $reasons'); |
3635 } else { | 3626 } else { |
3636 // TODO(karlklose): move this type registration to the codegen. | 3627 // TODO(karlklose): move this type registration to the codegen. |
3637 compiler.codegenWorld.instantiatedTypes.add(type); | 3628 compiler.codegenWorld.instantiatedTypes.add(type); |
3638 visitNewSend(node.send, type); | 3629 visitNewSend(node.send, type); |
3639 } | 3630 } |
3640 } | 3631 } |
3641 } | 3632 } |
3642 | 3633 |
3643 HInvokeDynamicMethod buildInvokeDynamicWithOneArgument( | 3634 HInvokeDynamicMethod buildInvokeDynamic(Node node, |
3644 Node node, Selector selector, HInstruction receiver, HInstruction arg0) { | 3635 Selector selector, |
| 3636 HInstruction receiver, |
| 3637 List<HInstruction> arguments) { |
3645 Set<ClassElement> interceptedClasses = | 3638 Set<ClassElement> interceptedClasses = |
3646 getInterceptedClassesOn(node, selector); | 3639 getInterceptedClassesOn(node, selector); |
3647 List<HInstruction> inputs = <HInstruction>[]; | 3640 List<HInstruction> inputs = <HInstruction>[]; |
3648 if (interceptedClasses != null) { | 3641 if (interceptedClasses != null) { |
3649 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); | 3642 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); |
3650 } | 3643 } |
3651 inputs.add(receiver); | 3644 inputs.add(receiver); |
3652 inputs.add(arg0); | 3645 inputs.addAll(arguments); |
3653 return new HInvokeDynamicMethod(selector, inputs); | 3646 return new HInvokeDynamicMethod(selector, inputs); |
3654 } | 3647 } |
3655 | 3648 |
3656 visitSendSet(SendSet node) { | 3649 visitSendSet(SendSet node) { |
3657 Element element = elements[node]; | 3650 Element element = elements[node]; |
3658 if (!Elements.isUnresolved(element) && element.impliesType()) { | 3651 if (!Elements.isUnresolved(element) && element.impliesType()) { |
3659 Identifier selector = node.selector; | 3652 Identifier selector = node.selector; |
3660 generateThrowNoSuchMethod(node, selector.source.slowToString(), | 3653 generateThrowNoSuchMethod(node, selector.source.slowToString(), |
3661 argumentNodes: node.arguments); | 3654 argumentNodes: node.arguments); |
3662 return; | 3655 return; |
3663 } | 3656 } |
3664 Operator op = node.assignmentOperator; | 3657 Operator op = node.assignmentOperator; |
3665 if (node.isSuperCall) { | 3658 if (node.isSuperCall) { |
3666 if (element == null) return generateSuperNoSuchMethodSend(node); | 3659 if (element == null) return generateSuperNoSuchMethodSend(node); |
3667 HInstruction target = new HStatic(element); | 3660 HInstruction target = new HStatic(element); |
3668 HInstruction context = localsHandler.readThis(); | 3661 HInstruction context = localsHandler.readThis(); |
3669 add(target); | 3662 add(target); |
3670 var inputs = <HInstruction>[target, context]; | 3663 var inputs = <HInstruction>[target, context]; |
3671 addDynamicSendArgumentsToList(node, inputs); | 3664 addDynamicSendArgumentsToList(node, inputs); |
3672 if (!identical(node.assignmentOperator.source.stringValue, '=')) { | 3665 if (!identical(node.assignmentOperator.source.stringValue, '=')) { |
3673 compiler.unimplemented('complex super assignment', | 3666 compiler.unimplemented('complex super assignment', |
3674 node: node.assignmentOperator); | 3667 node: node.assignmentOperator); |
3675 } | 3668 } |
3676 push(new HInvokeSuper(inputs, isSetter: true)); | 3669 push(new HInvokeSuper(inputs, isSetter: true)); |
3677 } else if (node.isIndex) { | 3670 } else if (node.isIndex) { |
3678 if (!methodInterceptionEnabled) { | 3671 if (!methodInterceptionEnabled) { |
3679 assert(identical(op.source.stringValue, '=')); | 3672 assert(identical(op.source.stringValue, '=')); |
3680 visitDynamicSend(node); | 3673 visitDynamicSend(node); |
| 3674 } else if (const SourceString("=") == op.source) { |
| 3675 visitDynamicSend(node); |
| 3676 HInvokeDynamicMethod method = pop(); |
| 3677 // Push the value. |
| 3678 stack.add(method.inputs.last); |
3681 } else { | 3679 } else { |
3682 HStatic target = new HStatic( | |
3683 interceptors.getIndexAssignmentInterceptor()); | |
3684 add(target); | |
3685 visit(node.receiver); | 3680 visit(node.receiver); |
3686 HInstruction receiver = pop(); | 3681 HInstruction receiver = pop(); |
3687 visit(node.argumentsNode); | 3682 visit(node.argumentsNode); |
3688 if (const SourceString("=") == op.source) { | 3683 HInstruction value; |
3689 HInstruction value = pop(); | 3684 HInstruction index; |
3690 HInstruction index = pop(); | 3685 // Compound assignments are considered as being prefix. |
3691 add(new HIndexAssign(target, receiver, index, value)); | 3686 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 3687 bool isPrefix = !node.isPostfix; |
| 3688 Element getter = elements[node.selector]; |
| 3689 if (isCompoundAssignment) { |
| 3690 value = pop(); |
| 3691 index = pop(); |
| 3692 } else { |
| 3693 index = pop(); |
| 3694 value = graph.addConstantInt(1, constantSystem); |
| 3695 } |
| 3696 |
| 3697 HInvokeDynamicMethod left = buildInvokeDynamic( |
| 3698 node, new Selector.index(), receiver, [index]); |
| 3699 add(left); |
| 3700 visitBinary(left, op, value); |
| 3701 value = pop(); |
| 3702 HInvokeDynamicMethod assign = buildInvokeDynamic( |
| 3703 node, new Selector.indexSet(), receiver, [index, value]); |
| 3704 add(assign); |
| 3705 if (isPrefix) { |
3692 stack.add(value); | 3706 stack.add(value); |
3693 } else { | 3707 } else { |
3694 HInstruction value; | 3708 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 } | 3709 } |
3723 } | 3710 } |
3724 } else if (const SourceString("=") == op.source) { | 3711 } else if (const SourceString("=") == op.source) { |
3725 Element element = elements[node]; | 3712 Element element = elements[node]; |
3726 Link<Node> link = node.arguments; | 3713 Link<Node> link = node.arguments; |
3727 assert(!link.isEmpty && link.tail.isEmpty); | 3714 assert(!link.isEmpty && link.tail.isEmpty); |
3728 visit(link.head); | 3715 visit(link.head); |
3729 HInstruction value = pop(); | 3716 HInstruction value = pop(); |
3730 generateSetter(node, element, value); | 3717 generateSetter(node, element, value); |
3731 } else if (identical(op.source.stringValue, "is")) { | 3718 } 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)); | 5088 new HSubGraphBlockInformation(elseBranch.graph)); |
5102 | 5089 |
5103 HBasicBlock conditionStartBlock = conditionBranch.block; | 5090 HBasicBlock conditionStartBlock = conditionBranch.block; |
5104 conditionStartBlock.setBlockFlow(info, joinBlock); | 5091 conditionStartBlock.setBlockFlow(info, joinBlock); |
5105 SubGraph conditionGraph = conditionBranch.graph; | 5092 SubGraph conditionGraph = conditionBranch.graph; |
5106 HIf branch = conditionGraph.end.last; | 5093 HIf branch = conditionGraph.end.last; |
5107 assert(branch is HIf); | 5094 assert(branch is HIf); |
5108 branch.blockInformation = conditionStartBlock.blockFlow; | 5095 branch.blockInformation = conditionStartBlock.blockFlow; |
5109 } | 5096 } |
5110 } | 5097 } |
OLD | NEW |