src/share/classes/com/sun/tools/javac/comp/Flow.java

changeset 1713
2ca9e7d50136
parent 1693
c430f1cde21c
child 1790
9f11c7676cd5
equal deleted inserted replaced
1712:3c02d2f1a421 1713:2ca9e7d50136
33 import com.sun.tools.javac.tree.*; 33 import com.sun.tools.javac.tree.*;
34 import com.sun.tools.javac.util.*; 34 import com.sun.tools.javac.util.*;
35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
36 36
37 import com.sun.tools.javac.code.Symbol.*; 37 import com.sun.tools.javac.code.Symbol.*;
38 import com.sun.tools.javac.comp.Resolve;
39 import com.sun.tools.javac.tree.JCTree.*; 38 import com.sun.tools.javac.tree.JCTree.*;
40 39
41 import static com.sun.tools.javac.code.Flags.*; 40 import static com.sun.tools.javac.code.Flags.*;
42 import static com.sun.tools.javac.code.Flags.BLOCK; 41 import static com.sun.tools.javac.code.Flags.BLOCK;
43 import static com.sun.tools.javac.code.Kinds.*; 42 import static com.sun.tools.javac.code.Kinds.*;
275 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); 274 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
276 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); 275 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
277 } 276 }
278 277
279 /** 278 /**
279 * Utility method to reset several Bits instances.
280 */
281 private void resetBits(Bits... bits) {
282 for (Bits b : bits) {
283 b.reset();
284 }
285 }
286
287 /**
280 * Base visitor class for all visitors implementing dataflow analysis logic. 288 * Base visitor class for all visitors implementing dataflow analysis logic.
281 * This class define the shared logic for handling jumps (break/continue statements). 289 * This class define the shared logic for handling jumps (break/continue statements).
282 */ 290 */
283 static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner { 291 static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
284 292
1292 */ 1300 */
1293 class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> { 1301 class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
1294 1302
1295 /** The set of definitely assigned variables. 1303 /** The set of definitely assigned variables.
1296 */ 1304 */
1297 Bits inits; 1305 final Bits inits;
1298 1306
1299 /** The set of definitely unassigned variables. 1307 /** The set of definitely unassigned variables.
1300 */ 1308 */
1301 Bits uninits; 1309 final Bits uninits;
1302 1310
1303 /** The set of variables that are definitely unassigned everywhere 1311 /** The set of variables that are definitely unassigned everywhere
1304 * in current try block. This variable is maintained lazily; it is 1312 * in current try block. This variable is maintained lazily; it is
1305 * updated only when something gets removed from uninits, 1313 * updated only when something gets removed from uninits,
1306 * typically by being assigned in reachable code. To obtain the 1314 * typically by being assigned in reachable code. To obtain the
1307 * correct set of variables which are definitely unassigned 1315 * correct set of variables which are definitely unassigned
1308 * anywhere in current try block, intersect uninitsTry and 1316 * anywhere in current try block, intersect uninitsTry and
1309 * uninits. 1317 * uninits.
1310 */ 1318 */
1311 Bits uninitsTry; 1319 final Bits uninitsTry;
1312 1320
1313 /** When analyzing a condition, inits and uninits are null. 1321 /** When analyzing a condition, inits and uninits are null.
1314 * Instead we have: 1322 * Instead we have:
1315 */ 1323 */
1316 Bits initsWhenTrue; 1324 final Bits initsWhenTrue;
1317 Bits initsWhenFalse; 1325 final Bits initsWhenFalse;
1318 Bits uninitsWhenTrue; 1326 final Bits uninitsWhenTrue;
1319 Bits uninitsWhenFalse; 1327 final Bits uninitsWhenFalse;
1320 1328
1321 /** A mapping from addresses to variable symbols. 1329 /** A mapping from addresses to variable symbols.
1322 */ 1330 */
1323 VarSymbol[] vars; 1331 VarSymbol[] vars;
1324 1332
1346 FlowKind flowKind = FlowKind.NORMAL; 1354 FlowKind flowKind = FlowKind.NORMAL;
1347 1355
1348 /** The starting position of the analysed tree */ 1356 /** The starting position of the analysed tree */
1349 int startPos; 1357 int startPos;
1350 1358
1359 AssignAnalyzer() {
1360 inits = new Bits();
1361 uninits = new Bits();
1362 uninitsTry = new Bits();
1363 initsWhenTrue = new Bits(true);
1364 initsWhenFalse = new Bits(true);
1365 uninitsWhenTrue = new Bits(true);
1366 uninitsWhenFalse = new Bits(true);
1367 }
1368
1351 class AssignPendingExit extends BaseAnalyzer.PendingExit { 1369 class AssignPendingExit extends BaseAnalyzer.PendingExit {
1352 1370
1353 Bits exit_inits; 1371 final Bits exit_inits = new Bits(true);
1354 Bits exit_uninits; 1372 final Bits exit_uninits = new Bits(true);
1355 1373
1356 AssignPendingExit(JCTree tree, Bits inits, Bits uninits) { 1374 AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
1357 super(tree); 1375 super(tree);
1358 this.exit_inits = inits.dup(); 1376 this.exit_inits.assign(inits);
1359 this.exit_uninits = uninits.dup(); 1377 this.exit_uninits.assign(uninits);
1360 } 1378 }
1361 1379
1362 void resolveJump() { 1380 void resolveJump() {
1363 inits.andSet(exit_inits); 1381 inits.andSet(exit_inits);
1364 uninits.andSet(exit_uninits); 1382 uninits.andSet(exit_uninits);
1474 } 1492 }
1475 1493
1476 /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets 1494 /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
1477 */ 1495 */
1478 void split(boolean setToNull) { 1496 void split(boolean setToNull) {
1479 initsWhenFalse = inits.dup(); 1497 initsWhenFalse.assign(inits);
1480 uninitsWhenFalse = uninits.dup(); 1498 uninitsWhenFalse.assign(uninits);
1481 initsWhenTrue = inits; 1499 initsWhenTrue.assign(inits);
1482 uninitsWhenTrue = uninits; 1500 uninitsWhenTrue.assign(uninits);
1483 if (setToNull) 1501 if (setToNull) {
1484 inits = uninits = null; 1502 resetBits(inits, uninits);
1503 }
1485 } 1504 }
1486 1505
1487 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. 1506 /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
1488 */ 1507 */
1489 void merge() { 1508 void merge() {
1490 inits = initsWhenFalse.andSet(initsWhenTrue); 1509 inits.assign(initsWhenFalse.andSet(initsWhenTrue));
1491 uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); 1510 uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
1492 } 1511 }
1493 1512
1494 /* ************************************************************************ 1513 /* ************************************************************************
1495 * Visitor methods for statements and definitions 1514 * Visitor methods for statements and definitions
1496 *************************************************************************/ 1515 *************************************************************************/
1499 * (un)initsWhenTrue(WhenFalse) on exit. 1518 * (un)initsWhenTrue(WhenFalse) on exit.
1500 */ 1519 */
1501 void scanExpr(JCTree tree) { 1520 void scanExpr(JCTree tree) {
1502 if (tree != null) { 1521 if (tree != null) {
1503 scan(tree); 1522 scan(tree);
1504 if (inits == null) merge(); 1523 if (inits.isReset()) merge();
1505 } 1524 }
1506 } 1525 }
1507 1526
1508 /** Analyze a list of expressions. 1527 /** Analyze a list of expressions.
1509 */ 1528 */
1516 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) 1535 /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
1517 * rather than (un)inits on exit. 1536 * rather than (un)inits on exit.
1518 */ 1537 */
1519 void scanCond(JCTree tree) { 1538 void scanCond(JCTree tree) {
1520 if (tree.type.isFalse()) { 1539 if (tree.type.isFalse()) {
1521 if (inits == null) merge(); 1540 if (inits.isReset()) merge();
1522 initsWhenTrue = inits.dup(); 1541 initsWhenTrue.assign(inits);
1523 initsWhenTrue.inclRange(firstadr, nextadr); 1542 initsWhenTrue.inclRange(firstadr, nextadr);
1524 uninitsWhenTrue = uninits.dup(); 1543 uninitsWhenTrue.assign(uninits);
1525 uninitsWhenTrue.inclRange(firstadr, nextadr); 1544 uninitsWhenTrue.inclRange(firstadr, nextadr);
1526 initsWhenFalse = inits; 1545 initsWhenFalse.assign(inits);
1527 uninitsWhenFalse = uninits; 1546 uninitsWhenFalse.assign(uninits);
1528 } else if (tree.type.isTrue()) { 1547 } else if (tree.type.isTrue()) {
1529 if (inits == null) merge(); 1548 if (inits.isReset()) merge();
1530 initsWhenFalse = inits.dup(); 1549 initsWhenFalse.assign(inits);
1531 initsWhenFalse.inclRange(firstadr, nextadr); 1550 initsWhenFalse.inclRange(firstadr, nextadr);
1532 uninitsWhenFalse = uninits.dup(); 1551 uninitsWhenFalse.assign(uninits);
1533 uninitsWhenFalse.inclRange(firstadr, nextadr); 1552 uninitsWhenFalse.inclRange(firstadr, nextadr);
1534 initsWhenTrue = inits; 1553 initsWhenTrue.assign(inits);
1535 uninitsWhenTrue = uninits; 1554 uninitsWhenTrue.assign(uninits);
1536 } else { 1555 } else {
1537 scan(tree); 1556 scan(tree);
1538 if (inits != null) 1557 if (!inits.isReset())
1539 split(tree.type != syms.unknownType); 1558 split(tree.type != syms.unknownType);
1540 } 1559 }
1541 if (tree.type != syms.unknownType) 1560 if (tree.type != syms.unknownType) {
1542 inits = uninits = null; 1561 resetBits(inits, uninits);
1562 }
1543 } 1563 }
1544 1564
1545 /* ------------ Visitor methods for various sorts of trees -------------*/ 1565 /* ------------ Visitor methods for various sorts of trees -------------*/
1546 1566
1547 public void visitClassDef(JCClassDecl tree) { 1567 public void visitClassDef(JCClassDecl tree) {
1617 } 1637 }
1618 1638
1619 public void visitMethodDef(JCMethodDecl tree) { 1639 public void visitMethodDef(JCMethodDecl tree) {
1620 if (tree.body == null) return; 1640 if (tree.body == null) return;
1621 1641
1622 Bits initsPrev = inits.dup(); 1642 final Bits initsPrev = new Bits(inits);
1623 Bits uninitsPrev = uninits.dup(); 1643 final Bits uninitsPrev = new Bits(uninits);
1624 int nextadrPrev = nextadr; 1644 int nextadrPrev = nextadr;
1625 int firstadrPrev = firstadr; 1645 int firstadrPrev = firstadr;
1626 int returnadrPrev = returnadr; 1646 int returnadrPrev = returnadr;
1627 Lint lintPrev = lint; 1647 Lint lintPrev = lint;
1628 1648
1656 while (exits.nonEmpty()) { 1676 while (exits.nonEmpty()) {
1657 AssignPendingExit exit = exits.head; 1677 AssignPendingExit exit = exits.head;
1658 exits = exits.tail; 1678 exits = exits.tail;
1659 Assert.check(exit.tree.hasTag(RETURN), exit.tree); 1679 Assert.check(exit.tree.hasTag(RETURN), exit.tree);
1660 if (isInitialConstructor) { 1680 if (isInitialConstructor) {
1661 inits = exit.exit_inits; 1681 inits.assign(exit.exit_inits);
1662 for (int i = firstadr; i < nextadr; i++) 1682 for (int i = firstadr; i < nextadr; i++)
1663 checkInit(exit.tree.pos(), vars[i]); 1683 checkInit(exit.tree.pos(), vars[i]);
1664 } 1684 }
1665 } 1685 }
1666 } finally { 1686 } finally {
1667 inits = initsPrev; 1687 inits.assign(initsPrev);
1668 uninits = uninitsPrev; 1688 uninits.assign(uninitsPrev);
1669 nextadr = nextadrPrev; 1689 nextadr = nextadrPrev;
1670 firstadr = firstadrPrev; 1690 firstadr = firstadrPrev;
1671 returnadr = returnadrPrev; 1691 returnadr = returnadrPrev;
1672 lint = lintPrev; 1692 lint = lintPrev;
1673 } 1693 }
1696 1716
1697 public void visitDoLoop(JCDoWhileLoop tree) { 1717 public void visitDoLoop(JCDoWhileLoop tree) {
1698 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1718 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1699 FlowKind prevFlowKind = flowKind; 1719 FlowKind prevFlowKind = flowKind;
1700 flowKind = FlowKind.NORMAL; 1720 flowKind = FlowKind.NORMAL;
1701 Bits initsSkip = null; 1721 final Bits initsSkip = new Bits(true);
1702 Bits uninitsSkip = null; 1722 final Bits uninitsSkip = new Bits(true);
1703 pendingExits = new ListBuffer<AssignPendingExit>(); 1723 pendingExits = new ListBuffer<AssignPendingExit>();
1704 int prevErrors = log.nerrors; 1724 int prevErrors = log.nerrors;
1705 do { 1725 do {
1706 Bits uninitsEntry = uninits.dup(); 1726 final Bits uninitsEntry = new Bits(uninits);
1707 uninitsEntry.excludeFrom(nextadr); 1727 uninitsEntry.excludeFrom(nextadr);
1708 scan(tree.body); 1728 scan(tree.body);
1709 resolveContinues(tree); 1729 resolveContinues(tree);
1710 scanCond(tree.cond); 1730 scanCond(tree.cond);
1711 if (!flowKind.isFinal()) { 1731 if (!flowKind.isFinal()) {
1712 initsSkip = initsWhenFalse; 1732 initsSkip.assign(initsWhenFalse);
1713 uninitsSkip = uninitsWhenFalse; 1733 uninitsSkip.assign(uninitsWhenFalse);
1714 } 1734 }
1715 if (log.nerrors != prevErrors || 1735 if (log.nerrors != prevErrors ||
1716 flowKind.isFinal() || 1736 flowKind.isFinal() ||
1717 uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) 1737 new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
1718 break; 1738 break;
1719 inits = initsWhenTrue; 1739 inits.assign(initsWhenTrue);
1720 uninits = uninitsEntry.andSet(uninitsWhenTrue); 1740 uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
1721 flowKind = FlowKind.SPECULATIVE_LOOP; 1741 flowKind = FlowKind.SPECULATIVE_LOOP;
1722 } while (true); 1742 } while (true);
1723 flowKind = prevFlowKind; 1743 flowKind = prevFlowKind;
1724 inits = initsSkip; 1744 inits.assign(initsSkip);
1725 uninits = uninitsSkip; 1745 uninits.assign(uninitsSkip);
1726 resolveBreaks(tree, prevPendingExits); 1746 resolveBreaks(tree, prevPendingExits);
1727 } 1747 }
1728 1748
1729 public void visitWhileLoop(JCWhileLoop tree) { 1749 public void visitWhileLoop(JCWhileLoop tree) {
1730 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1750 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1731 FlowKind prevFlowKind = flowKind; 1751 FlowKind prevFlowKind = flowKind;
1732 flowKind = FlowKind.NORMAL; 1752 flowKind = FlowKind.NORMAL;
1733 Bits initsSkip = null; 1753 final Bits initsSkip = new Bits(true);
1734 Bits uninitsSkip = null; 1754 final Bits uninitsSkip = new Bits(true);
1735 pendingExits = new ListBuffer<AssignPendingExit>(); 1755 pendingExits = new ListBuffer<AssignPendingExit>();
1736 int prevErrors = log.nerrors; 1756 int prevErrors = log.nerrors;
1737 Bits uninitsEntry = uninits.dup(); 1757 final Bits uninitsEntry = new Bits(uninits);
1738 uninitsEntry.excludeFrom(nextadr); 1758 uninitsEntry.excludeFrom(nextadr);
1739 do { 1759 do {
1740 scanCond(tree.cond); 1760 scanCond(tree.cond);
1741 if (!flowKind.isFinal()) { 1761 if (!flowKind.isFinal()) {
1742 initsSkip = initsWhenFalse; 1762 initsSkip.assign(initsWhenFalse) ;
1743 uninitsSkip = uninitsWhenFalse; 1763 uninitsSkip.assign(uninitsWhenFalse);
1744 } 1764 }
1745 inits = initsWhenTrue; 1765 inits.assign(initsWhenTrue);
1746 uninits = uninitsWhenTrue; 1766 uninits.assign(uninitsWhenTrue);
1747 scan(tree.body); 1767 scan(tree.body);
1748 resolveContinues(tree); 1768 resolveContinues(tree);
1749 if (log.nerrors != prevErrors || 1769 if (log.nerrors != prevErrors ||
1750 flowKind.isFinal() || 1770 flowKind.isFinal() ||
1751 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) 1771 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1752 break; 1772 break;
1753 uninits = uninitsEntry.andSet(uninits); 1773 uninits.assign(uninitsEntry.andSet(uninits));
1754 flowKind = FlowKind.SPECULATIVE_LOOP; 1774 flowKind = FlowKind.SPECULATIVE_LOOP;
1755 } while (true); 1775 } while (true);
1756 flowKind = prevFlowKind; 1776 flowKind = prevFlowKind;
1757 //a variable is DA/DU after the while statement, if it's DA/DU assuming the 1777 //a variable is DA/DU after the while statement, if it's DA/DU assuming the
1758 //branch is not taken AND if it's DA/DU before any break statement 1778 //branch is not taken AND if it's DA/DU before any break statement
1759 inits = initsSkip; 1779 inits.assign(initsSkip);
1760 uninits = uninitsSkip; 1780 uninits.assign(uninitsSkip);
1761 resolveBreaks(tree, prevPendingExits); 1781 resolveBreaks(tree, prevPendingExits);
1762 } 1782 }
1763 1783
1764 public void visitForLoop(JCForLoop tree) { 1784 public void visitForLoop(JCForLoop tree) {
1765 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1785 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1766 FlowKind prevFlowKind = flowKind; 1786 FlowKind prevFlowKind = flowKind;
1767 flowKind = FlowKind.NORMAL; 1787 flowKind = FlowKind.NORMAL;
1768 int nextadrPrev = nextadr; 1788 int nextadrPrev = nextadr;
1769 scan(tree.init); 1789 scan(tree.init);
1770 Bits initsSkip = null; 1790 final Bits initsSkip = new Bits(true);
1771 Bits uninitsSkip = null; 1791 final Bits uninitsSkip = new Bits(true);
1772 pendingExits = new ListBuffer<AssignPendingExit>(); 1792 pendingExits = new ListBuffer<AssignPendingExit>();
1773 int prevErrors = log.nerrors; 1793 int prevErrors = log.nerrors;
1774 do { 1794 do {
1775 Bits uninitsEntry = uninits.dup(); 1795 final Bits uninitsEntry = new Bits(uninits);
1776 uninitsEntry.excludeFrom(nextadr); 1796 uninitsEntry.excludeFrom(nextadr);
1777 if (tree.cond != null) { 1797 if (tree.cond != null) {
1778 scanCond(tree.cond); 1798 scanCond(tree.cond);
1779 if (!flowKind.isFinal()) { 1799 if (!flowKind.isFinal()) {
1780 initsSkip = initsWhenFalse; 1800 initsSkip.assign(initsWhenFalse);
1781 uninitsSkip = uninitsWhenFalse; 1801 uninitsSkip.assign(uninitsWhenFalse);
1782 } 1802 }
1783 inits = initsWhenTrue; 1803 inits.assign(initsWhenTrue);
1784 uninits = uninitsWhenTrue; 1804 uninits.assign(uninitsWhenTrue);
1785 } else if (!flowKind.isFinal()) { 1805 } else if (!flowKind.isFinal()) {
1786 initsSkip = inits.dup(); 1806 initsSkip.assign(inits);
1787 initsSkip.inclRange(firstadr, nextadr); 1807 initsSkip.inclRange(firstadr, nextadr);
1788 uninitsSkip = uninits.dup(); 1808 uninitsSkip.assign(uninits);
1789 uninitsSkip.inclRange(firstadr, nextadr); 1809 uninitsSkip.inclRange(firstadr, nextadr);
1790 } 1810 }
1791 scan(tree.body); 1811 scan(tree.body);
1792 resolveContinues(tree); 1812 resolveContinues(tree);
1793 scan(tree.step); 1813 scan(tree.step);
1794 if (log.nerrors != prevErrors || 1814 if (log.nerrors != prevErrors ||
1795 flowKind.isFinal() || 1815 flowKind.isFinal() ||
1796 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) 1816 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1797 break; 1817 break;
1798 uninits = uninitsEntry.andSet(uninits); 1818 uninits.assign(uninitsEntry.andSet(uninits));
1799 flowKind = FlowKind.SPECULATIVE_LOOP; 1819 flowKind = FlowKind.SPECULATIVE_LOOP;
1800 } while (true); 1820 } while (true);
1801 flowKind = prevFlowKind; 1821 flowKind = prevFlowKind;
1802 //a variable is DA/DU after a for loop, if it's DA/DU assuming the 1822 //a variable is DA/DU after a for loop, if it's DA/DU assuming the
1803 //branch is not taken AND if it's DA/DU before any break statement 1823 //branch is not taken AND if it's DA/DU before any break statement
1804 inits = initsSkip; 1824 inits.assign(initsSkip);
1805 uninits = uninitsSkip; 1825 uninits.assign(uninitsSkip);
1806 resolveBreaks(tree, prevPendingExits); 1826 resolveBreaks(tree, prevPendingExits);
1807 nextadr = nextadrPrev; 1827 nextadr = nextadrPrev;
1808 } 1828 }
1809 1829
1810 public void visitForeachLoop(JCEnhancedForLoop tree) { 1830 public void visitForeachLoop(JCEnhancedForLoop tree) {
1813 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1833 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1814 FlowKind prevFlowKind = flowKind; 1834 FlowKind prevFlowKind = flowKind;
1815 flowKind = FlowKind.NORMAL; 1835 flowKind = FlowKind.NORMAL;
1816 int nextadrPrev = nextadr; 1836 int nextadrPrev = nextadr;
1817 scan(tree.expr); 1837 scan(tree.expr);
1818 Bits initsStart = inits.dup(); 1838 final Bits initsStart = new Bits(inits);
1819 Bits uninitsStart = uninits.dup(); 1839 final Bits uninitsStart = new Bits(uninits);
1820 1840
1821 letInit(tree.pos(), tree.var.sym); 1841 letInit(tree.pos(), tree.var.sym);
1822 pendingExits = new ListBuffer<AssignPendingExit>(); 1842 pendingExits = new ListBuffer<AssignPendingExit>();
1823 int prevErrors = log.nerrors; 1843 int prevErrors = log.nerrors;
1824 do { 1844 do {
1825 Bits uninitsEntry = uninits.dup(); 1845 final Bits uninitsEntry = new Bits(uninits);
1826 uninitsEntry.excludeFrom(nextadr); 1846 uninitsEntry.excludeFrom(nextadr);
1827 scan(tree.body); 1847 scan(tree.body);
1828 resolveContinues(tree); 1848 resolveContinues(tree);
1829 if (log.nerrors != prevErrors || 1849 if (log.nerrors != prevErrors ||
1830 flowKind.isFinal() || 1850 flowKind.isFinal() ||
1831 uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) 1851 new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
1832 break; 1852 break;
1833 uninits = uninitsEntry.andSet(uninits); 1853 uninits.assign(uninitsEntry.andSet(uninits));
1834 flowKind = FlowKind.SPECULATIVE_LOOP; 1854 flowKind = FlowKind.SPECULATIVE_LOOP;
1835 } while (true); 1855 } while (true);
1836 flowKind = prevFlowKind; 1856 flowKind = prevFlowKind;
1837 inits = initsStart; 1857 inits.assign(initsStart);
1838 uninits = uninitsStart.andSet(uninits); 1858 uninits.assign(uninitsStart.andSet(uninits));
1839 resolveBreaks(tree, prevPendingExits); 1859 resolveBreaks(tree, prevPendingExits);
1840 nextadr = nextadrPrev; 1860 nextadr = nextadrPrev;
1841 } 1861 }
1842 1862
1843 public void visitLabelled(JCLabeledStatement tree) { 1863 public void visitLabelled(JCLabeledStatement tree) {
1850 public void visitSwitch(JCSwitch tree) { 1870 public void visitSwitch(JCSwitch tree) {
1851 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1871 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1852 pendingExits = new ListBuffer<AssignPendingExit>(); 1872 pendingExits = new ListBuffer<AssignPendingExit>();
1853 int nextadrPrev = nextadr; 1873 int nextadrPrev = nextadr;
1854 scanExpr(tree.selector); 1874 scanExpr(tree.selector);
1855 Bits initsSwitch = inits; 1875 final Bits initsSwitch = new Bits(inits);
1856 Bits uninitsSwitch = uninits.dup(); 1876 final Bits uninitsSwitch = new Bits(uninits);
1857 boolean hasDefault = false; 1877 boolean hasDefault = false;
1858 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1878 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
1859 inits = initsSwitch.dup(); 1879 inits.assign(initsSwitch);
1860 uninits = uninits.andSet(uninitsSwitch); 1880 uninits.assign(uninits.andSet(uninitsSwitch));
1861 JCCase c = l.head; 1881 JCCase c = l.head;
1862 if (c.pat == null) 1882 if (c.pat == null)
1863 hasDefault = true; 1883 hasDefault = true;
1864 else 1884 else
1865 scanExpr(c.pat); 1885 scanExpr(c.pat);
1873 resolveBreaks(tree, prevPendingExits); 1893 resolveBreaks(tree, prevPendingExits);
1874 nextadr = nextadrPrev; 1894 nextadr = nextadrPrev;
1875 } 1895 }
1876 // where 1896 // where
1877 /** Add any variables defined in stats to inits and uninits. */ 1897 /** Add any variables defined in stats to inits and uninits. */
1878 private void addVars(List<JCStatement> stats, Bits inits, 1898 private void addVars(List<JCStatement> stats, final Bits inits,
1879 Bits uninits) { 1899 final Bits uninits) {
1880 for (;stats.nonEmpty(); stats = stats.tail) { 1900 for (;stats.nonEmpty(); stats = stats.tail) {
1881 JCTree stat = stats.head; 1901 JCTree stat = stats.head;
1882 if (stat.hasTag(VARDEF)) { 1902 if (stat.hasTag(VARDEF)) {
1883 int adr = ((JCVariableDecl) stat).sym.adr; 1903 int adr = ((JCVariableDecl) stat).sym.adr;
1884 inits.excl(adr); 1904 inits.excl(adr);
1887 } 1907 }
1888 } 1908 }
1889 1909
1890 public void visitTry(JCTry tree) { 1910 public void visitTry(JCTry tree) {
1891 ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb(); 1911 ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
1892 Bits uninitsTryPrev = uninitsTry; 1912 final Bits uninitsTryPrev = new Bits(uninitsTry);
1893 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits; 1913 ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
1894 pendingExits = new ListBuffer<AssignPendingExit>(); 1914 pendingExits = new ListBuffer<AssignPendingExit>();
1895 Bits initsTry = inits.dup(); 1915 final Bits initsTry = new Bits(inits);
1896 uninitsTry = uninits.dup(); 1916 uninitsTry.assign(uninits);
1897 for (JCTree resource : tree.resources) { 1917 for (JCTree resource : tree.resources) {
1898 if (resource instanceof JCVariableDecl) { 1918 if (resource instanceof JCVariableDecl) {
1899 JCVariableDecl vdecl = (JCVariableDecl) resource; 1919 JCVariableDecl vdecl = (JCVariableDecl) resource;
1900 visitVarDef(vdecl); 1920 visitVarDef(vdecl);
1901 unrefdResources.enter(vdecl.sym); 1921 unrefdResources.enter(vdecl.sym);
1906 throw new AssertionError(tree); // parser error 1926 throw new AssertionError(tree); // parser error
1907 } 1927 }
1908 } 1928 }
1909 scan(tree.body); 1929 scan(tree.body);
1910 uninitsTry.andSet(uninits); 1930 uninitsTry.andSet(uninits);
1911 Bits initsEnd = inits; 1931 final Bits initsEnd = new Bits(inits);
1912 Bits uninitsEnd = uninits; 1932 final Bits uninitsEnd = new Bits(uninits);
1913 int nextadrCatch = nextadr; 1933 int nextadrCatch = nextadr;
1914 1934
1915 if (!resourceVarDecls.isEmpty() && 1935 if (!resourceVarDecls.isEmpty() &&
1916 lint.isEnabled(Lint.LintCategory.TRY)) { 1936 lint.isEnabled(Lint.LintCategory.TRY)) {
1917 for (JCVariableDecl resVar : resourceVarDecls) { 1937 for (JCVariableDecl resVar : resourceVarDecls) {
1923 } 1943 }
1924 } 1944 }
1925 1945
1926 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1946 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1927 JCVariableDecl param = l.head.param; 1947 JCVariableDecl param = l.head.param;
1928 inits = initsTry.dup(); 1948 inits.assign(initsTry);
1929 uninits = uninitsTry.dup(); 1949 uninits.assign(uninitsTry);
1930 scan(param); 1950 scan(param);
1931 inits.incl(param.sym.adr); 1951 inits.incl(param.sym.adr);
1932 uninits.excl(param.sym.adr); 1952 uninits.excl(param.sym.adr);
1933 scan(l.head.body); 1953 scan(l.head.body);
1934 initsEnd.andSet(inits); 1954 initsEnd.andSet(inits);
1935 uninitsEnd.andSet(uninits); 1955 uninitsEnd.andSet(uninits);
1936 nextadr = nextadrCatch; 1956 nextadr = nextadrCatch;
1937 } 1957 }
1938 if (tree.finalizer != null) { 1958 if (tree.finalizer != null) {
1939 inits = initsTry.dup(); 1959 inits.assign(initsTry);
1940 uninits = uninitsTry.dup(); 1960 uninits.assign(uninitsTry);
1941 ListBuffer<AssignPendingExit> exits = pendingExits; 1961 ListBuffer<AssignPendingExit> exits = pendingExits;
1942 pendingExits = prevPendingExits; 1962 pendingExits = prevPendingExits;
1943 scan(tree.finalizer); 1963 scan(tree.finalizer);
1944 if (!tree.finallyCanCompleteNormally) { 1964 if (!tree.finallyCanCompleteNormally) {
1945 // discard exits and exceptions from try and finally 1965 // discard exits and exceptions from try and finally
1956 pendingExits.append(exit); 1976 pendingExits.append(exit);
1957 } 1977 }
1958 inits.orSet(initsEnd); 1978 inits.orSet(initsEnd);
1959 } 1979 }
1960 } else { 1980 } else {
1961 inits = initsEnd; 1981 inits.assign(initsEnd);
1962 uninits = uninitsEnd; 1982 uninits.assign(uninitsEnd);
1963 ListBuffer<AssignPendingExit> exits = pendingExits; 1983 ListBuffer<AssignPendingExit> exits = pendingExits;
1964 pendingExits = prevPendingExits; 1984 pendingExits = prevPendingExits;
1965 while (exits.nonEmpty()) pendingExits.append(exits.next()); 1985 while (exits.nonEmpty()) pendingExits.append(exits.next());
1966 } 1986 }
1967 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 1987 uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1968 } 1988 }
1969 1989
1970 public void visitConditional(JCConditional tree) { 1990 public void visitConditional(JCConditional tree) {
1971 scanCond(tree.cond); 1991 scanCond(tree.cond);
1972 Bits initsBeforeElse = initsWhenFalse; 1992 final Bits initsBeforeElse = new Bits(initsWhenFalse);
1973 Bits uninitsBeforeElse = uninitsWhenFalse; 1993 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
1974 inits = initsWhenTrue; 1994 inits.assign(initsWhenTrue);
1975 uninits = uninitsWhenTrue; 1995 uninits.assign(uninitsWhenTrue);
1976 if (tree.truepart.type.hasTag(BOOLEAN) && 1996 if (tree.truepart.type.hasTag(BOOLEAN) &&
1977 tree.falsepart.type.hasTag(BOOLEAN)) { 1997 tree.falsepart.type.hasTag(BOOLEAN)) {
1978 // if b and c are boolean valued, then 1998 // if b and c are boolean valued, then
1979 // v is (un)assigned after a?b:c when true iff 1999 // v is (un)assigned after a?b:c when true iff
1980 // v is (un)assigned after b when true and 2000 // v is (un)assigned after b when true and
1981 // v is (un)assigned after c when true 2001 // v is (un)assigned after c when true
1982 scanCond(tree.truepart); 2002 scanCond(tree.truepart);
1983 Bits initsAfterThenWhenTrue = initsWhenTrue.dup(); 2003 final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
1984 Bits initsAfterThenWhenFalse = initsWhenFalse.dup(); 2004 final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
1985 Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup(); 2005 final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
1986 Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup(); 2006 final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
1987 inits = initsBeforeElse; 2007 inits.assign(initsBeforeElse);
1988 uninits = uninitsBeforeElse; 2008 uninits.assign(uninitsBeforeElse);
1989 scanCond(tree.falsepart); 2009 scanCond(tree.falsepart);
1990 initsWhenTrue.andSet(initsAfterThenWhenTrue); 2010 initsWhenTrue.andSet(initsAfterThenWhenTrue);
1991 initsWhenFalse.andSet(initsAfterThenWhenFalse); 2011 initsWhenFalse.andSet(initsAfterThenWhenFalse);
1992 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue); 2012 uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
1993 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); 2013 uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
1994 } else { 2014 } else {
1995 scanExpr(tree.truepart); 2015 scanExpr(tree.truepart);
1996 Bits initsAfterThen = inits.dup(); 2016 final Bits initsAfterThen = new Bits(inits);
1997 Bits uninitsAfterThen = uninits.dup(); 2017 final Bits uninitsAfterThen = new Bits(uninits);
1998 inits = initsBeforeElse; 2018 inits.assign(initsBeforeElse);
1999 uninits = uninitsBeforeElse; 2019 uninits.assign(uninitsBeforeElse);
2000 scanExpr(tree.falsepart); 2020 scanExpr(tree.falsepart);
2001 inits.andSet(initsAfterThen); 2021 inits.andSet(initsAfterThen);
2002 uninits.andSet(uninitsAfterThen); 2022 uninits.andSet(uninitsAfterThen);
2003 } 2023 }
2004 } 2024 }
2005 2025
2006 public void visitIf(JCIf tree) { 2026 public void visitIf(JCIf tree) {
2007 scanCond(tree.cond); 2027 scanCond(tree.cond);
2008 Bits initsBeforeElse = initsWhenFalse; 2028 final Bits initsBeforeElse = new Bits(initsWhenFalse);
2009 Bits uninitsBeforeElse = uninitsWhenFalse; 2029 final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
2010 inits = initsWhenTrue; 2030 inits.assign(initsWhenTrue);
2011 uninits = uninitsWhenTrue; 2031 uninits.assign(uninitsWhenTrue);
2012 scan(tree.thenpart); 2032 scan(tree.thenpart);
2013 if (tree.elsepart != null) { 2033 if (tree.elsepart != null) {
2014 Bits initsAfterThen = inits.dup(); 2034 final Bits initsAfterThen = new Bits(inits);
2015 Bits uninitsAfterThen = uninits.dup(); 2035 final Bits uninitsAfterThen = new Bits(uninits);
2016 inits = initsBeforeElse; 2036 inits.assign(initsBeforeElse);
2017 uninits = uninitsBeforeElse; 2037 uninits.assign(uninitsBeforeElse);
2018 scan(tree.elsepart); 2038 scan(tree.elsepart);
2019 inits.andSet(initsAfterThen); 2039 inits.andSet(initsAfterThen);
2020 uninits.andSet(uninitsAfterThen); 2040 uninits.andSet(uninitsAfterThen);
2021 } else { 2041 } else {
2022 inits.andSet(initsBeforeElse); 2042 inits.andSet(initsBeforeElse);
2053 scan(tree.def); 2073 scan(tree.def);
2054 } 2074 }
2055 2075
2056 @Override 2076 @Override
2057 public void visitLambda(JCLambda tree) { 2077 public void visitLambda(JCLambda tree) {
2058 Bits prevUninits = uninits; 2078 final Bits prevUninits = new Bits(uninits);
2059 Bits prevInits = inits; 2079 final Bits prevInits = new Bits(inits);
2060 int returnadrPrev = returnadr; 2080 int returnadrPrev = returnadr;
2061 ListBuffer<AssignPendingExit> prevPending = pendingExits; 2081 ListBuffer<AssignPendingExit> prevPending = pendingExits;
2062 try { 2082 try {
2063 returnadr = nextadr; 2083 returnadr = nextadr;
2064 pendingExits = new ListBuffer<AssignPendingExit>(); 2084 pendingExits = new ListBuffer<AssignPendingExit>();
2074 scan(tree.body); 2094 scan(tree.body);
2075 } 2095 }
2076 } 2096 }
2077 finally { 2097 finally {
2078 returnadr = returnadrPrev; 2098 returnadr = returnadrPrev;
2079 uninits = prevUninits; 2099 uninits.assign(prevUninits);
2080 inits = prevInits; 2100 inits.assign(prevInits);
2081 pendingExits = prevPending; 2101 pendingExits = prevPending;
2082 } 2102 }
2083 } 2103 }
2084 2104
2085 public void visitNewArray(JCNewArray tree) { 2105 public void visitNewArray(JCNewArray tree) {
2086 scanExprs(tree.dims); 2106 scanExprs(tree.dims);
2087 scanExprs(tree.elems); 2107 scanExprs(tree.elems);
2088 } 2108 }
2089 2109
2090 public void visitAssert(JCAssert tree) { 2110 public void visitAssert(JCAssert tree) {
2091 Bits initsExit = inits.dup(); 2111 final Bits initsExit = new Bits(inits);
2092 Bits uninitsExit = uninits.dup(); 2112 final Bits uninitsExit = new Bits(uninits);
2093 scanCond(tree.cond); 2113 scanCond(tree.cond);
2094 uninitsExit.andSet(uninitsWhenTrue); 2114 uninitsExit.andSet(uninitsWhenTrue);
2095 if (tree.detail != null) { 2115 if (tree.detail != null) {
2096 inits = initsWhenFalse; 2116 inits.assign(initsWhenFalse);
2097 uninits = uninitsWhenFalse; 2117 uninits.assign(uninitsWhenFalse);
2098 scanExpr(tree.detail); 2118 scanExpr(tree.detail);
2099 } 2119 }
2100 inits = initsExit; 2120 inits.assign(initsExit);
2101 uninits = uninitsExit; 2121 uninits.assign(uninitsExit);
2102 } 2122 }
2103 2123
2104 public void visitAssign(JCAssign tree) { 2124 public void visitAssign(JCAssign tree) {
2105 JCTree lhs = TreeInfo.skipParens(tree.lhs); 2125 JCTree lhs = TreeInfo.skipParens(tree.lhs);
2106 if (!(lhs instanceof JCIdent)) { 2126 if (!(lhs instanceof JCIdent)) {
2118 2138
2119 public void visitUnary(JCUnary tree) { 2139 public void visitUnary(JCUnary tree) {
2120 switch (tree.getTag()) { 2140 switch (tree.getTag()) {
2121 case NOT: 2141 case NOT:
2122 scanCond(tree.arg); 2142 scanCond(tree.arg);
2123 Bits t = initsWhenFalse; 2143 final Bits t = new Bits(initsWhenFalse);
2124 initsWhenFalse = initsWhenTrue; 2144 initsWhenFalse.assign(initsWhenTrue);
2125 initsWhenTrue = t; 2145 initsWhenTrue.assign(t);
2126 t = uninitsWhenFalse; 2146 t.assign(uninitsWhenFalse);
2127 uninitsWhenFalse = uninitsWhenTrue; 2147 uninitsWhenFalse.assign(uninitsWhenTrue);
2128 uninitsWhenTrue = t; 2148 uninitsWhenTrue.assign(t);
2129 break; 2149 break;
2130 case PREINC: case POSTINC: 2150 case PREINC: case POSTINC:
2131 case PREDEC: case POSTDEC: 2151 case PREDEC: case POSTDEC:
2132 scanExpr(tree.arg); 2152 scanExpr(tree.arg);
2133 letInit(tree.arg); 2153 letInit(tree.arg);
2139 2159
2140 public void visitBinary(JCBinary tree) { 2160 public void visitBinary(JCBinary tree) {
2141 switch (tree.getTag()) { 2161 switch (tree.getTag()) {
2142 case AND: 2162 case AND:
2143 scanCond(tree.lhs); 2163 scanCond(tree.lhs);
2144 Bits initsWhenFalseLeft = initsWhenFalse; 2164 final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
2145 Bits uninitsWhenFalseLeft = uninitsWhenFalse; 2165 final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
2146 inits = initsWhenTrue; 2166 inits.assign(initsWhenTrue);
2147 uninits = uninitsWhenTrue; 2167 uninits.assign(uninitsWhenTrue);
2148 scanCond(tree.rhs); 2168 scanCond(tree.rhs);
2149 initsWhenFalse.andSet(initsWhenFalseLeft); 2169 initsWhenFalse.andSet(initsWhenFalseLeft);
2150 uninitsWhenFalse.andSet(uninitsWhenFalseLeft); 2170 uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
2151 break; 2171 break;
2152 case OR: 2172 case OR:
2153 scanCond(tree.lhs); 2173 scanCond(tree.lhs);
2154 Bits initsWhenTrueLeft = initsWhenTrue; 2174 final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
2155 Bits uninitsWhenTrueLeft = uninitsWhenTrue; 2175 final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
2156 inits = initsWhenFalse; 2176 inits.assign(initsWhenFalse);
2157 uninits = uninitsWhenFalse; 2177 uninits.assign(uninitsWhenFalse);
2158 scanCond(tree.rhs); 2178 scanCond(tree.rhs);
2159 initsWhenTrue.andSet(initsWhenTrueLeft); 2179 initsWhenTrue.andSet(initsWhenTrueLeft);
2160 uninitsWhenTrue.andSet(uninitsWhenTrueLeft); 2180 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
2161 break; 2181 break;
2162 default: 2182 default:
2198 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) { 2218 public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
2199 try { 2219 try {
2200 attrEnv = env; 2220 attrEnv = env;
2201 Flow.this.make = make; 2221 Flow.this.make = make;
2202 startPos = tree.pos().getStartPosition(); 2222 startPos = tree.pos().getStartPosition();
2203 inits = new Bits(); 2223
2204 uninits = new Bits();
2205 uninitsTry = new Bits();
2206 initsWhenTrue = initsWhenFalse =
2207 uninitsWhenTrue = uninitsWhenFalse = null;
2208 if (vars == null) 2224 if (vars == null)
2209 vars = new VarSymbol[32]; 2225 vars = new VarSymbol[32];
2210 else 2226 else
2211 for (int i=0; i<vars.length; i++) 2227 for (int i=0; i<vars.length; i++)
2212 vars[i] = null; 2228 vars[i] = null;
2217 unrefdResources = new Scope(env.enclClass.sym); 2233 unrefdResources = new Scope(env.enclClass.sym);
2218 scan(tree); 2234 scan(tree);
2219 } finally { 2235 } finally {
2220 // note that recursive invocations of this method fail hard 2236 // note that recursive invocations of this method fail hard
2221 startPos = -1; 2237 startPos = -1;
2222 inits = uninits = uninitsTry = null; 2238 resetBits(inits, uninits, uninitsTry, initsWhenTrue,
2223 initsWhenTrue = initsWhenFalse = 2239 initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
2224 uninitsWhenTrue = uninitsWhenFalse = null;
2225 if (vars != null) for (int i=0; i<vars.length; i++) 2240 if (vars != null) for (int i=0; i<vars.length; i++)
2226 vars[i] = null; 2241 vars[i] = null;
2227 firstadr = 0; 2242 firstadr = 0;
2228 nextadr = 0; 2243 nextadr = 0;
2229 pendingExits = null; 2244 pendingExits = null;

mercurial