| 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 |