1188 result = items.makeStackItem(pt); |
1189 result = items.makeStackItem(pt); |
1189 } |
1190 } |
1190 |
1191 |
1191 private void doHandleSwitchExpression(JCSwitchExpression tree) { |
1192 private void doHandleSwitchExpression(JCSwitchExpression tree) { |
1192 List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression; |
1193 List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression; |
|
1194 LocalItem prevSwitchResult = switchResult; |
1193 int limit = code.nextreg; |
1195 int limit = code.nextreg; |
1194 try { |
1196 try { |
1195 stackBeforeSwitchExpression = List.nil(); |
1197 stackBeforeSwitchExpression = List.nil(); |
|
1198 switchResult = null; |
1196 if (hasTry(tree)) { |
1199 if (hasTry(tree)) { |
1197 //if the switch expression contains try-catch, the catch handlers need to have |
1200 //if the switch expression contains try-catch, the catch handlers need to have |
1198 //an empty stack. So stash whole stack to local variables, and restore it before |
1201 //an empty stack. So stash whole stack to local variables, and restore it before |
1199 //breaks: |
1202 //breaks: |
1200 while (code.state.stacksize > 0) { |
1203 while (code.state.stacksize > 0) { |
1209 this.env.enclMethod.sym); |
1212 this.env.enclMethod.sym); |
1210 LocalItem item = items.new LocalItem(type, code.newLocal(var)); |
1213 LocalItem item = items.new LocalItem(type, code.newLocal(var)); |
1211 stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item); |
1214 stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item); |
1212 item.store(); |
1215 item.store(); |
1213 } |
1216 } |
|
1217 switchResult = makeTemp(tree.type); |
1214 } |
1218 } |
1215 int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize); |
1219 int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize); |
1216 try { |
1220 try { |
1217 handleSwitch(tree, tree.selector, tree.cases); |
1221 handleSwitch(tree, tree.selector, tree.cases); |
1218 } finally { |
1222 } finally { |
1219 code.setLetExprStackPos(prevLetExprStart); |
1223 code.setLetExprStackPos(prevLetExprStart); |
1220 } |
1224 } |
1221 } finally { |
1225 } finally { |
1222 stackBeforeSwitchExpression = prevStackBeforeSwitchExpression; |
1226 stackBeforeSwitchExpression = prevStackBeforeSwitchExpression; |
|
1227 switchResult = prevSwitchResult; |
1223 code.endScopes(limit); |
1228 code.endScopes(limit); |
1224 } |
1229 } |
1225 } |
1230 } |
1226 //where: |
1231 //where: |
1227 private boolean hasTry(JCSwitchExpression tree) { |
1232 private boolean hasTry(JCSwitchExpression tree) { |
1715 Assert.check(code.isStatementStart()); |
1720 Assert.check(code.isStatementStart()); |
1716 } |
1721 } |
1717 |
1722 |
1718 public void visitBreak(JCBreak tree) { |
1723 public void visitBreak(JCBreak tree) { |
1719 Assert.check(code.isStatementStart()); |
1724 Assert.check(code.isStatementStart()); |
|
1725 final Env<GenContext> targetEnv = unwindBreak(tree.target); |
|
1726 targetEnv.info.addExit(code.branch(goto_)); |
|
1727 endFinalizerGaps(env, targetEnv); |
|
1728 } |
|
1729 |
|
1730 public void visitYield(JCYield tree) { |
|
1731 Assert.check(code.isStatementStart()); |
1720 final Env<GenContext> targetEnv; |
1732 final Env<GenContext> targetEnv; |
1721 if (tree.isValueBreak()) { |
1733 if (inCondSwitchExpression) { |
1722 //restore stack as it was before the switch expression: |
1734 CondItem value = genCond(tree.value, CRT_FLOW_TARGET); |
1723 for (LocalItem li : stackBeforeSwitchExpression) { |
1735 Chain falseJumps = value.jumpFalse(); |
1724 li.load(); |
1736 |
1725 } |
1737 code.resolve(value.trueJumps); |
1726 if (inCondSwitchExpression) { |
1738 Env<GenContext> localEnv = unwindBreak(tree.target); |
1727 CondItem value = genCond(tree.value, CRT_FLOW_TARGET); |
1739 reloadStackBeforeSwitchExpr(); |
1728 Chain falseJumps = value.jumpFalse(); |
1740 Chain trueJumps = code.branch(goto_); |
1729 targetEnv = unwindBreak(tree); |
1741 |
1730 code.resolve(value.trueJumps); |
1742 endFinalizerGaps(env, localEnv); |
1731 Chain trueJumps = code.branch(goto_); |
1743 |
1732 if (switchExpressionTrueChain == null) { |
1744 code.resolve(falseJumps); |
1733 switchExpressionTrueChain = trueJumps; |
1745 targetEnv = unwindBreak(tree.target); |
1734 } else { |
1746 reloadStackBeforeSwitchExpr(); |
1735 switchExpressionTrueChain = |
1747 falseJumps = code.branch(goto_); |
1736 Code.mergeChains(switchExpressionTrueChain, trueJumps); |
1748 |
1737 } |
1749 if (switchExpressionTrueChain == null) { |
1738 if (switchExpressionFalseChain == null) { |
1750 switchExpressionTrueChain = trueJumps; |
1739 switchExpressionFalseChain = falseJumps; |
|
1740 } else { |
|
1741 switchExpressionFalseChain = |
|
1742 Code.mergeChains(switchExpressionFalseChain, falseJumps); |
|
1743 } |
|
1744 } else { |
1751 } else { |
1745 genExpr(tree.value, pt).load(); |
1752 switchExpressionTrueChain = |
|
1753 Code.mergeChains(switchExpressionTrueChain, trueJumps); |
|
1754 } |
|
1755 if (switchExpressionFalseChain == null) { |
|
1756 switchExpressionFalseChain = falseJumps; |
|
1757 } else { |
|
1758 switchExpressionFalseChain = |
|
1759 Code.mergeChains(switchExpressionFalseChain, falseJumps); |
|
1760 } |
|
1761 } else { |
|
1762 genExpr(tree.value, pt).load(); |
|
1763 if (switchResult != null) |
|
1764 switchResult.store(); |
|
1765 |
|
1766 targetEnv = unwindBreak(tree.target); |
|
1767 |
|
1768 if (code.isAlive()) { |
|
1769 reloadStackBeforeSwitchExpr(); |
|
1770 if (switchResult != null) |
|
1771 switchResult.load(); |
|
1772 |
1746 code.state.forceStackTop(tree.target.type); |
1773 code.state.forceStackTop(tree.target.type); |
1747 targetEnv = unwindBreak(tree); |
|
1748 targetEnv.info.addExit(code.branch(goto_)); |
1774 targetEnv.info.addExit(code.branch(goto_)); |
1749 } |
1775 code.markDead(); |
1750 } else { |
1776 } |
1751 targetEnv = unwindBreak(tree); |
|
1752 targetEnv.info.addExit(code.branch(goto_)); |
|
1753 } |
1777 } |
1754 endFinalizerGaps(env, targetEnv); |
1778 endFinalizerGaps(env, targetEnv); |
1755 } |
1779 } |
1756 //where: |
1780 //where: |
1757 private Env<GenContext> unwindBreak(JCBreak tree) { |
1781 /** As side-effect, might mark code as dead disabling any further emission. |
|
1782 */ |
|
1783 private Env<GenContext> unwindBreak(JCTree target) { |
1758 int tmpPos = code.pendingStatPos; |
1784 int tmpPos = code.pendingStatPos; |
1759 Env<GenContext> targetEnv = unwind(tree.target, env); |
1785 Env<GenContext> targetEnv = unwind(target, env); |
1760 code.pendingStatPos = tmpPos; |
1786 code.pendingStatPos = tmpPos; |
1761 return targetEnv; |
1787 return targetEnv; |
|
1788 } |
|
1789 |
|
1790 private void reloadStackBeforeSwitchExpr() { |
|
1791 for (LocalItem li : stackBeforeSwitchExpression) |
|
1792 li.load(); |
1762 } |
1793 } |
1763 |
1794 |
1764 public void visitContinue(JCContinue tree) { |
1795 public void visitContinue(JCContinue tree) { |
1765 int tmpPos = code.pendingStatPos; |
1796 int tmpPos = code.pendingStatPos; |
1766 Env<GenContext> targetEnv = unwind(tree.target, env); |
1797 Env<GenContext> targetEnv = unwind(tree.target, env); |