| 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 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 if (name == const SourceString('==')) { | 933 if (name == const SourceString('==')) { |
| 934 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 934 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 935 handleIf( | 935 handleIf( |
| 936 function, | 936 function, |
| 937 () { | 937 () { |
| 938 HParameterValue parameter = parameters.values.first; | 938 HParameterValue parameter = parameters.values.first; |
| 939 push(new HIdentity( | 939 push(new HIdentity( |
| 940 parameter, graph.addConstantNull(constantSystem))); | 940 parameter, graph.addConstantNull(constantSystem))); |
| 941 }, | 941 }, |
| 942 () { | 942 () { |
| 943 HReturn ret = new HReturn( | 943 closeAndGotoExit(new HReturn( |
| 944 graph.addConstantBool(false, constantSystem)); | 944 graph.addConstantBool(false, constantSystem))); |
| 945 close(ret).addSuccessor(graph.exit); | |
| 946 }, | 945 }, |
| 947 null); | 946 null); |
| 948 } | 947 } |
| 949 } | 948 } |
| 950 function.body.accept(this); | 949 function.body.accept(this); |
| 951 return closeFunction(); | 950 return closeFunction(); |
| 952 } | 951 } |
| 953 | 952 |
| 954 HGraph buildLazyInitializer(VariableElement variable) { | 953 HGraph buildLazyInitializer(VariableElement variable) { |
| 955 SendSet node = variable.parseNode(compiler); | 954 SendSet node = variable.parseNode(compiler); |
| 956 openFunction(variable, node); | 955 openFunction(variable, node); |
| 957 Link<Node> link = node.arguments; | 956 Link<Node> link = node.arguments; |
| 958 assert(!link.isEmpty && link.tail.isEmpty); | 957 assert(!link.isEmpty && link.tail.isEmpty); |
| 959 visit(link.head); | 958 visit(link.head); |
| 960 HInstruction value = pop(); | 959 HInstruction value = pop(); |
| 961 value = potentiallyCheckType(value, variable.computeType(compiler)); | 960 value = potentiallyCheckType(value, variable.computeType(compiler)); |
| 962 close(new HReturn(value)).addSuccessor(graph.exit); | 961 closeAndGotoExit(new HReturn(value)); |
| 963 return closeFunction(); | 962 return closeFunction(); |
| 964 } | 963 } |
| 965 | 964 |
| 966 /** | 965 /** |
| 967 * Returns the constructor body associated with the given constructor or | 966 * Returns the constructor body associated with the given constructor or |
| 968 * creates a new constructor body, if none can be found. | 967 * creates a new constructor body, if none can be found. |
| 969 * | 968 * |
| 970 * Returns [:null:] if the constructor does not have a body. | 969 * Returns [:null:] if the constructor does not have a body. |
| 971 */ | 970 */ |
| 972 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 971 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 // these selectors. Maybe the resolver can do more of the work | 1528 // these selectors. Maybe the resolver can do more of the work |
| 1530 // for us here? | 1529 // for us here? |
| 1531 LibraryElement library = body.getLibrary(); | 1530 LibraryElement library = body.getLibrary(); |
| 1532 Selector selector = new Selector.call( | 1531 Selector selector = new Selector.call( |
| 1533 name, library, bodyCallInputs.length - 1); | 1532 name, library, bodyCallInputs.length - 1); |
| 1534 HInvokeDynamic invoke = | 1533 HInvokeDynamic invoke = |
| 1535 new HInvokeDynamicMethod(selector, bodyCallInputs); | 1534 new HInvokeDynamicMethod(selector, bodyCallInputs); |
| 1536 invoke.element = body; | 1535 invoke.element = body; |
| 1537 add(invoke); | 1536 add(invoke); |
| 1538 } | 1537 } |
| 1539 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1538 closeAndGotoExit(new HReturn(newObject)); |
| 1540 return closeFunction(); | 1539 return closeFunction(); |
| 1541 } | 1540 } |
| 1542 | 1541 |
| 1543 void addParameterCheckInstruction(Element element) { | 1542 void addParameterCheckInstruction(Element element) { |
| 1544 HInstruction check; | 1543 HInstruction check; |
| 1545 Element checkResultElement = | 1544 Element checkResultElement = |
| 1546 localsHandler.closureData.parametersWithSentinel[element]; | 1545 localsHandler.closureData.parametersWithSentinel[element]; |
| 1547 if (currentElement.isGenerativeConstructorBody()) { | 1546 if (currentElement.isGenerativeConstructorBody()) { |
| 1548 // A generative constructor body receives extra parameters that | 1547 // A generative constructor body receives extra parameters that |
| 1549 // indicate if a parameter was passed to the factory. | 1548 // indicate if a parameter was passed to the factory. |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 HInstruction original, DartType type, | 1656 HInstruction original, DartType type, |
| 1658 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 1657 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
| 1659 if (!compiler.enableTypeAssertions) return original; | 1658 if (!compiler.enableTypeAssertions) return original; |
| 1660 HInstruction other = original.convertType(compiler, type, kind); | 1659 HInstruction other = original.convertType(compiler, type, kind); |
| 1661 if (other != original) add(other); | 1660 if (other != original) add(other); |
| 1662 return other; | 1661 return other; |
| 1663 } | 1662 } |
| 1664 | 1663 |
| 1665 HGraph closeFunction() { | 1664 HGraph closeFunction() { |
| 1666 // TODO(kasperl): Make this goto an implicit return. | 1665 // TODO(kasperl): Make this goto an implicit return. |
| 1667 if (!isAborted()) close(new HGoto()).addSuccessor(graph.exit); | 1666 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 1668 graph.finalize(); | 1667 graph.finalize(); |
| 1669 return graph; | 1668 return graph; |
| 1670 } | 1669 } |
| 1671 | 1670 |
| 1672 HBasicBlock addNewBlock() { | 1671 HBasicBlock addNewBlock() { |
| 1673 HBasicBlock block = graph.addNewBlock(); | 1672 HBasicBlock block = graph.addNewBlock(); |
| 1674 // If adding a new block during building of an expression, it is due to | 1673 // If adding a new block during building of an expression, it is due to |
| 1675 // conditional expressions or short-circuit logical operators. | 1674 // conditional expressions or short-circuit logical operators. |
| 1676 return block; | 1675 return block; |
| 1677 } | 1676 } |
| 1678 | 1677 |
| 1679 void open(HBasicBlock block) { | 1678 void open(HBasicBlock block) { |
| 1680 block.open(); | 1679 block.open(); |
| 1681 current = block; | 1680 current = block; |
| 1682 lastOpenedBlock = block; | 1681 lastOpenedBlock = block; |
| 1683 } | 1682 } |
| 1684 | 1683 |
| 1685 HBasicBlock close(HControlFlow end) { | 1684 HBasicBlock close(HControlFlow end) { |
| 1686 HBasicBlock result = current; | 1685 HBasicBlock result = current; |
| 1687 current.close(end); | 1686 current.close(end); |
| 1688 current = null; | 1687 current = null; |
| 1689 return result; | 1688 return result; |
| 1690 } | 1689 } |
| 1691 | 1690 |
| 1691 HBasicBlock closeAndGotoExit(HControlFlow end) { |
| 1692 HBasicBlock result = current; |
| 1693 current.close(end); |
| 1694 current = null; |
| 1695 result.addSuccessor(graph.exit); |
| 1696 return result; |
| 1697 } |
| 1698 |
| 1692 void goto(HBasicBlock from, HBasicBlock to) { | 1699 void goto(HBasicBlock from, HBasicBlock to) { |
| 1693 from.close(new HGoto()); | 1700 from.close(new HGoto()); |
| 1694 from.addSuccessor(to); | 1701 from.addSuccessor(to); |
| 1695 } | 1702 } |
| 1696 | 1703 |
| 1697 bool isAborted() { | 1704 bool isAborted() { |
| 1698 return _current == null; | 1705 return _current == null; |
| 1699 } | 1706 } |
| 1700 | 1707 |
| 1701 /** | 1708 /** |
| (...skipping 2218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3920 visit(node.expression); | 3927 visit(node.expression); |
| 3921 value = pop(); | 3928 value = pop(); |
| 3922 value = potentiallyCheckType(value, returnType); | 3929 value = potentiallyCheckType(value, returnType); |
| 3923 } | 3930 } |
| 3924 | 3931 |
| 3925 handleInTryStatement(); | 3932 handleInTryStatement(); |
| 3926 | 3933 |
| 3927 if (!inliningStack.isEmpty) { | 3934 if (!inliningStack.isEmpty) { |
| 3928 localsHandler.updateLocal(returnElement, value); | 3935 localsHandler.updateLocal(returnElement, value); |
| 3929 } else { | 3936 } else { |
| 3930 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | 3937 closeAndGotoExit(attachPosition(new HReturn(value), node)); |
| 3931 } | 3938 } |
| 3932 } | 3939 } |
| 3933 | 3940 |
| 3934 visitThrow(Throw node) { | 3941 visitThrow(Throw node) { |
| 3935 if (node.expression == null) { | 3942 if (node.expression == null) { |
| 3936 HInstruction exception = rethrowableException; | 3943 HInstruction exception = rethrowableException; |
| 3937 if (exception == null) { | 3944 if (exception == null) { |
| 3938 exception = graph.addConstantNull(constantSystem); | 3945 exception = graph.addConstantNull(constantSystem); |
| 3939 compiler.internalError( | 3946 compiler.internalError( |
| 3940 'rethrowableException should not be null', node: node); | 3947 'rethrowableException should not be null', node: node); |
| 3941 } | 3948 } |
| 3942 close(new HThrow(exception, isRethrow: true)); | 3949 handleInTryStatement(); |
| 3950 closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
| 3943 } else { | 3951 } else { |
| 3952 visit(node.expression); |
| 3953 handleInTryStatement(); |
| 3944 if (inliningStack.isEmpty) { | 3954 if (inliningStack.isEmpty) { |
| 3945 visit(node.expression); | 3955 closeAndGotoExit(new HThrow(pop())); |
| 3946 close(new HThrow(pop())); | |
| 3947 } else if (isReachable) { | 3956 } else if (isReachable) { |
| 3948 // We don't close the block when we are inlining, because we could be | 3957 // We don't close the block when we are inlining, because we could be |
| 3949 // inside an expression, and it is rather complicated to close the | 3958 // inside an expression, and it is rather complicated to close the |
| 3950 // block at an arbitrary place in an expression. | 3959 // block at an arbitrary place in an expression. |
| 3951 visit(node.expression); | |
| 3952 add(new HThrowExpression(pop())); | 3960 add(new HThrowExpression(pop())); |
| 3953 isReachable = false; | 3961 isReachable = false; |
| 3954 } | 3962 } |
| 3955 } | 3963 } |
| 3956 } | 3964 } |
| 3957 | 3965 |
| 3958 visitTypeAnnotation(TypeAnnotation node) { | 3966 visitTypeAnnotation(TypeAnnotation node) { |
| 3959 compiler.internalError('visiting type annotation in SSA builder', | 3967 compiler.internalError('visiting type annotation in SSA builder', |
| 3960 node: node); | 3968 node: node); |
| 3961 } | 3969 } |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4357 // default case. | 4365 // default case. |
| 4358 expressionBlock.addSuccessor(block); | 4366 expressionBlock.addSuccessor(block); |
| 4359 hasDefault = true; | 4367 hasDefault = true; |
| 4360 } | 4368 } |
| 4361 open(block); | 4369 open(block); |
| 4362 localsHandler = new LocalsHandler.from(savedLocals); | 4370 localsHandler = new LocalsHandler.from(savedLocals); |
| 4363 visit(switchCase.statements); | 4371 visit(switchCase.statements); |
| 4364 if (!isAborted() && caseIterator.hasNext) { | 4372 if (!isAborted() && caseIterator.hasNext) { |
| 4365 pushInvokeHelper0(getFallThroughErrorElement, HType.UNKNOWN); | 4373 pushInvokeHelper0(getFallThroughErrorElement, HType.UNKNOWN); |
| 4366 HInstruction error = pop(); | 4374 HInstruction error = pop(); |
| 4367 close(new HThrow(error)); | 4375 closeAndGotoExit(new HThrow(error)); |
| 4368 } | 4376 } |
| 4369 statements.add( | 4377 statements.add( |
| 4370 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 4378 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
| 4371 } | 4379 } |
| 4372 | 4380 |
| 4373 // Add a join-block if necessary. | 4381 // Add a join-block if necessary. |
| 4374 // We create [joinBlock] early, and then go through the cases that might | 4382 // We create [joinBlock] early, and then go through the cases that might |
| 4375 // want to jump to it. In each case, if we add [joinBlock] as a successor | 4383 // want to jump to it. In each case, if we add [joinBlock] as a successor |
| 4376 // of another block, we also add an element to [caseHandlers] that is used | 4384 // of another block, we also add an element to [caseHandlers] that is used |
| 4377 // to create the phis in [joinBlock]. | 4385 // to create the phis in [joinBlock]. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4474 // Called for the statements on all but the last case block. | 4482 // Called for the statements on all but the last case block. |
| 4475 // Ensures that a user expecting a fallthrough gets an error. | 4483 // Ensures that a user expecting a fallthrough gets an error. |
| 4476 void visitStatementsAndAbort() { | 4484 void visitStatementsAndAbort() { |
| 4477 visit(node.statements); | 4485 visit(node.statements); |
| 4478 if (!isAborted()) { | 4486 if (!isAborted()) { |
| 4479 compiler.reportWarning(node, 'Missing break at end of switch case'); | 4487 compiler.reportWarning(node, 'Missing break at end of switch case'); |
| 4480 Element element = | 4488 Element element = |
| 4481 compiler.findHelper(const SourceString("getFallThroughError")); | 4489 compiler.findHelper(const SourceString("getFallThroughError")); |
| 4482 pushInvokeHelper0(element, HType.UNKNOWN); | 4490 pushInvokeHelper0(element, HType.UNKNOWN); |
| 4483 HInstruction error = pop(); | 4491 HInstruction error = pop(); |
| 4484 close(new HThrow(error)); | 4492 closeAndGotoExit(new HThrow(error)); |
| 4485 } | 4493 } |
| 4486 } | 4494 } |
| 4487 | 4495 |
| 4488 Link<Node> skipLabels(Link<Node> labelsAndCases) { | 4496 Link<Node> skipLabels(Link<Node> labelsAndCases) { |
| 4489 while (!labelsAndCases.isEmpty && labelsAndCases.head is Label) { | 4497 while (!labelsAndCases.isEmpty && labelsAndCases.head is Label) { |
| 4490 labelsAndCases = labelsAndCases.tail; | 4498 labelsAndCases = labelsAndCases.tail; |
| 4491 } | 4499 } |
| 4492 return labelsAndCases; | 4500 return labelsAndCases; |
| 4493 } | 4501 } |
| 4494 | 4502 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4690 pushInvokeHelper1( | 4698 pushInvokeHelper1( |
| 4691 backend.getTraceFromException(), exception, HType.UNKNOWN); | 4699 backend.getTraceFromException(), exception, HType.UNKNOWN); |
| 4692 HInstruction traceInstruction = pop(); | 4700 HInstruction traceInstruction = pop(); |
| 4693 localsHandler.updateLocal(elements[trace], traceInstruction); | 4701 localsHandler.updateLocal(elements[trace], traceInstruction); |
| 4694 } | 4702 } |
| 4695 visit(catchBlock); | 4703 visit(catchBlock); |
| 4696 } | 4704 } |
| 4697 | 4705 |
| 4698 void visitElse() { | 4706 void visitElse() { |
| 4699 if (link.isEmpty) { | 4707 if (link.isEmpty) { |
| 4700 close(new HThrow(exception, isRethrow: true)); | 4708 closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
| 4701 } else { | 4709 } else { |
| 4702 CatchBlock newBlock = link.head; | 4710 CatchBlock newBlock = link.head; |
| 4703 handleIf(node, | 4711 handleIf(node, |
| 4704 () { pushCondition(newBlock); }, | 4712 () { pushCondition(newBlock); }, |
| 4705 visitThen, visitElse); | 4713 visitThen, visitElse); |
| 4706 } | 4714 } |
| 4707 } | 4715 } |
| 4708 | 4716 |
| 4709 CatchBlock firstBlock = link.head; | 4717 CatchBlock firstBlock = link.head; |
| 4710 handleIf(node, () { pushCondition(firstBlock); }, visitThen, visitElse); | 4718 handleIf(node, () { pushCondition(firstBlock); }, visitThen, visitElse); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4732 addExitTrySuccessor(successor) { | 4740 addExitTrySuccessor(successor) { |
| 4733 if (successor == null) return; | 4741 if (successor == null) return; |
| 4734 // Iterate over all blocks created inside this try/catch, and | 4742 // Iterate over all blocks created inside this try/catch, and |
| 4735 // attach successor information to blocks that end with | 4743 // attach successor information to blocks that end with |
| 4736 // [HExitTry]. | 4744 // [HExitTry]. |
| 4737 for (int i = startTryBlock.id; i < successor.id; i++) { | 4745 for (int i = startTryBlock.id; i < successor.id; i++) { |
| 4738 HBasicBlock block = graph.blocks[i]; | 4746 HBasicBlock block = graph.blocks[i]; |
| 4739 var last = block.last; | 4747 var last = block.last; |
| 4740 if (last is HExitTry) { | 4748 if (last is HExitTry) { |
| 4741 block.addSuccessor(successor); | 4749 block.addSuccessor(successor); |
| 4742 } else if (last is HTry) { | |
| 4743 // Skip all blocks inside this nested try/catch. | |
| 4744 i = last.joinBlock.id; | |
| 4745 } | 4750 } |
| 4746 } | 4751 } |
| 4747 } | 4752 } |
| 4748 | 4753 |
| 4749 // Setup all successors. The entry block that contains the [HTry] | 4754 // Setup all successors. The entry block that contains the [HTry] |
| 4750 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit | 4755 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit |
| 4751 // blocks as successors. | 4756 // blocks as successors. |
| 4752 enterBlock.addSuccessor(startTryBlock); | 4757 enterBlock.addSuccessor(startTryBlock); |
| 4753 addOptionalSuccessor(enterBlock, startCatchBlock); | 4758 addOptionalSuccessor(enterBlock, startCatchBlock); |
| 4754 addOptionalSuccessor(enterBlock, startFinallyBlock); | 4759 addOptionalSuccessor(enterBlock, startFinallyBlock); |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5214 new HSubGraphBlockInformation(elseBranch.graph)); | 5219 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5215 | 5220 |
| 5216 HBasicBlock conditionStartBlock = conditionBranch.block; | 5221 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5217 conditionStartBlock.setBlockFlow(info, joinBlock); | 5222 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5218 SubGraph conditionGraph = conditionBranch.graph; | 5223 SubGraph conditionGraph = conditionBranch.graph; |
| 5219 HIf branch = conditionGraph.end.last; | 5224 HIf branch = conditionGraph.end.last; |
| 5220 assert(branch is HIf); | 5225 assert(branch is HIf); |
| 5221 branch.blockInformation = conditionStartBlock.blockFlow; | 5226 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5222 } | 5227 } |
| 5223 } | 5228 } |
| OLD | NEW |