| 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 class Interceptors { | 7 class Interceptors { |
| 8 Compiler compiler; | 8 Compiler compiler; |
| 9 Interceptors(Compiler this.compiler); | 9 Interceptors(Compiler this.compiler); |
| 10 | 10 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 void enterScope(Node node, Element element) { | 325 void enterScope(Node node, Element element) { |
| 326 // See if any variable in the top-scope of the function is captured. If yes | 326 // See if any variable in the top-scope of the function is captured. If yes |
| 327 // we need to create a box-object. | 327 // we need to create a box-object. |
| 328 ClosureScope scopeData = closureData.capturingScopes[node]; | 328 ClosureScope scopeData = closureData.capturingScopes[node]; |
| 329 if (scopeData != null) { | 329 if (scopeData != null) { |
| 330 HInstruction box; | 330 HInstruction box; |
| 331 // The scope has captured variables. | 331 // The scope has captured variables. |
| 332 if (element != null && element.isGenerativeConstructorBody()) { | 332 if (element != null && element.isGenerativeConstructorBody()) { |
| 333 // The box is passed as a parameter to a generative | 333 // The box is passed as a parameter to a generative |
| 334 // constructor body. | 334 // constructor body. |
| 335 box = new HParameterValue(scopeData.boxElement); | 335 box = builder.addParameter(scopeData.boxElement); |
| 336 builder.add(box); | |
| 337 } else { | 336 } else { |
| 338 box = createBox(); | 337 box = createBox(); |
| 339 } | 338 } |
| 340 // Add the box to the known locals. | 339 // Add the box to the known locals. |
| 341 directLocals[scopeData.boxElement] = box; | 340 directLocals[scopeData.boxElement] = box; |
| 342 // Make sure that accesses to the boxed locals go into the box. We also | 341 // Make sure that accesses to the boxed locals go into the box. We also |
| 343 // need to make sure that parameters are copied into the box if necessary. | 342 // need to make sure that parameters are copied into the box if necessary. |
| 344 scopeData.capturedVariableMapping.forEach((Element from, Element to) { | 343 scopeData.capturedVariableMapping.forEach((Element from, Element to) { |
| 345 // The [from] can only be a parameter for function-scopes and not | 344 // The [from] can only be a parameter for function-scopes and not |
| 346 // loop scopes. | 345 // loop scopes. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 void startFunction(Element element, Expression node) { | 386 void startFunction(Element element, Expression node) { |
| 388 assert(invariant(node, element.isImplementation)); | 387 assert(invariant(node, element.isImplementation)); |
| 389 Compiler compiler = builder.compiler; | 388 Compiler compiler = builder.compiler; |
| 390 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 389 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 391 element, node, builder.elements); | 390 element, node, builder.elements); |
| 392 | 391 |
| 393 if (element is FunctionElement) { | 392 if (element is FunctionElement) { |
| 394 FunctionElement functionElement = element; | 393 FunctionElement functionElement = element; |
| 395 FunctionSignature params = functionElement.computeSignature(compiler); | 394 FunctionSignature params = functionElement.computeSignature(compiler); |
| 396 params.orderedForEachParameter((Element parameterElement) { | 395 params.orderedForEachParameter((Element parameterElement) { |
| 397 HInstruction parameter = new HParameterValue(parameterElement); | 396 HInstruction parameter = builder.addParameter(parameterElement); |
| 398 builder.add(parameter); | |
| 399 builder.parameters[parameterElement] = parameter; | 397 builder.parameters[parameterElement] = parameter; |
| 400 directLocals[parameterElement] = parameter; | 398 directLocals[parameterElement] = parameter; |
| 401 parameter.guaranteedType = | 399 parameter.guaranteedType = |
| 402 builder.mapInferredType( | 400 builder.mapInferredType( |
| 403 typesTask.getGuaranteedTypeOfElement(parameterElement)); | 401 typesTask.getGuaranteedTypeOfElement(parameterElement)); |
| 404 }); | 402 }); |
| 405 } | 403 } |
| 406 | 404 |
| 407 enterScope(node, element); | 405 enterScope(node, element); |
| 408 | 406 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 // In all other cases a new box will be created when entering the body of | 656 // In all other cases a new box will be created when entering the body of |
| 659 // the next iteration. | 657 // the next iteration. |
| 660 ClosureScope scopeData = closureData.capturingScopes[node]; | 658 ClosureScope scopeData = closureData.capturingScopes[node]; |
| 661 if (scopeData == null) return; | 659 if (scopeData == null) return; |
| 662 if (scopeData.hasBoxedLoopVariables()) { | 660 if (scopeData.hasBoxedLoopVariables()) { |
| 663 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); | 661 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); |
| 664 } | 662 } |
| 665 } | 663 } |
| 666 | 664 |
| 667 void endLoop(HBasicBlock loopEntry) { | 665 void endLoop(HBasicBlock loopEntry) { |
| 666 // If the loop has an aborting body, we don't update the loop |
| 667 // phis. |
| 668 if (loopEntry.predecessors.length == 1) return; |
| 668 loopEntry.forEachPhi((HPhi phi) { | 669 loopEntry.forEachPhi((HPhi phi) { |
| 669 Element element = phi.sourceElement; | 670 Element element = phi.sourceElement; |
| 670 HInstruction postLoopDefinition = directLocals[element]; | 671 HInstruction postLoopDefinition = directLocals[element]; |
| 671 phi.addInput(postLoopDefinition); | 672 phi.addInput(postLoopDefinition); |
| 672 }); | 673 }); |
| 673 } | 674 } |
| 674 | 675 |
| 675 /** | 676 /** |
| 676 * Merge [otherLocals] into this locals handler, creating phi-nodes when | 677 * Merge [otherLocals] into this locals handler, creating phi-nodes when |
| 677 * there is a conflict. | 678 * there is a conflict. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 | 761 |
| 761 abstract class JumpHandler { | 762 abstract class JumpHandler { |
| 762 factory JumpHandler(SsaBuilder builder, TargetElement target) { | 763 factory JumpHandler(SsaBuilder builder, TargetElement target) { |
| 763 return new TargetJumpHandler(builder, target); | 764 return new TargetJumpHandler(builder, target); |
| 764 } | 765 } |
| 765 void generateBreak([LabelElement label]); | 766 void generateBreak([LabelElement label]); |
| 766 void generateContinue([LabelElement label]); | 767 void generateContinue([LabelElement label]); |
| 767 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); | 768 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); |
| 768 void forEachContinue(void action(HContinue instruction, | 769 void forEachContinue(void action(HContinue instruction, |
| 769 LocalsHandler locals)); | 770 LocalsHandler locals)); |
| 771 bool hasAnyContinue(); |
| 772 bool hasAnyBreak(); |
| 770 void close(); | 773 void close(); |
| 771 final TargetElement target; | 774 final TargetElement target; |
| 772 List<LabelElement> labels(); | 775 List<LabelElement> labels(); |
| 773 } | 776 } |
| 774 | 777 |
| 775 // Insert break handler used to avoid null checks when a target isn't | 778 // Insert break handler used to avoid null checks when a target isn't |
| 776 // used as the target of a break, and therefore doesn't need a break | 779 // used as the target of a break, and therefore doesn't need a break |
| 777 // handler associated with it. | 780 // handler associated with it. |
| 778 class NullJumpHandler implements JumpHandler { | 781 class NullJumpHandler implements JumpHandler { |
| 779 final Compiler compiler; | 782 final Compiler compiler; |
| 780 | 783 |
| 781 NullJumpHandler(this.compiler); | 784 NullJumpHandler(this.compiler); |
| 782 | 785 |
| 783 void generateBreak([LabelElement label]) { | 786 void generateBreak([LabelElement label]) { |
| 784 compiler.internalError('generateBreak should not be called'); | 787 compiler.internalError('generateBreak should not be called'); |
| 785 } | 788 } |
| 786 | 789 |
| 787 void generateContinue([LabelElement label]) { | 790 void generateContinue([LabelElement label]) { |
| 788 compiler.internalError('generateContinue should not be called'); | 791 compiler.internalError('generateContinue should not be called'); |
| 789 } | 792 } |
| 790 | 793 |
| 791 void forEachBreak(Function ignored) { } | 794 void forEachBreak(Function ignored) { } |
| 792 void forEachContinue(Function ignored) { } | 795 void forEachContinue(Function ignored) { } |
| 793 void close() { } | 796 void close() { } |
| 797 bool hasAnyContinue() => false; |
| 798 bool hasAnyBreak() => false; |
| 794 | 799 |
| 795 List<LabelElement> labels() => const <LabelElement>[]; | 800 List<LabelElement> labels() => const <LabelElement>[]; |
| 796 TargetElement get target => null; | 801 TargetElement get target => null; |
| 797 } | 802 } |
| 798 | 803 |
| 799 // Records breaks until a target block is available. | 804 // Records breaks until a target block is available. |
| 800 // Breaks are always forward jumps. | 805 // Breaks are always forward jumps. |
| 801 // Continues in loops are implemented as breaks of the body. | 806 // Continues in loops are implemented as breaks of the body. |
| 802 // Continues in switches is currently not handled. | 807 // Continues in switches is currently not handled. |
| 803 class TargetJumpHandler implements JumpHandler { | 808 class TargetJumpHandler implements JumpHandler { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals); | 846 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals); |
| 842 } | 847 } |
| 843 } | 848 } |
| 844 | 849 |
| 845 void forEachContinue(Function action) { | 850 void forEachContinue(Function action) { |
| 846 for (JumpHandlerEntry entry in jumps) { | 851 for (JumpHandlerEntry entry in jumps) { |
| 847 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals); | 852 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals); |
| 848 } | 853 } |
| 849 } | 854 } |
| 850 | 855 |
| 856 bool hasAnyContinue() { |
| 857 for (JumpHandlerEntry entry in jumps) { |
| 858 if (entry.isContinue()) return true; |
| 859 } |
| 860 return false; |
| 861 } |
| 862 |
| 863 bool hasAnyBreak() { |
| 864 for (JumpHandlerEntry entry in jumps) { |
| 865 if (entry.isBreak()) return true; |
| 866 } |
| 867 return false; |
| 868 } |
| 869 |
| 851 void close() { | 870 void close() { |
| 852 // The mapping from TargetElement to JumpHandler is no longer needed. | 871 // The mapping from TargetElement to JumpHandler is no longer needed. |
| 853 builder.jumpTargets.remove(target); | 872 builder.jumpTargets.remove(target); |
| 854 } | 873 } |
| 855 | 874 |
| 856 List<LabelElement> labels() { | 875 List<LabelElement> labels() { |
| 857 List<LabelElement> result = null; | 876 List<LabelElement> result = null; |
| 858 for (LabelElement element in target.labels) { | 877 for (LabelElement element in target.labels) { |
| 859 if (result == null) result = <LabelElement>[]; | 878 if (result == null) result = <LabelElement>[]; |
| 860 result.add(element); | 879 result.add(element); |
| 861 } | 880 } |
| 862 return (result == null) ? const <LabelElement>[] : result; | 881 return (result == null) ? const <LabelElement>[] : result; |
| 863 } | 882 } |
| 864 } | 883 } |
| 865 | 884 |
| 866 class SsaBuilder extends ResolvedVisitor implements Visitor { | 885 class SsaBuilder extends ResolvedVisitor implements Visitor { |
| 867 final SsaBuilderTask builder; | 886 final SsaBuilderTask builder; |
| 868 final JavaScriptBackend backend; | 887 final JavaScriptBackend backend; |
| 869 final Interceptors interceptors; | 888 final Interceptors interceptors; |
| 870 final WorkItem work; | 889 final WorkItem work; |
| 871 final ConstantSystem constantSystem; | 890 final ConstantSystem constantSystem; |
| 872 bool methodInterceptionEnabled; | 891 bool methodInterceptionEnabled; |
| 873 HGraph graph; | 892 HGraph graph; |
| 874 LocalsHandler localsHandler; | 893 LocalsHandler localsHandler; |
| 875 HInstruction rethrowableException; | 894 HInstruction rethrowableException; |
| 876 Map<Element, HInstruction> parameters; | 895 Map<Element, HInstruction> parameters; |
| 877 final RuntimeTypeInformation rti; | 896 final RuntimeTypeInformation rti; |
| 897 HParameterValue lastAddedParameter; |
| 878 | 898 |
| 879 Map<TargetElement, JumpHandler> jumpTargets; | 899 Map<TargetElement, JumpHandler> jumpTargets; |
| 880 | 900 |
| 881 /** | 901 /** |
| 882 * Variables stored in the current activation. These variables are | 902 * Variables stored in the current activation. These variables are |
| 883 * being updated in try/catch blocks, and should be | 903 * being updated in try/catch blocks, and should be |
| 884 * accessed indirectly through [HLocalGet] and [HLocalSet]. | 904 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| 885 */ | 905 */ |
| 886 Map<Element, HLocalValue> activationVariables; | 906 Map<Element, HLocalValue> activationVariables; |
| 887 | 907 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 rti = builder.compiler.codegenWorld.rti, | 939 rti = builder.compiler.codegenWorld.rti, |
| 920 super(work.resolutionTree) { | 940 super(work.resolutionTree) { |
| 921 localsHandler = new LocalsHandler(this); | 941 localsHandler = new LocalsHandler(this); |
| 922 } | 942 } |
| 923 | 943 |
| 924 static const MAX_INLINING_DEPTH = 3; | 944 static const MAX_INLINING_DEPTH = 3; |
| 925 static const MAX_INLINING_SOURCE_SIZE = 128; | 945 static const MAX_INLINING_SOURCE_SIZE = 128; |
| 926 List<InliningState> inliningStack; | 946 List<InliningState> inliningStack; |
| 927 Element returnElement; | 947 Element returnElement; |
| 928 DartType returnType; | 948 DartType returnType; |
| 949 bool inTryStatement = false; |
| 929 | 950 |
| 930 void disableMethodInterception() { | 951 void disableMethodInterception() { |
| 931 assert(methodInterceptionEnabled); | 952 assert(methodInterceptionEnabled); |
| 932 methodInterceptionEnabled = false; | 953 methodInterceptionEnabled = false; |
| 933 } | 954 } |
| 934 | 955 |
| 935 void enableMethodInterception() { | 956 void enableMethodInterception() { |
| 936 assert(!methodInterceptionEnabled); | 957 assert(!methodInterceptionEnabled); |
| 937 methodInterceptionEnabled = true; | 958 methodInterceptionEnabled = true; |
| 938 } | 959 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 classElement.origin.backendMembers = | 1031 classElement.origin.backendMembers = |
| 1011 classElement.origin.backendMembers.prepend(bodyElement.origin); | 1032 classElement.origin.backendMembers.prepend(bodyElement.origin); |
| 1012 } | 1033 } |
| 1013 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, | 1034 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, |
| 1014 treeElements); | 1035 treeElements); |
| 1015 } | 1036 } |
| 1016 assert(bodyElement.isGenerativeConstructorBody()); | 1037 assert(bodyElement.isGenerativeConstructorBody()); |
| 1017 return bodyElement; | 1038 return bodyElement; |
| 1018 } | 1039 } |
| 1019 | 1040 |
| 1041 HParameterValue addParameter(Element element) { |
| 1042 HParameterValue result = new HParameterValue(element); |
| 1043 if (lastAddedParameter == null) { |
| 1044 graph.entry.addBefore(graph.entry.first, result); |
| 1045 } else { |
| 1046 graph.entry.addAfter(lastAddedParameter, result); |
| 1047 } |
| 1048 lastAddedParameter = result; |
| 1049 return result; |
| 1050 } |
| 1051 |
| 1020 /** | 1052 /** |
| 1021 * Documentation wanted -- johnniwinther | 1053 * Documentation wanted -- johnniwinther |
| 1022 * | 1054 * |
| 1023 * Invariant: [function] must be an implementation element. | 1055 * Invariant: [function] must be an implementation element. |
| 1024 */ | 1056 */ |
| 1025 InliningState enterInlinedMethod(PartialFunctionElement function, | 1057 InliningState enterInlinedMethod(PartialFunctionElement function, |
| 1026 Selector selector, | 1058 Selector selector, |
| 1027 Link<Node> arguments) { | 1059 Link<Node> arguments) { |
| 1028 assert(invariant(function, function.isImplementation)); | 1060 assert(invariant(function, function.isImplementation)); |
| 1029 | 1061 |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 return closeFunction(); | 1460 return closeFunction(); |
| 1429 } | 1461 } |
| 1430 | 1462 |
| 1431 void addParameterCheckInstruction(Element element) { | 1463 void addParameterCheckInstruction(Element element) { |
| 1432 HInstruction check; | 1464 HInstruction check; |
| 1433 Element checkResultElement = | 1465 Element checkResultElement = |
| 1434 localsHandler.closureData.parametersWithSentinel[element]; | 1466 localsHandler.closureData.parametersWithSentinel[element]; |
| 1435 if (currentElement.isGenerativeConstructorBody()) { | 1467 if (currentElement.isGenerativeConstructorBody()) { |
| 1436 // A generative constructor body receives extra parameters that | 1468 // A generative constructor body receives extra parameters that |
| 1437 // indicate if a parameter was passed to the factory. | 1469 // indicate if a parameter was passed to the factory. |
| 1438 check = new HParameterValue(checkResultElement); | 1470 check = addParameter(checkResultElement); |
| 1439 add(check); | |
| 1440 } else { | 1471 } else { |
| 1441 // This is the code we emit for a parameter that is being checked | 1472 // This is the code we emit for a parameter that is being checked |
| 1442 // on whether it was given at value at the call site: | 1473 // on whether it was given at value at the call site: |
| 1443 // | 1474 // |
| 1444 // foo([a = 42) { | 1475 // foo([a = 42) { |
| 1445 // if (?a) print('parameter passed $a'); | 1476 // if (?a) print('parameter passed $a'); |
| 1446 // } | 1477 // } |
| 1447 // | 1478 // |
| 1448 // foo([a = 42]) { | 1479 // foo([a = 42]) { |
| 1449 // var t1 = a === sentinel; | 1480 // var t1 = a === sentinel; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1521 } else { | 1552 } else { |
| 1522 // Otherwise it is a lazy initializer which does not have parameters. | 1553 // Otherwise it is a lazy initializer which does not have parameters. |
| 1523 assert(element is VariableElement); | 1554 assert(element is VariableElement); |
| 1524 } | 1555 } |
| 1525 | 1556 |
| 1526 // Add the type parameters of the class as parameters of this | 1557 // Add the type parameters of the class as parameters of this |
| 1527 // method. | 1558 // method. |
| 1528 var enclosing = element.enclosingElement; | 1559 var enclosing = element.enclosingElement; |
| 1529 if (element.isConstructor() && compiler.world.needsRti(enclosing)) { | 1560 if (element.isConstructor() && compiler.world.needsRti(enclosing)) { |
| 1530 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1561 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1531 HParameterValue param = new HParameterValue(typeVariable.element); | 1562 HParameterValue param = addParameter(typeVariable.element); |
| 1532 add(param); | |
| 1533 localsHandler.directLocals[typeVariable.element] = param; | 1563 localsHandler.directLocals[typeVariable.element] = param; |
| 1534 }); | 1564 }); |
| 1535 } | 1565 } |
| 1536 } | 1566 } |
| 1537 | 1567 |
| 1538 HInstruction potentiallyCheckType( | 1568 HInstruction potentiallyCheckType( |
| 1539 HInstruction original, DartType type, | 1569 HInstruction original, DartType type, |
| 1540 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { | 1570 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { |
| 1541 if (!compiler.enableTypeAssertions) return original; | 1571 if (!compiler.enableTypeAssertions) return original; |
| 1542 HInstruction other = original.convertType(compiler, type, kind); | 1572 HInstruction other = original.convertType(compiler, type, kind); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 /** | 1738 /** |
| 1709 * Ends the loop: | 1739 * Ends the loop: |
| 1710 * - creates a new block and adds it as successor to the [branchBlock]. | 1740 * - creates a new block and adds it as successor to the [branchBlock]. |
| 1711 * - opens the new block (setting as [current]). | 1741 * - opens the new block (setting as [current]). |
| 1712 * - notifies the locals handler that we're exiting a loop. | 1742 * - notifies the locals handler that we're exiting a loop. |
| 1713 */ | 1743 */ |
| 1714 void endLoop(HBasicBlock loopEntry, | 1744 void endLoop(HBasicBlock loopEntry, |
| 1715 HBasicBlock branchBlock, | 1745 HBasicBlock branchBlock, |
| 1716 JumpHandler jumpHandler, | 1746 JumpHandler jumpHandler, |
| 1717 LocalsHandler savedLocals) { | 1747 LocalsHandler savedLocals) { |
| 1748 if (branchBlock == null && !jumpHandler.hasAnyBreak()) return; |
| 1749 |
| 1718 HBasicBlock loopExitBlock = addNewBlock(); | 1750 HBasicBlock loopExitBlock = addNewBlock(); |
| 1719 assert(branchBlock.successors.length == 1); | 1751 assert(branchBlock == null || branchBlock.successors.length == 1); |
| 1720 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 1752 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 1721 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1753 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 1722 breakInstruction.block.addSuccessor(loopExitBlock); | 1754 breakInstruction.block.addSuccessor(loopExitBlock); |
| 1723 breakLocals.add(locals); | 1755 breakLocals.add(locals); |
| 1724 }); | 1756 }); |
| 1725 branchBlock.addSuccessor(loopExitBlock); | 1757 if (branchBlock != null) { |
| 1758 branchBlock.addSuccessor(loopExitBlock); |
| 1759 } |
| 1726 open(loopExitBlock); | 1760 open(loopExitBlock); |
| 1727 localsHandler.endLoop(loopEntry); | 1761 localsHandler.endLoop(loopEntry); |
| 1728 if (!breakLocals.isEmpty) { | 1762 if (!breakLocals.isEmpty) { |
| 1729 breakLocals.add(savedLocals); | 1763 breakLocals.add(savedLocals); |
| 1730 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); | 1764 localsHandler = savedLocals.mergeMultiple(breakLocals, loopExitBlock); |
| 1731 } else { | 1765 } else { |
| 1732 localsHandler = savedLocals; | 1766 localsHandler = savedLocals; |
| 1733 } | 1767 } |
| 1734 } | 1768 } |
| 1735 | 1769 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 new SubExpression(conditionBlock, conditionExitBlock); | 1820 new SubExpression(conditionBlock, conditionExitBlock); |
| 1787 | 1821 |
| 1788 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1822 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1789 | 1823 |
| 1790 // The body. | 1824 // The body. |
| 1791 HBasicBlock beginBodyBlock = addNewBlock(); | 1825 HBasicBlock beginBodyBlock = addNewBlock(); |
| 1792 conditionExitBlock.addSuccessor(beginBodyBlock); | 1826 conditionExitBlock.addSuccessor(beginBodyBlock); |
| 1793 open(beginBodyBlock); | 1827 open(beginBodyBlock); |
| 1794 | 1828 |
| 1795 localsHandler.enterLoopBody(loop); | 1829 localsHandler.enterLoopBody(loop); |
| 1796 hackAroundPossiblyAbortingBody(loop, body); | 1830 body(); |
| 1797 | 1831 |
| 1798 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); | 1832 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock); |
| 1799 HBasicBlock bodyBlock = close(new HGoto()); | 1833 HBasicBlock bodyBlock = current; |
| 1834 if (current != null) close(new HGoto()); |
| 1800 | 1835 |
| 1801 // Update. | 1836 SubExpression updateGraph; |
| 1802 // We create an update block, even when we are in a while loop. There the | |
| 1803 // update block is the jump-target for continue statements. We could avoid | |
| 1804 // the creation if there is no continue, but for now we always create it. | |
| 1805 HBasicBlock updateBlock = addNewBlock(); | |
| 1806 | 1837 |
| 1807 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1838 // Check that the loop has at least one back-edge. |
| 1808 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1839 if (jumpHandler.hasAnyContinue() || bodyBlock != null) { |
| 1809 instruction.block.addSuccessor(updateBlock); | 1840 // Update. |
| 1810 continueLocals.add(locals); | 1841 // We create an update block, even when we are in a while loop. There the |
| 1811 }); | 1842 // update block is the jump-target for continue statements. We could avoid |
| 1812 bodyBlock.addSuccessor(updateBlock); | 1843 // the creation if there is no continue, but for now we always create it. |
| 1813 continueLocals.add(localsHandler); | 1844 HBasicBlock updateBlock = addNewBlock(); |
| 1814 | 1845 |
| 1815 open(updateBlock); | 1846 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| 1847 jumpHandler.forEachContinue((HContinue instruction, |
| 1848 LocalsHandler locals) { |
| 1849 instruction.block.addSuccessor(updateBlock); |
| 1850 continueLocals.add(locals); |
| 1851 }); |
| 1816 | 1852 |
| 1817 localsHandler = localsHandler.mergeMultiple(continueLocals, updateBlock); | |
| 1818 | 1853 |
| 1819 HLabeledBlockInformation labelInfo; | 1854 if (bodyBlock != null) { |
| 1820 List<LabelElement> labels = jumpHandler.labels(); | 1855 continueLocals.add(localsHandler); |
| 1821 TargetElement target = elements[loop]; | 1856 bodyBlock.addSuccessor(updateBlock); |
| 1822 if (!labels.isEmpty) { | 1857 } |
| 1823 beginBodyBlock.setBlockFlow( | 1858 |
| 1824 new HLabeledBlockInformation( | 1859 open(updateBlock); |
| 1825 new HSubGraphBlockInformation(bodyGraph), | 1860 localsHandler = |
| 1826 jumpHandler.labels(), | 1861 continueLocals[0].mergeMultiple(continueLocals, updateBlock); |
| 1827 isContinue: true), | 1862 |
| 1828 updateBlock); | 1863 HLabeledBlockInformation labelInfo; |
| 1829 } else if (target != null && target.isContinueTarget) { | 1864 List<LabelElement> labels = jumpHandler.labels(); |
| 1830 beginBodyBlock.setBlockFlow( | 1865 TargetElement target = elements[loop]; |
| 1831 new HLabeledBlockInformation.implicit( | 1866 if (!labels.isEmpty) { |
| 1832 new HSubGraphBlockInformation(bodyGraph), | 1867 beginBodyBlock.setBlockFlow( |
| 1833 target, | 1868 new HLabeledBlockInformation( |
| 1834 isContinue: true), | 1869 new HSubGraphBlockInformation(bodyGraph), |
| 1835 updateBlock); | 1870 jumpHandler.labels(), |
| 1871 isContinue: true), |
| 1872 updateBlock); |
| 1873 } else if (target != null && target.isContinueTarget) { |
| 1874 beginBodyBlock.setBlockFlow( |
| 1875 new HLabeledBlockInformation.implicit( |
| 1876 new HSubGraphBlockInformation(bodyGraph), |
| 1877 target, |
| 1878 isContinue: true), |
| 1879 updateBlock); |
| 1880 } |
| 1881 |
| 1882 localsHandler.enterLoopUpdates(loop); |
| 1883 |
| 1884 update(); |
| 1885 |
| 1886 HBasicBlock updateEndBlock = close(new HGoto()); |
| 1887 // The back-edge completing the cycle. |
| 1888 updateEndBlock.addSuccessor(conditionBlock); |
| 1889 updateGraph = new SubExpression(updateBlock, updateEndBlock); |
| 1836 } | 1890 } |
| 1837 | 1891 |
| 1838 localsHandler.enterLoopUpdates(loop); | |
| 1839 | |
| 1840 update(); | |
| 1841 | |
| 1842 HBasicBlock updateEndBlock = close(new HGoto()); | |
| 1843 // The back-edge completing the cycle. | |
| 1844 updateEndBlock.addSuccessor(conditionBlock); | |
| 1845 conditionBlock.postProcessLoopHeader(); | 1892 conditionBlock.postProcessLoopHeader(); |
| 1846 SubExpression updateGraph = new SubExpression(updateBlock, updateEndBlock); | |
| 1847 | 1893 |
| 1848 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1894 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
| 1849 HLoopBlockInformation info = | 1895 HLoopBlockInformation info = |
| 1850 new HLoopBlockInformation( | 1896 new HLoopBlockInformation( |
| 1851 HLoopBlockInformation.loopType(loop), | 1897 HLoopBlockInformation.loopType(loop), |
| 1852 wrapExpressionGraph(initializerGraph), | 1898 wrapExpressionGraph(initializerGraph), |
| 1853 wrapExpressionGraph(conditionExpression), | 1899 wrapExpressionGraph(conditionExpression), |
| 1854 wrapStatementGraph(bodyGraph), | 1900 wrapStatementGraph(bodyGraph), |
| 1855 wrapExpressionGraph(updateGraph), | 1901 wrapExpressionGraph(updateGraph), |
| 1856 conditionBlock.loopInformation.target, | 1902 conditionBlock.loopInformation.target, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1921 // Add extra block to hang labels on. | 1967 // Add extra block to hang labels on. |
| 1922 // It doesn't currently work if they are on the same block as the | 1968 // It doesn't currently work if they are on the same block as the |
| 1923 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1969 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| 1924 // SubGraph that starts at the same block again, so the HLoopInfo is | 1970 // SubGraph that starts at the same block again, so the HLoopInfo is |
| 1925 // either handled twice, or it's handled after the labeled block info, | 1971 // either handled twice, or it's handled after the labeled block info, |
| 1926 // both of which generate the wrong code. | 1972 // both of which generate the wrong code. |
| 1927 // Using a separate block is just a simple workaround. | 1973 // Using a separate block is just a simple workaround. |
| 1928 bodyEntryBlock = openNewBlock(); | 1974 bodyEntryBlock = openNewBlock(); |
| 1929 } | 1975 } |
| 1930 localsHandler.enterLoopBody(node); | 1976 localsHandler.enterLoopBody(node); |
| 1931 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); | 1977 visit(node.body); |
| 1932 | 1978 |
| 1933 // If there are no continues we could avoid the creation of the condition | 1979 // If there are no continues we could avoid the creation of the condition |
| 1934 // block. This could also lead to a block having multiple entries and exits. | 1980 // block. This could also lead to a block having multiple entries and exits. |
| 1935 HBasicBlock bodyExitBlock = close(new HGoto()); | 1981 HBasicBlock bodyExitBlock; |
| 1936 HBasicBlock conditionBlock = addNewBlock(); | 1982 bool isAbortingBody = false; |
| 1983 if (current != null) { |
| 1984 bodyExitBlock = close(new HGoto()); |
| 1985 } else { |
| 1986 isAbortingBody = true; |
| 1987 bodyExitBlock = lastOpenedBlock; |
| 1988 } |
| 1937 | 1989 |
| 1938 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1990 SubExpression conditionExpression; |
| 1939 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1991 HBasicBlock conditionEndBlock; |
| 1940 instruction.block.addSuccessor(conditionBlock); | 1992 if (!isAbortingBody || hasContinues) { |
| 1941 continueLocals.add(locals); | 1993 HBasicBlock conditionBlock = addNewBlock(); |
| 1942 }); | 1994 |
| 1943 bodyExitBlock.addSuccessor(conditionBlock); | 1995 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| 1944 if (!continueLocals.isEmpty) { | 1996 jumpHandler.forEachContinue((HContinue instruction, |
| 1945 continueLocals.add(localsHandler); | 1997 LocalsHandler locals) { |
| 1946 localsHandler = savedLocals.mergeMultiple(continueLocals, conditionBlock); | 1998 instruction.block.addSuccessor(conditionBlock); |
| 1947 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1999 continueLocals.add(locals); |
| 1948 List<LabelElement> labels = jumpHandler.labels(); | 2000 }); |
| 1949 HSubGraphBlockInformation bodyInfo = | 2001 |
| 1950 new HSubGraphBlockInformation(bodyGraph); | 2002 if (!isAbortingBody) { |
| 1951 HLabeledBlockInformation info; | 2003 bodyExitBlock.addSuccessor(conditionBlock); |
| 1952 if (!labels.isEmpty) { | |
| 1953 info = new HLabeledBlockInformation(bodyInfo, labels, isContinue: true); | |
| 1954 } else { | |
| 1955 info = new HLabeledBlockInformation.implicit(bodyInfo, target, | |
| 1956 isContinue: true); | |
| 1957 } | 2004 } |
| 1958 bodyEntryBlock.setBlockFlow(info, conditionBlock); | 2005 |
| 2006 if (!continueLocals.isEmpty) { |
| 2007 if (!isAbortingBody) continueLocals.add(localsHandler); |
| 2008 localsHandler = |
| 2009 savedLocals.mergeMultiple(continueLocals, conditionBlock); |
| 2010 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 2011 List<LabelElement> labels = jumpHandler.labels(); |
| 2012 HSubGraphBlockInformation bodyInfo = |
| 2013 new HSubGraphBlockInformation(bodyGraph); |
| 2014 HLabeledBlockInformation info; |
| 2015 if (!labels.isEmpty) { |
| 2016 info = new HLabeledBlockInformation(bodyInfo, labels, |
| 2017 isContinue: true); |
| 2018 } else { |
| 2019 info = new HLabeledBlockInformation.implicit(bodyInfo, target, |
| 2020 isContinue: true); |
| 2021 } |
| 2022 bodyEntryBlock.setBlockFlow(info, conditionBlock); |
| 2023 } |
| 2024 open(conditionBlock); |
| 2025 |
| 2026 visit(node.condition); |
| 2027 assert(!isAborted()); |
| 2028 HInstruction conditionInstruction = popBoolified(); |
| 2029 conditionEndBlock = close( |
| 2030 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); |
| 2031 |
| 2032 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge. |
| 2033 conditionExpression = |
| 2034 new SubExpression(conditionBlock, conditionEndBlock); |
| 1959 } | 2035 } |
| 1960 open(conditionBlock); | |
| 1961 | 2036 |
| 1962 visit(node.condition); | |
| 1963 assert(!isAborted()); | |
| 1964 HInstruction conditionInstruction = popBoolified(); | |
| 1965 HBasicBlock conditionEndBlock = | |
| 1966 close(new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); | |
| 1967 | |
| 1968 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge. | |
| 1969 loopEntryBlock.postProcessLoopHeader(); | 2037 loopEntryBlock.postProcessLoopHeader(); |
| 1970 | 2038 |
| 1971 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); | 2039 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
| 1972 jumpHandler.close(); | 2040 jumpHandler.close(); |
| 1973 | 2041 |
| 1974 SubExpression conditionExpression = | |
| 1975 new SubExpression(conditionBlock, conditionEndBlock); | |
| 1976 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 2042 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 1977 | 2043 |
| 1978 HLoopBlockInformation loopBlockInfo = | 2044 HLoopBlockInformation loopBlockInfo = |
| 1979 new HLoopBlockInformation( | 2045 new HLoopBlockInformation( |
| 1980 HLoopBlockInformation.DO_WHILE_LOOP, | 2046 HLoopBlockInformation.DO_WHILE_LOOP, |
| 1981 null, | 2047 null, |
| 1982 wrapExpressionGraph(conditionExpression), | 2048 wrapExpressionGraph(conditionExpression), |
| 1983 wrapStatementGraph(bodyGraph), | 2049 wrapStatementGraph(bodyGraph), |
| 1984 null, | 2050 null, |
| 1985 loopEntryBlock.loopInformation.target, | 2051 loopEntryBlock.loopInformation.target, |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 HInstruction generateInstanceSendReceiver(Send send) { | 2257 HInstruction generateInstanceSendReceiver(Send send) { |
| 2192 assert(Elements.isInstanceSend(send, elements)); | 2258 assert(Elements.isInstanceSend(send, elements)); |
| 2193 if (send.receiver == null) { | 2259 if (send.receiver == null) { |
| 2194 return localsHandler.readThis(); | 2260 return localsHandler.readThis(); |
| 2195 } | 2261 } |
| 2196 visit(send.receiver); | 2262 visit(send.receiver); |
| 2197 return pop(); | 2263 return pop(); |
| 2198 } | 2264 } |
| 2199 | 2265 |
| 2200 String getTargetName(ErroneousElement error, [String prefix]) { | 2266 String getTargetName(ErroneousElement error, [String prefix]) { |
| 2201 String result = error.targetName.slowToString(); | 2267 String result = error.name.slowToString(); |
| 2202 if (?prefix) { | 2268 if (?prefix) { |
| 2203 result = '$prefix $result'; | 2269 result = '$prefix $result'; |
| 2204 } | 2270 } |
| 2205 return result; | 2271 return result; |
| 2206 } | 2272 } |
| 2207 | 2273 |
| 2208 void generateInstanceGetterWithCompiledReceiver(Send send, | 2274 void generateInstanceGetterWithCompiledReceiver(Send send, |
| 2209 HInstruction receiver) { | 2275 HInstruction receiver) { |
| 2210 assert(Elements.isInstanceSend(send, elements)); | 2276 assert(Elements.isInstanceSend(send, elements)); |
| 2211 // TODO(kasperl): This is a convoluted way of checking if we're | 2277 // TODO(kasperl): This is a convoluted way of checking if we're |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3000 return HType.UNKNOWN; | 3066 return HType.UNKNOWN; |
| 3001 } | 3067 } |
| 3002 } | 3068 } |
| 3003 | 3069 |
| 3004 Element constructor = elements[node]; | 3070 Element constructor = elements[node]; |
| 3005 Selector selector = elements.getSelector(node); | 3071 Selector selector = elements.getSelector(node); |
| 3006 if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) { | 3072 if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) { |
| 3007 compiler.internalError("Unresolved element: $constructor", node: node); | 3073 compiler.internalError("Unresolved element: $constructor", node: node); |
| 3008 } | 3074 } |
| 3009 FunctionElement functionElement = constructor; | 3075 FunctionElement functionElement = constructor; |
| 3010 constructor = functionElement.defaultImplementation; | 3076 constructor = functionElement.redirectionTarget; |
| 3011 // TODO(5346): Try to avoid the need for calling [declaration] before | 3077 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3012 // creating an [HStatic]. | 3078 // creating an [HStatic]. |
| 3013 HInstruction target = new HStatic(constructor.declaration); | 3079 HInstruction target = new HStatic(constructor.declaration); |
| 3014 add(target); | 3080 add(target); |
| 3015 var inputs = <HInstruction>[]; | 3081 var inputs = <HInstruction>[]; |
| 3016 inputs.add(target); | 3082 inputs.add(target); |
| 3017 // TODO(5347): Try to avoid the need for calling [implementation] before | 3083 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 3018 // calling [addStaticSendArgumentsToList]. | 3084 // calling [addStaticSendArgumentsToList]. |
| 3019 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 3085 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 3020 constructor.implementation, | 3086 constructor.implementation, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3234 existingArguments.add(parameter.name.slowToString()); | 3300 existingArguments.add(parameter.name.slowToString()); |
| 3235 }); | 3301 }); |
| 3236 generateThrowNoSuchMethod(diagnosticNode, | 3302 generateThrowNoSuchMethod(diagnosticNode, |
| 3237 function.name.slowToString(), | 3303 function.name.slowToString(), |
| 3238 argumentNodes: argumentNodes, | 3304 argumentNodes: argumentNodes, |
| 3239 existingArguments: existingArguments); | 3305 existingArguments: existingArguments); |
| 3240 } | 3306 } |
| 3241 | 3307 |
| 3242 visitNewExpression(NewExpression node) { | 3308 visitNewExpression(NewExpression node) { |
| 3243 Element element = elements[node.send]; | 3309 Element element = elements[node.send]; |
| 3310 if (!Elements.isErroneousElement(element)) { |
| 3311 element = element.redirectionTarget; |
| 3312 } |
| 3244 if (Elements.isErroneousElement(element)) { | 3313 if (Elements.isErroneousElement(element)) { |
| 3245 ErroneousElement error = element; | 3314 ErroneousElement error = element; |
| 3246 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { | 3315 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { |
| 3247 generateThrowNoSuchMethod(node.send, | 3316 generateThrowNoSuchMethod(node.send, |
| 3248 getTargetName(error, 'constructor'), | 3317 getTargetName(error, 'constructor'), |
| 3249 argumentNodes: node.send.arguments); | 3318 argumentNodes: node.send.arguments); |
| 3250 } else if (error.messageKind == MessageKind.CANNOT_RESOLVE) { | 3319 } else if (error.messageKind == MessageKind.CANNOT_RESOLVE) { |
| 3251 Message message = error.messageKind.message(error.messageArguments); | 3320 Message message = error.messageKind.message(error.messageArguments); |
| 3252 generateRuntimeError(node.send, message.toString()); | 3321 generateRuntimeError(node.send, message.toString()); |
| 3253 } else { | 3322 } else { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3437 visit(node.expression); | 3506 visit(node.expression); |
| 3438 // Remove the result and reveal the duplicated receiver on the stack. | 3507 // Remove the result and reveal the duplicated receiver on the stack. |
| 3439 pop(); | 3508 pop(); |
| 3440 } | 3509 } |
| 3441 | 3510 |
| 3442 visitCascadeReceiver(CascadeReceiver node) { | 3511 visitCascadeReceiver(CascadeReceiver node) { |
| 3443 visit(node.expression); | 3512 visit(node.expression); |
| 3444 dup(); | 3513 dup(); |
| 3445 } | 3514 } |
| 3446 | 3515 |
| 3516 void handleInTryStatement() { |
| 3517 if (!inTryStatement) return; |
| 3518 HBasicBlock block = close(new HExitTry()); |
| 3519 HBasicBlock newBlock = graph.addNewBlock(); |
| 3520 block.addSuccessor(newBlock); |
| 3521 open(newBlock); |
| 3522 } |
| 3523 |
| 3447 visitReturn(Return node) { | 3524 visitReturn(Return node) { |
| 3448 if (identical(node.getBeginToken().stringValue, 'native')) { | 3525 if (identical(node.getBeginToken().stringValue, 'native')) { |
| 3449 native.handleSsaNative(this, node.expression); | 3526 native.handleSsaNative(this, node.expression); |
| 3450 return; | 3527 return; |
| 3451 } | 3528 } |
| 3452 if (node.isRedirectingFactoryBody) { | 3529 assert(invariant(node, !node.isRedirectingFactoryBody)); |
| 3453 compiler.internalError("Unimplemented: Redirecting factory constructor", | |
| 3454 node: node); | |
| 3455 } | |
| 3456 HInstruction value; | 3530 HInstruction value; |
| 3457 if (node.expression == null) { | 3531 if (node.expression == null) { |
| 3458 value = graph.addConstantNull(constantSystem); | 3532 value = graph.addConstantNull(constantSystem); |
| 3459 } else { | 3533 } else { |
| 3460 visit(node.expression); | 3534 visit(node.expression); |
| 3461 value = pop(); | 3535 value = pop(); |
| 3462 if (value is HForeign) { | 3536 if (value is HForeign) { |
| 3463 // TODO(6530, 6534): remove this check. | 3537 // TODO(6530, 6534): remove this check. |
| 3464 } else { | 3538 } else { |
| 3465 value = potentiallyCheckType(value, returnType); | 3539 value = potentiallyCheckType(value, returnType); |
| 3466 } | 3540 } |
| 3467 } | 3541 } |
| 3542 |
| 3543 handleInTryStatement(); |
| 3544 |
| 3468 if (!inliningStack.isEmpty) { | 3545 if (!inliningStack.isEmpty) { |
| 3469 localsHandler.updateLocal(returnElement, value); | 3546 localsHandler.updateLocal(returnElement, value); |
| 3470 } else { | 3547 } else { |
| 3471 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | 3548 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); |
| 3472 } | 3549 } |
| 3473 } | 3550 } |
| 3474 | 3551 |
| 3475 visitThrow(Throw node) { | 3552 visitThrow(Throw node) { |
| 3476 if (node.expression == null) { | 3553 if (node.expression == null) { |
| 3477 HInstruction exception = rethrowableException; | 3554 HInstruction exception = rethrowableException; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3548 visitEmptyStatement(EmptyStatement node) { | 3625 visitEmptyStatement(EmptyStatement node) { |
| 3549 // Do nothing, empty statement. | 3626 // Do nothing, empty statement. |
| 3550 } | 3627 } |
| 3551 | 3628 |
| 3552 visitModifiers(Modifiers node) { | 3629 visitModifiers(Modifiers node) { |
| 3553 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); | 3630 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); |
| 3554 } | 3631 } |
| 3555 | 3632 |
| 3556 visitBreakStatement(BreakStatement node) { | 3633 visitBreakStatement(BreakStatement node) { |
| 3557 assert(!isAborted()); | 3634 assert(!isAborted()); |
| 3635 handleInTryStatement(); |
| 3558 TargetElement target = elements[node]; | 3636 TargetElement target = elements[node]; |
| 3559 assert(target != null); | 3637 assert(target != null); |
| 3560 JumpHandler handler = jumpTargets[target]; | 3638 JumpHandler handler = jumpTargets[target]; |
| 3561 assert(handler != null); | 3639 assert(handler != null); |
| 3562 if (node.target == null) { | 3640 if (node.target == null) { |
| 3563 handler.generateBreak(); | 3641 handler.generateBreak(); |
| 3564 } else { | 3642 } else { |
| 3565 LabelElement label = elements[node.target]; | 3643 LabelElement label = elements[node.target]; |
| 3566 handler.generateBreak(label); | 3644 handler.generateBreak(label); |
| 3567 } | 3645 } |
| 3568 } | 3646 } |
| 3569 | 3647 |
| 3570 visitContinueStatement(ContinueStatement node) { | 3648 visitContinueStatement(ContinueStatement node) { |
| 3649 handleInTryStatement(); |
| 3571 TargetElement target = elements[node]; | 3650 TargetElement target = elements[node]; |
| 3572 assert(target != null); | 3651 assert(target != null); |
| 3573 JumpHandler handler = jumpTargets[target]; | 3652 JumpHandler handler = jumpTargets[target]; |
| 3574 assert(handler != null); | 3653 assert(handler != null); |
| 3575 if (node.target == null) { | 3654 if (node.target == null) { |
| 3576 handler.generateContinue(); | 3655 handler.generateContinue(); |
| 3577 } else { | 3656 } else { |
| 3578 LabelElement label = elements[node.target]; | 3657 LabelElement label = elements[node.target]; |
| 3579 assert(label != null); | 3658 assert(label != null); |
| 3580 handler.generateContinue(label); | 3659 handler.generateContinue(label); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3671 // a break or continue for a different target. In that case, this | 3750 // a break or continue for a different target. In that case, this |
| 3672 // label is also always unused. | 3751 // label is also always unused. |
| 3673 visit(body); | 3752 visit(body); |
| 3674 return; | 3753 return; |
| 3675 } | 3754 } |
| 3676 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 3755 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
| 3677 assert(targetElement.isBreakTarget); | 3756 assert(targetElement.isBreakTarget); |
| 3678 JumpHandler handler = new JumpHandler(this, targetElement); | 3757 JumpHandler handler = new JumpHandler(this, targetElement); |
| 3679 // Introduce a new basic block. | 3758 // Introduce a new basic block. |
| 3680 HBasicBlock entryBlock = openNewBlock(); | 3759 HBasicBlock entryBlock = openNewBlock(); |
| 3681 hackAroundPossiblyAbortingBody(node, () { visit(body); }); | 3760 visit(body); |
| 3682 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); | 3761 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
| 3683 | 3762 |
| 3684 HBasicBlock joinBlock = graph.addNewBlock(); | 3763 HBasicBlock joinBlock = graph.addNewBlock(); |
| 3685 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 3764 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 3686 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 3765 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 3687 breakInstruction.block.addSuccessor(joinBlock); | 3766 breakInstruction.block.addSuccessor(joinBlock); |
| 3688 breakLocals.add(locals); | 3767 breakLocals.add(locals); |
| 3689 }); | 3768 }); |
| 3690 bool hasBreak = breakLocals.length > 0; | 3769 bool hasBreak = breakLocals.length > 0; |
| 3691 if (!isAborted()) { | 3770 if (!isAborted()) { |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4100 // Save the current locals. The catch block and the finally block | 4179 // Save the current locals. The catch block and the finally block |
| 4101 // must not reuse the existing locals handler. None of the variables | 4180 // must not reuse the existing locals handler. None of the variables |
| 4102 // that have been defined in the body-block will be used, but for | 4181 // that have been defined in the body-block will be used, but for |
| 4103 // loops we will add (unnecessary) phis that will reference the body | 4182 // loops we will add (unnecessary) phis that will reference the body |
| 4104 // variables. This makes it look as if the variables were used | 4183 // variables. This makes it look as if the variables were used |
| 4105 // in a non-dominated block. | 4184 // in a non-dominated block. |
| 4106 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 4185 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 4107 HBasicBlock enterBlock = openNewBlock(); | 4186 HBasicBlock enterBlock = openNewBlock(); |
| 4108 HTry tryInstruction = new HTry(); | 4187 HTry tryInstruction = new HTry(); |
| 4109 close(tryInstruction); | 4188 close(tryInstruction); |
| 4189 bool oldInTryStatement = inTryStatement; |
| 4190 inTryStatement = true; |
| 4110 | 4191 |
| 4111 HBasicBlock startTryBlock; | 4192 HBasicBlock startTryBlock; |
| 4112 HBasicBlock endTryBlock; | 4193 HBasicBlock endTryBlock; |
| 4113 HBasicBlock startCatchBlock; | 4194 HBasicBlock startCatchBlock; |
| 4114 HBasicBlock endCatchBlock; | 4195 HBasicBlock endCatchBlock; |
| 4115 HBasicBlock startFinallyBlock; | 4196 HBasicBlock startFinallyBlock; |
| 4116 HBasicBlock endFinallyBlock; | 4197 HBasicBlock endFinallyBlock; |
| 4117 | 4198 |
| 4118 startTryBlock = graph.addNewBlock(); | 4199 startTryBlock = graph.addNewBlock(); |
| 4119 open(startTryBlock); | 4200 open(startTryBlock); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4214 open(startFinallyBlock); | 4295 open(startFinallyBlock); |
| 4215 visit(node.finallyBlock); | 4296 visit(node.finallyBlock); |
| 4216 if (!isAborted()) endFinallyBlock = close(new HGoto()); | 4297 if (!isAborted()) endFinallyBlock = close(new HGoto()); |
| 4217 tryInstruction.finallyBlock = startFinallyBlock; | 4298 tryInstruction.finallyBlock = startFinallyBlock; |
| 4218 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); | 4299 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); |
| 4219 } | 4300 } |
| 4220 | 4301 |
| 4221 HBasicBlock exitBlock = graph.addNewBlock(); | 4302 HBasicBlock exitBlock = graph.addNewBlock(); |
| 4222 | 4303 |
| 4223 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } | 4304 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } |
| 4305 addExitTrySuccessor(successor) { |
| 4306 if (successor == null) return; |
| 4307 // Iterate over all blocks created inside this try/catch, and |
| 4308 // attach successor information to blocks that end with |
| 4309 // [HExitTry]. |
| 4310 for (int i = startTryBlock.id; i < successor.id; i++) { |
| 4311 HBasicBlock block = graph.blocks[i]; |
| 4312 var last = block.last; |
| 4313 if (last is HExitTry) { |
| 4314 block.addSuccessor(successor); |
| 4315 } else if (last is HTry) { |
| 4316 // Skip all blocks inside this nested try/catch. |
| 4317 i = last.joinBlock.id; |
| 4318 } |
| 4319 } |
| 4320 } |
| 4224 | 4321 |
| 4225 // Setup all successors. The entry block that contains the [HTry] | 4322 // Setup all successors. The entry block that contains the [HTry] |
| 4226 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit | 4323 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit |
| 4227 // blocks as successors. | 4324 // blocks as successors. |
| 4228 enterBlock.addSuccessor(startTryBlock); | 4325 enterBlock.addSuccessor(startTryBlock); |
| 4229 addOptionalSuccessor(enterBlock, startCatchBlock); | 4326 addOptionalSuccessor(enterBlock, startCatchBlock); |
| 4230 addOptionalSuccessor(enterBlock, startFinallyBlock); | 4327 addOptionalSuccessor(enterBlock, startFinallyBlock); |
| 4231 enterBlock.addSuccessor(exitBlock); | 4328 enterBlock.addSuccessor(exitBlock); |
| 4232 | 4329 |
| 4233 // The body has either the catch or the finally block as successor. | 4330 // The body has either the catch or the finally block as successor. |
| 4234 if (endTryBlock != null) { | 4331 if (endTryBlock != null) { |
| 4235 assert(startCatchBlock != null || startFinallyBlock != null); | 4332 assert(startCatchBlock != null || startFinallyBlock != null); |
| 4236 endTryBlock.addSuccessor( | 4333 endTryBlock.addSuccessor( |
| 4237 startCatchBlock != null ? startCatchBlock : startFinallyBlock); | 4334 startCatchBlock != null ? startCatchBlock : startFinallyBlock); |
| 4238 } | 4335 } |
| 4239 | 4336 |
| 4240 // The catch block has either the finally or the exit block as | 4337 // The catch block has either the finally or the exit block as |
| 4241 // successor. | 4338 // successor. |
| 4242 if (endCatchBlock != null) { | 4339 if (endCatchBlock != null) { |
| 4243 endCatchBlock.addSuccessor( | 4340 endCatchBlock.addSuccessor( |
| 4244 startFinallyBlock != null ? startFinallyBlock : exitBlock); | 4341 startFinallyBlock != null ? startFinallyBlock : exitBlock); |
| 4245 } | 4342 } |
| 4246 | 4343 |
| 4247 // The finally block has the exit block as successor. | 4344 // The finally block has the exit block as successor. |
| 4248 if (endFinallyBlock != null) { | 4345 if (endFinallyBlock != null) { |
| 4249 endFinallyBlock.addSuccessor(exitBlock); | 4346 endFinallyBlock.addSuccessor(exitBlock); |
| 4250 } | 4347 } |
| 4251 | 4348 |
| 4349 // If a block inside try/catch aborts (eg with a return statement), |
| 4350 // we explicitely mark this block a predecessor of the catch |
| 4351 // block and the finally block. |
| 4352 addExitTrySuccessor(startCatchBlock); |
| 4353 addExitTrySuccessor(startFinallyBlock); |
| 4354 |
| 4252 // Use the locals handler not altered by the catch and finally | 4355 // Use the locals handler not altered by the catch and finally |
| 4253 // blocks. | 4356 // blocks. |
| 4254 localsHandler = savedLocals; | 4357 localsHandler = savedLocals; |
| 4255 open(exitBlock); | 4358 open(exitBlock); |
| 4256 enterBlock.setBlockFlow( | 4359 enterBlock.setBlockFlow( |
| 4257 new HTryBlockInformation( | 4360 new HTryBlockInformation( |
| 4258 wrapStatementGraph(bodyGraph), | 4361 wrapStatementGraph(bodyGraph), |
| 4259 exception, | 4362 exception, |
| 4260 wrapStatementGraph(catchGraph), | 4363 wrapStatementGraph(catchGraph), |
| 4261 wrapStatementGraph(finallyGraph)), | 4364 wrapStatementGraph(finallyGraph)), |
| 4262 exitBlock); | 4365 exitBlock); |
| 4366 inTryStatement = oldInTryStatement; |
| 4263 } | 4367 } |
| 4264 | 4368 |
| 4265 visitScriptTag(ScriptTag node) { | 4369 visitScriptTag(ScriptTag node) { |
| 4266 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); | 4370 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); |
| 4267 } | 4371 } |
| 4268 | 4372 |
| 4269 visitCatchBlock(CatchBlock node) { | 4373 visitCatchBlock(CatchBlock node) { |
| 4270 visit(node.block); | 4374 visit(node.block); |
| 4271 } | 4375 } |
| 4272 | 4376 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4283 ClassElement element = concreteType.getUniqueType(); | 4387 ClassElement element = concreteType.getUniqueType(); |
| 4284 if (element == null) return HType.UNKNOWN; | 4388 if (element == null) return HType.UNKNOWN; |
| 4285 if (element == builder.compiler.boolClass) return HType.BOOLEAN; | 4389 if (element == builder.compiler.boolClass) return HType.BOOLEAN; |
| 4286 if (element == builder.compiler.doubleClass) return HType.DOUBLE; | 4390 if (element == builder.compiler.doubleClass) return HType.DOUBLE; |
| 4287 if (element == builder.compiler.intClass) return HType.INTEGER; | 4391 if (element == builder.compiler.intClass) return HType.INTEGER; |
| 4288 if (element == builder.compiler.listClass) return HType.READABLE_ARRAY; | 4392 if (element == builder.compiler.listClass) return HType.READABLE_ARRAY; |
| 4289 if (element == builder.compiler.nullClass) return HType.NULL; | 4393 if (element == builder.compiler.nullClass) return HType.NULL; |
| 4290 if (element == builder.compiler.stringClass) return HType.STRING; | 4394 if (element == builder.compiler.stringClass) return HType.STRING; |
| 4291 return HType.UNKNOWN; | 4395 return HType.UNKNOWN; |
| 4292 } | 4396 } |
| 4293 | |
| 4294 /** HACK HACK HACK */ | |
| 4295 void hackAroundPossiblyAbortingBody(Node statement, void body()) { | |
| 4296 visitCondition() { | |
| 4297 stack.add(graph.addConstantBool(true, constantSystem)); | |
| 4298 } | |
| 4299 buildBody() { | |
| 4300 // TODO(lrn): Make sure to take continue into account. | |
| 4301 body(); | |
| 4302 } | |
| 4303 handleIf(statement, visitCondition, buildBody, null); | |
| 4304 } | |
| 4305 } | 4397 } |
| 4306 | 4398 |
| 4307 /** | 4399 /** |
| 4308 * Visitor that handles generation of string literals (LiteralString, | 4400 * Visitor that handles generation of string literals (LiteralString, |
| 4309 * StringInterpolation), and otherwise delegates to the given visitor for | 4401 * StringInterpolation), and otherwise delegates to the given visitor for |
| 4310 * non-literal subexpressions. | 4402 * non-literal subexpressions. |
| 4311 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 4403 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
| 4312 * expressions as well. | 4404 * expressions as well. |
| 4313 */ | 4405 */ |
| 4314 class StringBuilderVisitor extends Visitor { | 4406 class StringBuilderVisitor extends Visitor { |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4679 new HSubGraphBlockInformation(elseBranch.graph)); | 4771 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4680 | 4772 |
| 4681 HBasicBlock conditionStartBlock = conditionBranch.block; | 4773 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4682 conditionStartBlock.setBlockFlow(info, joinBlock); | 4774 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4683 SubGraph conditionGraph = conditionBranch.graph; | 4775 SubGraph conditionGraph = conditionBranch.graph; |
| 4684 HIf branch = conditionGraph.end.last; | 4776 HIf branch = conditionGraph.end.last; |
| 4685 assert(branch is HIf); | 4777 assert(branch is HIf); |
| 4686 branch.blockInformation = conditionStartBlock.blockFlow; | 4778 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4687 } | 4779 } |
| 4688 } | 4780 } |
| OLD | NEW |