8008562: javac, a refactoring to Bits is necessary in order to provide a change history

Fri, 26 Apr 2013 10:17:01 +0100

author
vromero
date
Fri, 26 Apr 2013 10:17:01 +0100
changeset 1713
2ca9e7d50136
parent 1712
3c02d2f1a421
child 1714
f3f3ac1273e8

8008562: javac, a refactoring to Bits is necessary in order to provide a change history
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/javac/comp/Flow.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/Code.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/Bits.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Apr 26 10:04:01 2013 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Apr 26 10:17:01 2013 +0100
     1.3 @@ -35,7 +35,6 @@
     1.4  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
     1.5  
     1.6  import com.sun.tools.javac.code.Symbol.*;
     1.7 -import com.sun.tools.javac.comp.Resolve;
     1.8  import com.sun.tools.javac.tree.JCTree.*;
     1.9  
    1.10  import static com.sun.tools.javac.code.Flags.*;
    1.11 @@ -277,6 +276,15 @@
    1.12      }
    1.13  
    1.14      /**
    1.15 +     * Utility method to reset several Bits instances.
    1.16 +     */
    1.17 +    private void resetBits(Bits... bits) {
    1.18 +        for (Bits b : bits) {
    1.19 +            b.reset();
    1.20 +        }
    1.21 +    }
    1.22 +
    1.23 +    /**
    1.24       * Base visitor class for all visitors implementing dataflow analysis logic.
    1.25       * This class define the shared logic for handling jumps (break/continue statements).
    1.26       */
    1.27 @@ -1294,11 +1302,11 @@
    1.28  
    1.29          /** The set of definitely assigned variables.
    1.30           */
    1.31 -        Bits inits;
    1.32 +        final Bits inits;
    1.33  
    1.34          /** The set of definitely unassigned variables.
    1.35           */
    1.36 -        Bits uninits;
    1.37 +        final Bits uninits;
    1.38  
    1.39          /** The set of variables that are definitely unassigned everywhere
    1.40           *  in current try block. This variable is maintained lazily; it is
    1.41 @@ -1308,15 +1316,15 @@
    1.42           *  anywhere in current try block, intersect uninitsTry and
    1.43           *  uninits.
    1.44           */
    1.45 -        Bits uninitsTry;
    1.46 +        final Bits uninitsTry;
    1.47  
    1.48          /** When analyzing a condition, inits and uninits are null.
    1.49           *  Instead we have:
    1.50           */
    1.51 -        Bits initsWhenTrue;
    1.52 -        Bits initsWhenFalse;
    1.53 -        Bits uninitsWhenTrue;
    1.54 -        Bits uninitsWhenFalse;
    1.55 +        final Bits initsWhenTrue;
    1.56 +        final Bits initsWhenFalse;
    1.57 +        final Bits uninitsWhenTrue;
    1.58 +        final Bits uninitsWhenFalse;
    1.59  
    1.60          /** A mapping from addresses to variable symbols.
    1.61           */
    1.62 @@ -1348,15 +1356,25 @@
    1.63          /** The starting position of the analysed tree */
    1.64          int startPos;
    1.65  
    1.66 +        AssignAnalyzer() {
    1.67 +            inits = new Bits();
    1.68 +            uninits = new Bits();
    1.69 +            uninitsTry = new Bits();
    1.70 +            initsWhenTrue = new Bits(true);
    1.71 +            initsWhenFalse = new Bits(true);
    1.72 +            uninitsWhenTrue = new Bits(true);
    1.73 +            uninitsWhenFalse = new Bits(true);
    1.74 +        }
    1.75 +
    1.76          class AssignPendingExit extends BaseAnalyzer.PendingExit {
    1.77  
    1.78 -            Bits exit_inits;
    1.79 -            Bits exit_uninits;
    1.80 +            final Bits exit_inits = new Bits(true);
    1.81 +            final Bits exit_uninits = new Bits(true);
    1.82  
    1.83 -            AssignPendingExit(JCTree tree, Bits inits, Bits uninits) {
    1.84 +            AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
    1.85                  super(tree);
    1.86 -                this.exit_inits = inits.dup();
    1.87 -                this.exit_uninits = uninits.dup();
    1.88 +                this.exit_inits.assign(inits);
    1.89 +                this.exit_uninits.assign(uninits);
    1.90              }
    1.91  
    1.92              void resolveJump() {
    1.93 @@ -1476,19 +1494,20 @@
    1.94          /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
    1.95           */
    1.96          void split(boolean setToNull) {
    1.97 -            initsWhenFalse = inits.dup();
    1.98 -            uninitsWhenFalse = uninits.dup();
    1.99 -            initsWhenTrue = inits;
   1.100 -            uninitsWhenTrue = uninits;
   1.101 -            if (setToNull)
   1.102 -                inits = uninits = null;
   1.103 +            initsWhenFalse.assign(inits);
   1.104 +            uninitsWhenFalse.assign(uninits);
   1.105 +            initsWhenTrue.assign(inits);
   1.106 +            uninitsWhenTrue.assign(uninits);
   1.107 +            if (setToNull) {
   1.108 +                resetBits(inits, uninits);
   1.109 +            }
   1.110          }
   1.111  
   1.112          /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
   1.113           */
   1.114          void merge() {
   1.115 -            inits = initsWhenFalse.andSet(initsWhenTrue);
   1.116 -            uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
   1.117 +            inits.assign(initsWhenFalse.andSet(initsWhenTrue));
   1.118 +            uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
   1.119          }
   1.120  
   1.121      /* ************************************************************************
   1.122 @@ -1501,7 +1520,7 @@
   1.123          void scanExpr(JCTree tree) {
   1.124              if (tree != null) {
   1.125                  scan(tree);
   1.126 -                if (inits == null) merge();
   1.127 +                if (inits.isReset()) merge();
   1.128              }
   1.129          }
   1.130  
   1.131 @@ -1518,28 +1537,29 @@
   1.132           */
   1.133          void scanCond(JCTree tree) {
   1.134              if (tree.type.isFalse()) {
   1.135 -                if (inits == null) merge();
   1.136 -                initsWhenTrue = inits.dup();
   1.137 +                if (inits.isReset()) merge();
   1.138 +                initsWhenTrue.assign(inits);
   1.139                  initsWhenTrue.inclRange(firstadr, nextadr);
   1.140 -                uninitsWhenTrue = uninits.dup();
   1.141 +                uninitsWhenTrue.assign(uninits);
   1.142                  uninitsWhenTrue.inclRange(firstadr, nextadr);
   1.143 -                initsWhenFalse = inits;
   1.144 -                uninitsWhenFalse = uninits;
   1.145 +                initsWhenFalse.assign(inits);
   1.146 +                uninitsWhenFalse.assign(uninits);
   1.147              } else if (tree.type.isTrue()) {
   1.148 -                if (inits == null) merge();
   1.149 -                initsWhenFalse = inits.dup();
   1.150 +                if (inits.isReset()) merge();
   1.151 +                initsWhenFalse.assign(inits);
   1.152                  initsWhenFalse.inclRange(firstadr, nextadr);
   1.153 -                uninitsWhenFalse = uninits.dup();
   1.154 +                uninitsWhenFalse.assign(uninits);
   1.155                  uninitsWhenFalse.inclRange(firstadr, nextadr);
   1.156 -                initsWhenTrue = inits;
   1.157 -                uninitsWhenTrue = uninits;
   1.158 +                initsWhenTrue.assign(inits);
   1.159 +                uninitsWhenTrue.assign(uninits);
   1.160              } else {
   1.161                  scan(tree);
   1.162 -                if (inits != null)
   1.163 +                if (!inits.isReset())
   1.164                      split(tree.type != syms.unknownType);
   1.165              }
   1.166 -            if (tree.type != syms.unknownType)
   1.167 -                inits = uninits = null;
   1.168 +            if (tree.type != syms.unknownType) {
   1.169 +                resetBits(inits, uninits);
   1.170 +            }
   1.171          }
   1.172  
   1.173          /* ------------ Visitor methods for various sorts of trees -------------*/
   1.174 @@ -1619,8 +1639,8 @@
   1.175          public void visitMethodDef(JCMethodDecl tree) {
   1.176              if (tree.body == null) return;
   1.177  
   1.178 -            Bits initsPrev = inits.dup();
   1.179 -            Bits uninitsPrev = uninits.dup();
   1.180 +            final Bits initsPrev = new Bits(inits);
   1.181 +            final Bits uninitsPrev = new Bits(uninits);
   1.182              int nextadrPrev = nextadr;
   1.183              int firstadrPrev = firstadr;
   1.184              int returnadrPrev = returnadr;
   1.185 @@ -1658,14 +1678,14 @@
   1.186                      exits = exits.tail;
   1.187                      Assert.check(exit.tree.hasTag(RETURN), exit.tree);
   1.188                      if (isInitialConstructor) {
   1.189 -                        inits = exit.exit_inits;
   1.190 +                        inits.assign(exit.exit_inits);
   1.191                          for (int i = firstadr; i < nextadr; i++)
   1.192                              checkInit(exit.tree.pos(), vars[i]);
   1.193                      }
   1.194                  }
   1.195              } finally {
   1.196 -                inits = initsPrev;
   1.197 -                uninits = uninitsPrev;
   1.198 +                inits.assign(initsPrev);
   1.199 +                uninits.assign(uninitsPrev);
   1.200                  nextadr = nextadrPrev;
   1.201                  firstadr = firstadrPrev;
   1.202                  returnadr = returnadrPrev;
   1.203 @@ -1698,31 +1718,31 @@
   1.204              ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.205              FlowKind prevFlowKind = flowKind;
   1.206              flowKind = FlowKind.NORMAL;
   1.207 -            Bits initsSkip = null;
   1.208 -            Bits uninitsSkip = null;
   1.209 +            final Bits initsSkip = new Bits(true);
   1.210 +            final Bits uninitsSkip = new Bits(true);
   1.211              pendingExits = new ListBuffer<AssignPendingExit>();
   1.212              int prevErrors = log.nerrors;
   1.213              do {
   1.214 -                Bits uninitsEntry = uninits.dup();
   1.215 +                final Bits uninitsEntry = new Bits(uninits);
   1.216                  uninitsEntry.excludeFrom(nextadr);
   1.217                  scan(tree.body);
   1.218                  resolveContinues(tree);
   1.219                  scanCond(tree.cond);
   1.220                  if (!flowKind.isFinal()) {
   1.221 -                    initsSkip = initsWhenFalse;
   1.222 -                    uninitsSkip = uninitsWhenFalse;
   1.223 +                    initsSkip.assign(initsWhenFalse);
   1.224 +                    uninitsSkip.assign(uninitsWhenFalse);
   1.225                  }
   1.226                  if (log.nerrors !=  prevErrors ||
   1.227                      flowKind.isFinal() ||
   1.228 -                    uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
   1.229 +                    new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
   1.230                      break;
   1.231 -                inits = initsWhenTrue;
   1.232 -                uninits = uninitsEntry.andSet(uninitsWhenTrue);
   1.233 +                inits.assign(initsWhenTrue);
   1.234 +                uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
   1.235                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.236              } while (true);
   1.237              flowKind = prevFlowKind;
   1.238 -            inits = initsSkip;
   1.239 -            uninits = uninitsSkip;
   1.240 +            inits.assign(initsSkip);
   1.241 +            uninits.assign(uninitsSkip);
   1.242              resolveBreaks(tree, prevPendingExits);
   1.243          }
   1.244  
   1.245 @@ -1730,34 +1750,34 @@
   1.246              ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.247              FlowKind prevFlowKind = flowKind;
   1.248              flowKind = FlowKind.NORMAL;
   1.249 -            Bits initsSkip = null;
   1.250 -            Bits uninitsSkip = null;
   1.251 +            final Bits initsSkip = new Bits(true);
   1.252 +            final Bits uninitsSkip = new Bits(true);
   1.253              pendingExits = new ListBuffer<AssignPendingExit>();
   1.254              int prevErrors = log.nerrors;
   1.255 -            Bits uninitsEntry = uninits.dup();
   1.256 +            final Bits uninitsEntry = new Bits(uninits);
   1.257              uninitsEntry.excludeFrom(nextadr);
   1.258              do {
   1.259                  scanCond(tree.cond);
   1.260                  if (!flowKind.isFinal()) {
   1.261 -                    initsSkip = initsWhenFalse;
   1.262 -                    uninitsSkip = uninitsWhenFalse;
   1.263 +                    initsSkip.assign(initsWhenFalse) ;
   1.264 +                    uninitsSkip.assign(uninitsWhenFalse);
   1.265                  }
   1.266 -                inits = initsWhenTrue;
   1.267 -                uninits = uninitsWhenTrue;
   1.268 +                inits.assign(initsWhenTrue);
   1.269 +                uninits.assign(uninitsWhenTrue);
   1.270                  scan(tree.body);
   1.271                  resolveContinues(tree);
   1.272                  if (log.nerrors != prevErrors ||
   1.273                      flowKind.isFinal() ||
   1.274 -                    uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
   1.275 +                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.276                      break;
   1.277 -                uninits = uninitsEntry.andSet(uninits);
   1.278 +                uninits.assign(uninitsEntry.andSet(uninits));
   1.279                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.280              } while (true);
   1.281              flowKind = prevFlowKind;
   1.282              //a variable is DA/DU after the while statement, if it's DA/DU assuming the
   1.283              //branch is not taken AND if it's DA/DU before any break statement
   1.284 -            inits = initsSkip;
   1.285 -            uninits = uninitsSkip;
   1.286 +            inits.assign(initsSkip);
   1.287 +            uninits.assign(uninitsSkip);
   1.288              resolveBreaks(tree, prevPendingExits);
   1.289          }
   1.290  
   1.291 @@ -1767,25 +1787,25 @@
   1.292              flowKind = FlowKind.NORMAL;
   1.293              int nextadrPrev = nextadr;
   1.294              scan(tree.init);
   1.295 -            Bits initsSkip = null;
   1.296 -            Bits uninitsSkip = null;
   1.297 +            final Bits initsSkip = new Bits(true);
   1.298 +            final Bits uninitsSkip = new Bits(true);
   1.299              pendingExits = new ListBuffer<AssignPendingExit>();
   1.300              int prevErrors = log.nerrors;
   1.301              do {
   1.302 -                Bits uninitsEntry = uninits.dup();
   1.303 +                final Bits uninitsEntry = new Bits(uninits);
   1.304                  uninitsEntry.excludeFrom(nextadr);
   1.305                  if (tree.cond != null) {
   1.306                      scanCond(tree.cond);
   1.307                      if (!flowKind.isFinal()) {
   1.308 -                        initsSkip = initsWhenFalse;
   1.309 -                        uninitsSkip = uninitsWhenFalse;
   1.310 +                        initsSkip.assign(initsWhenFalse);
   1.311 +                        uninitsSkip.assign(uninitsWhenFalse);
   1.312                      }
   1.313 -                    inits = initsWhenTrue;
   1.314 -                    uninits = uninitsWhenTrue;
   1.315 +                    inits.assign(initsWhenTrue);
   1.316 +                    uninits.assign(uninitsWhenTrue);
   1.317                  } else if (!flowKind.isFinal()) {
   1.318 -                    initsSkip = inits.dup();
   1.319 +                    initsSkip.assign(inits);
   1.320                      initsSkip.inclRange(firstadr, nextadr);
   1.321 -                    uninitsSkip = uninits.dup();
   1.322 +                    uninitsSkip.assign(uninits);
   1.323                      uninitsSkip.inclRange(firstadr, nextadr);
   1.324                  }
   1.325                  scan(tree.body);
   1.326 @@ -1793,16 +1813,16 @@
   1.327                  scan(tree.step);
   1.328                  if (log.nerrors != prevErrors ||
   1.329                      flowKind.isFinal() ||
   1.330 -                    uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
   1.331 +                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.332                      break;
   1.333 -                uninits = uninitsEntry.andSet(uninits);
   1.334 +                uninits.assign(uninitsEntry.andSet(uninits));
   1.335                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.336              } while (true);
   1.337              flowKind = prevFlowKind;
   1.338              //a variable is DA/DU after a for loop, if it's DA/DU assuming the
   1.339              //branch is not taken AND if it's DA/DU before any break statement
   1.340 -            inits = initsSkip;
   1.341 -            uninits = uninitsSkip;
   1.342 +            inits.assign(initsSkip);
   1.343 +            uninits.assign(uninitsSkip);
   1.344              resolveBreaks(tree, prevPendingExits);
   1.345              nextadr = nextadrPrev;
   1.346          }
   1.347 @@ -1815,27 +1835,27 @@
   1.348              flowKind = FlowKind.NORMAL;
   1.349              int nextadrPrev = nextadr;
   1.350              scan(tree.expr);
   1.351 -            Bits initsStart = inits.dup();
   1.352 -            Bits uninitsStart = uninits.dup();
   1.353 +            final Bits initsStart = new Bits(inits);
   1.354 +            final Bits uninitsStart = new Bits(uninits);
   1.355  
   1.356              letInit(tree.pos(), tree.var.sym);
   1.357              pendingExits = new ListBuffer<AssignPendingExit>();
   1.358              int prevErrors = log.nerrors;
   1.359              do {
   1.360 -                Bits uninitsEntry = uninits.dup();
   1.361 +                final Bits uninitsEntry = new Bits(uninits);
   1.362                  uninitsEntry.excludeFrom(nextadr);
   1.363                  scan(tree.body);
   1.364                  resolveContinues(tree);
   1.365                  if (log.nerrors != prevErrors ||
   1.366                      flowKind.isFinal() ||
   1.367 -                    uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1)
   1.368 +                    new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
   1.369                      break;
   1.370 -                uninits = uninitsEntry.andSet(uninits);
   1.371 +                uninits.assign(uninitsEntry.andSet(uninits));
   1.372                  flowKind = FlowKind.SPECULATIVE_LOOP;
   1.373              } while (true);
   1.374              flowKind = prevFlowKind;
   1.375 -            inits = initsStart;
   1.376 -            uninits = uninitsStart.andSet(uninits);
   1.377 +            inits.assign(initsStart);
   1.378 +            uninits.assign(uninitsStart.andSet(uninits));
   1.379              resolveBreaks(tree, prevPendingExits);
   1.380              nextadr = nextadrPrev;
   1.381          }
   1.382 @@ -1852,12 +1872,12 @@
   1.383              pendingExits = new ListBuffer<AssignPendingExit>();
   1.384              int nextadrPrev = nextadr;
   1.385              scanExpr(tree.selector);
   1.386 -            Bits initsSwitch = inits;
   1.387 -            Bits uninitsSwitch = uninits.dup();
   1.388 +            final Bits initsSwitch = new Bits(inits);
   1.389 +            final Bits uninitsSwitch = new Bits(uninits);
   1.390              boolean hasDefault = false;
   1.391              for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
   1.392 -                inits = initsSwitch.dup();
   1.393 -                uninits = uninits.andSet(uninitsSwitch);
   1.394 +                inits.assign(initsSwitch);
   1.395 +                uninits.assign(uninits.andSet(uninitsSwitch));
   1.396                  JCCase c = l.head;
   1.397                  if (c.pat == null)
   1.398                      hasDefault = true;
   1.399 @@ -1875,8 +1895,8 @@
   1.400          }
   1.401          // where
   1.402              /** Add any variables defined in stats to inits and uninits. */
   1.403 -            private void addVars(List<JCStatement> stats, Bits inits,
   1.404 -                                        Bits uninits) {
   1.405 +            private void addVars(List<JCStatement> stats, final Bits inits,
   1.406 +                                        final Bits uninits) {
   1.407                  for (;stats.nonEmpty(); stats = stats.tail) {
   1.408                      JCTree stat = stats.head;
   1.409                      if (stat.hasTag(VARDEF)) {
   1.410 @@ -1889,11 +1909,11 @@
   1.411  
   1.412          public void visitTry(JCTry tree) {
   1.413              ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
   1.414 -            Bits uninitsTryPrev = uninitsTry;
   1.415 +            final Bits uninitsTryPrev = new Bits(uninitsTry);
   1.416              ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
   1.417              pendingExits = new ListBuffer<AssignPendingExit>();
   1.418 -            Bits initsTry = inits.dup();
   1.419 -            uninitsTry = uninits.dup();
   1.420 +            final Bits initsTry = new Bits(inits);
   1.421 +            uninitsTry.assign(uninits);
   1.422              for (JCTree resource : tree.resources) {
   1.423                  if (resource instanceof JCVariableDecl) {
   1.424                      JCVariableDecl vdecl = (JCVariableDecl) resource;
   1.425 @@ -1908,8 +1928,8 @@
   1.426              }
   1.427              scan(tree.body);
   1.428              uninitsTry.andSet(uninits);
   1.429 -            Bits initsEnd = inits;
   1.430 -            Bits uninitsEnd = uninits;
   1.431 +            final Bits initsEnd = new Bits(inits);
   1.432 +            final Bits uninitsEnd = new Bits(uninits);
   1.433              int nextadrCatch = nextadr;
   1.434  
   1.435              if (!resourceVarDecls.isEmpty() &&
   1.436 @@ -1925,8 +1945,8 @@
   1.437  
   1.438              for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
   1.439                  JCVariableDecl param = l.head.param;
   1.440 -                inits = initsTry.dup();
   1.441 -                uninits = uninitsTry.dup();
   1.442 +                inits.assign(initsTry);
   1.443 +                uninits.assign(uninitsTry);
   1.444                  scan(param);
   1.445                  inits.incl(param.sym.adr);
   1.446                  uninits.excl(param.sym.adr);
   1.447 @@ -1936,8 +1956,8 @@
   1.448                  nextadr = nextadrCatch;
   1.449              }
   1.450              if (tree.finalizer != null) {
   1.451 -                inits = initsTry.dup();
   1.452 -                uninits = uninitsTry.dup();
   1.453 +                inits.assign(initsTry);
   1.454 +                uninits.assign(uninitsTry);
   1.455                  ListBuffer<AssignPendingExit> exits = pendingExits;
   1.456                  pendingExits = prevPendingExits;
   1.457                  scan(tree.finalizer);
   1.458 @@ -1958,8 +1978,8 @@
   1.459                      inits.orSet(initsEnd);
   1.460                  }
   1.461              } else {
   1.462 -                inits = initsEnd;
   1.463 -                uninits = uninitsEnd;
   1.464 +                inits.assign(initsEnd);
   1.465 +                uninits.assign(uninitsEnd);
   1.466                  ListBuffer<AssignPendingExit> exits = pendingExits;
   1.467                  pendingExits = prevPendingExits;
   1.468                  while (exits.nonEmpty()) pendingExits.append(exits.next());
   1.469 @@ -1969,10 +1989,10 @@
   1.470  
   1.471          public void visitConditional(JCConditional tree) {
   1.472              scanCond(tree.cond);
   1.473 -            Bits initsBeforeElse = initsWhenFalse;
   1.474 -            Bits uninitsBeforeElse = uninitsWhenFalse;
   1.475 -            inits = initsWhenTrue;
   1.476 -            uninits = uninitsWhenTrue;
   1.477 +            final Bits initsBeforeElse = new Bits(initsWhenFalse);
   1.478 +            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
   1.479 +            inits.assign(initsWhenTrue);
   1.480 +            uninits.assign(uninitsWhenTrue);
   1.481              if (tree.truepart.type.hasTag(BOOLEAN) &&
   1.482                  tree.falsepart.type.hasTag(BOOLEAN)) {
   1.483                  // if b and c are boolean valued, then
   1.484 @@ -1980,12 +2000,12 @@
   1.485                  //    v is (un)assigned after b when true and
   1.486                  //    v is (un)assigned after c when true
   1.487                  scanCond(tree.truepart);
   1.488 -                Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
   1.489 -                Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
   1.490 -                Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
   1.491 -                Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
   1.492 -                inits = initsBeforeElse;
   1.493 -                uninits = uninitsBeforeElse;
   1.494 +                final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue);
   1.495 +                final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
   1.496 +                final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
   1.497 +                final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
   1.498 +                inits.assign(initsBeforeElse);
   1.499 +                uninits.assign(uninitsBeforeElse);
   1.500                  scanCond(tree.falsepart);
   1.501                  initsWhenTrue.andSet(initsAfterThenWhenTrue);
   1.502                  initsWhenFalse.andSet(initsAfterThenWhenFalse);
   1.503 @@ -1993,10 +2013,10 @@
   1.504                  uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
   1.505              } else {
   1.506                  scanExpr(tree.truepart);
   1.507 -                Bits initsAfterThen = inits.dup();
   1.508 -                Bits uninitsAfterThen = uninits.dup();
   1.509 -                inits = initsBeforeElse;
   1.510 -                uninits = uninitsBeforeElse;
   1.511 +                final Bits initsAfterThen = new Bits(inits);
   1.512 +                final Bits uninitsAfterThen = new Bits(uninits);
   1.513 +                inits.assign(initsBeforeElse);
   1.514 +                uninits.assign(uninitsBeforeElse);
   1.515                  scanExpr(tree.falsepart);
   1.516                  inits.andSet(initsAfterThen);
   1.517                  uninits.andSet(uninitsAfterThen);
   1.518 @@ -2005,16 +2025,16 @@
   1.519  
   1.520          public void visitIf(JCIf tree) {
   1.521              scanCond(tree.cond);
   1.522 -            Bits initsBeforeElse = initsWhenFalse;
   1.523 -            Bits uninitsBeforeElse = uninitsWhenFalse;
   1.524 -            inits = initsWhenTrue;
   1.525 -            uninits = uninitsWhenTrue;
   1.526 +            final Bits initsBeforeElse = new Bits(initsWhenFalse);
   1.527 +            final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
   1.528 +            inits.assign(initsWhenTrue);
   1.529 +            uninits.assign(uninitsWhenTrue);
   1.530              scan(tree.thenpart);
   1.531              if (tree.elsepart != null) {
   1.532 -                Bits initsAfterThen = inits.dup();
   1.533 -                Bits uninitsAfterThen = uninits.dup();
   1.534 -                inits = initsBeforeElse;
   1.535 -                uninits = uninitsBeforeElse;
   1.536 +                final Bits initsAfterThen = new Bits(inits);
   1.537 +                final Bits uninitsAfterThen = new Bits(uninits);
   1.538 +                inits.assign(initsBeforeElse);
   1.539 +                uninits.assign(uninitsBeforeElse);
   1.540                  scan(tree.elsepart);
   1.541                  inits.andSet(initsAfterThen);
   1.542                  uninits.andSet(uninitsAfterThen);
   1.543 @@ -2055,8 +2075,8 @@
   1.544  
   1.545          @Override
   1.546          public void visitLambda(JCLambda tree) {
   1.547 -            Bits prevUninits = uninits;
   1.548 -            Bits prevInits = inits;
   1.549 +            final Bits prevUninits = new Bits(uninits);
   1.550 +            final Bits prevInits = new Bits(inits);
   1.551              int returnadrPrev = returnadr;
   1.552              ListBuffer<AssignPendingExit> prevPending = pendingExits;
   1.553              try {
   1.554 @@ -2076,8 +2096,8 @@
   1.555              }
   1.556              finally {
   1.557                  returnadr = returnadrPrev;
   1.558 -                uninits = prevUninits;
   1.559 -                inits = prevInits;
   1.560 +                uninits.assign(prevUninits);
   1.561 +                inits.assign(prevInits);
   1.562                  pendingExits = prevPending;
   1.563              }
   1.564          }
   1.565 @@ -2088,17 +2108,17 @@
   1.566          }
   1.567  
   1.568          public void visitAssert(JCAssert tree) {
   1.569 -            Bits initsExit = inits.dup();
   1.570 -            Bits uninitsExit = uninits.dup();
   1.571 +            final Bits initsExit = new Bits(inits);
   1.572 +            final Bits uninitsExit = new Bits(uninits);
   1.573              scanCond(tree.cond);
   1.574              uninitsExit.andSet(uninitsWhenTrue);
   1.575              if (tree.detail != null) {
   1.576 -                inits = initsWhenFalse;
   1.577 -                uninits = uninitsWhenFalse;
   1.578 +                inits.assign(initsWhenFalse);
   1.579 +                uninits.assign(uninitsWhenFalse);
   1.580                  scanExpr(tree.detail);
   1.581              }
   1.582 -            inits = initsExit;
   1.583 -            uninits = uninitsExit;
   1.584 +            inits.assign(initsExit);
   1.585 +            uninits.assign(uninitsExit);
   1.586          }
   1.587  
   1.588          public void visitAssign(JCAssign tree) {
   1.589 @@ -2120,12 +2140,12 @@
   1.590              switch (tree.getTag()) {
   1.591              case NOT:
   1.592                  scanCond(tree.arg);
   1.593 -                Bits t = initsWhenFalse;
   1.594 -                initsWhenFalse = initsWhenTrue;
   1.595 -                initsWhenTrue = t;
   1.596 -                t = uninitsWhenFalse;
   1.597 -                uninitsWhenFalse = uninitsWhenTrue;
   1.598 -                uninitsWhenTrue = t;
   1.599 +                final Bits t = new Bits(initsWhenFalse);
   1.600 +                initsWhenFalse.assign(initsWhenTrue);
   1.601 +                initsWhenTrue.assign(t);
   1.602 +                t.assign(uninitsWhenFalse);
   1.603 +                uninitsWhenFalse.assign(uninitsWhenTrue);
   1.604 +                uninitsWhenTrue.assign(t);
   1.605                  break;
   1.606              case PREINC: case POSTINC:
   1.607              case PREDEC: case POSTDEC:
   1.608 @@ -2141,20 +2161,20 @@
   1.609              switch (tree.getTag()) {
   1.610              case AND:
   1.611                  scanCond(tree.lhs);
   1.612 -                Bits initsWhenFalseLeft = initsWhenFalse;
   1.613 -                Bits uninitsWhenFalseLeft = uninitsWhenFalse;
   1.614 -                inits = initsWhenTrue;
   1.615 -                uninits = uninitsWhenTrue;
   1.616 +                final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
   1.617 +                final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
   1.618 +                inits.assign(initsWhenTrue);
   1.619 +                uninits.assign(uninitsWhenTrue);
   1.620                  scanCond(tree.rhs);
   1.621                  initsWhenFalse.andSet(initsWhenFalseLeft);
   1.622                  uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
   1.623                  break;
   1.624              case OR:
   1.625                  scanCond(tree.lhs);
   1.626 -                Bits initsWhenTrueLeft = initsWhenTrue;
   1.627 -                Bits uninitsWhenTrueLeft = uninitsWhenTrue;
   1.628 -                inits = initsWhenFalse;
   1.629 -                uninits = uninitsWhenFalse;
   1.630 +                final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
   1.631 +                final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
   1.632 +                inits.assign(initsWhenFalse);
   1.633 +                uninits.assign(uninitsWhenFalse);
   1.634                  scanCond(tree.rhs);
   1.635                  initsWhenTrue.andSet(initsWhenTrueLeft);
   1.636                  uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
   1.637 @@ -2200,11 +2220,7 @@
   1.638                  attrEnv = env;
   1.639                  Flow.this.make = make;
   1.640                  startPos = tree.pos().getStartPosition();
   1.641 -                inits = new Bits();
   1.642 -                uninits = new Bits();
   1.643 -                uninitsTry = new Bits();
   1.644 -                initsWhenTrue = initsWhenFalse =
   1.645 -                    uninitsWhenTrue = uninitsWhenFalse = null;
   1.646 +
   1.647                  if (vars == null)
   1.648                      vars = new VarSymbol[32];
   1.649                  else
   1.650 @@ -2219,9 +2235,8 @@
   1.651              } finally {
   1.652                  // note that recursive invocations of this method fail hard
   1.653                  startPos = -1;
   1.654 -                inits = uninits = uninitsTry = null;
   1.655 -                initsWhenTrue = initsWhenFalse =
   1.656 -                    uninitsWhenTrue = uninitsWhenFalse = null;
   1.657 +                resetBits(inits, uninits, uninitsTry, initsWhenTrue,
   1.658 +                        initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
   1.659                  if (vars != null) for (int i=0; i<vars.length; i++)
   1.660                      vars[i] = null;
   1.661                  firstadr = 0;
     2.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Apr 26 10:04:01 2013 +0100
     2.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java	Fri Apr 26 10:17:01 2013 +0100
     2.3 @@ -1647,7 +1647,7 @@
     2.4          State dup() {
     2.5              try {
     2.6                  State state = (State)super.clone();
     2.7 -                state.defined = defined.dup();
     2.8 +                state.defined = new Bits(defined);
     2.9                  state.stack = stack.clone();
    2.10                  if (locks != null) state.locks = locks.clone();
    2.11                  if (debugCode) {
    2.12 @@ -1775,7 +1775,7 @@
    2.13          }
    2.14  
    2.15          State join(State other) {
    2.16 -            defined = defined.andSet(other.defined);
    2.17 +            defined.andSet(other.defined);
    2.18              Assert.check(stacksize == other.stacksize
    2.19                      && nlocks == other.nlocks);
    2.20              for (int i=0; i<stacksize; ) {
    2.21 @@ -1887,7 +1887,7 @@
    2.22      /** Set the current variable defined state. */
    2.23      public void setDefined(Bits newDefined) {
    2.24          if (alive && newDefined != state.defined) {
    2.25 -            Bits diff = state.defined.dup().xorSet(newDefined);
    2.26 +            Bits diff = new Bits(state.defined).xorSet(newDefined);
    2.27              for (int adr = diff.nextBit(0);
    2.28                   adr >= 0;
    2.29                   adr = diff.nextBit(adr+1)) {
     3.1 --- a/src/share/classes/com/sun/tools/javac/util/Bits.java	Fri Apr 26 10:04:01 2013 +0100
     3.2 +++ b/src/share/classes/com/sun/tools/javac/util/Bits.java	Fri Apr 26 10:17:01 2013 +0100
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -27,6 +27,8 @@
    3.11  
    3.12  import java.util.Arrays;
    3.13  
    3.14 +import static com.sun.tools.javac.util.Bits.BitsOpKind.*;
    3.15 +
    3.16  /** A class for extensible, mutable bit sets.
    3.17   *
    3.18   *  <p><b>This is NOT part of any supported API.
    3.19 @@ -36,31 +38,114 @@
    3.20   */
    3.21  public class Bits {
    3.22  
    3.23 +    public enum BitsOpKind {
    3.24 +        INIT,
    3.25 +        CLEAR,
    3.26 +        INCL_BIT,
    3.27 +        EXCL_BIT,
    3.28 +        ASSIGN,
    3.29 +        AND_SET,
    3.30 +        OR_SET,
    3.31 +        DIFF_SET,
    3.32 +        XOR_SET,
    3.33 +        INCL_RANGE,
    3.34 +        EXCL_RANGE,
    3.35 +    }
    3.36 +
    3.37 +    //       ____________      reset    _________
    3.38 +    //      /  UNKNOWN   \   <-------- / UNINIT  \
    3.39 +    //      \____________/       |     \_________/
    3.40 +    //            |              |          |
    3.41 +    //            |assign        |          | any
    3.42 +    //            |        ___________      |
    3.43 +    //            ------> /  NORMAL   \ <----
    3.44 +    //                    \___________/     |
    3.45 +    //                            |         |
    3.46 +    //                            |         |
    3.47 +    //                            -----------
    3.48 +    //                               any
    3.49 +    private enum BitsState {
    3.50 +        /*  A Bits instance is in UNKNOWN state if it has been explicitly reset.
    3.51 +         *  It is possible to get to this state from any other by calling the
    3.52 +         *  reset method. An instance in the UNKNOWN state can pass to the
    3.53 +         *  NORMAL state after being assigned another Bits instance.
    3.54 +         */
    3.55 +        UNKNOWN,
    3.56 +        /*  A Bits instance is in UNINIT when it is created with the default
    3.57 +         *  constructor but it isn't explicitly reset. The main objective of this
    3.58 +         *  internal state is to save some memory.
    3.59 +         */
    3.60 +        UNINIT,
    3.61 +        /*  The normal state is reached after creating a Bits instance from an
    3.62 +         *  existing one or after applying any operation to an instance on UNINIT
    3.63 +         *  or NORMAL state. From this state a bits instance can pass to the
    3.64 +         *  UNKNOWN state by calling the reset method.
    3.65 +         */
    3.66 +        NORMAL;
    3.67 +
    3.68 +        static BitsState getState(int[] someBits, boolean reset) {
    3.69 +            if (reset) {
    3.70 +                return UNKNOWN;
    3.71 +            } else {
    3.72 +                if (someBits != unassignedBits) {
    3.73 +                    return NORMAL;
    3.74 +                } else {
    3.75 +                    return UNINIT;
    3.76 +                }
    3.77 +            }
    3.78 +        }
    3.79 +
    3.80 +    }
    3.81  
    3.82      private final static int wordlen = 32;
    3.83      private final static int wordshift = 5;
    3.84      private final static int wordmask = wordlen - 1;
    3.85  
    3.86 -    private int[] bits;
    3.87 +    public int[] bits = null;
    3.88 +    // This field will store last version of bits after every change.
    3.89 +    public int[] oldBits = null;
    3.90 +
    3.91 +    public BitsOpKind lastOperation = null;
    3.92 +
    3.93 +    private static final int[] unassignedBits = new int[0];
    3.94 +
    3.95 +    private BitsState currentState;
    3.96  
    3.97      /** Construct an initially empty set.
    3.98       */
    3.99      public Bits() {
   3.100 -        this(new int[1]);
   3.101 +        this(false);
   3.102 +    }
   3.103 +
   3.104 +    public Bits(Bits someBits) {
   3.105 +        this(someBits.dup().bits, BitsState.getState(someBits.bits, false));
   3.106 +    }
   3.107 +
   3.108 +    public Bits(boolean reset) {
   3.109 +        this(unassignedBits, BitsState.getState(unassignedBits, reset));
   3.110      }
   3.111  
   3.112      /** Construct a set consisting initially of given bit vector.
   3.113       */
   3.114 -    public Bits(int[] bits) {
   3.115 +    private Bits(int[] bits, BitsState initState) {
   3.116          this.bits = bits;
   3.117 +        this.currentState = initState;
   3.118 +        switch (initState) {
   3.119 +            case UNKNOWN:
   3.120 +                reset(); //this will also set current state;
   3.121 +                break;
   3.122 +            case NORMAL:
   3.123 +                Assert.check(bits != unassignedBits);
   3.124 +                lastOperation = INIT;
   3.125 +                break;
   3.126 +        }
   3.127      }
   3.128  
   3.129 -    /** Construct a set consisting initially of given range.
   3.130 +    /** This method will be called after any operation that causes a change to
   3.131 +     *  the bits. Subclasses can thus override it in order to extract information
   3.132 +     *  from the changes produced to the bits by the given operation.
   3.133       */
   3.134 -    public Bits(int start, int limit) {
   3.135 -        this();
   3.136 -        inclRange(start, limit);
   3.137 -    }
   3.138 +    public void changed() {}
   3.139  
   3.140      private void sizeTo(int len) {
   3.141          if (bits.length < len) {
   3.142 @@ -71,57 +156,110 @@
   3.143      /** This set = {}.
   3.144       */
   3.145      public void clear() {
   3.146 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.147 +        oldBits = bits;
   3.148 +        lastOperation = CLEAR;
   3.149          for (int i = 0; i < bits.length; i++) bits[i] = 0;
   3.150 +        changed();
   3.151 +        currentState = BitsState.NORMAL;
   3.152 +    }
   3.153 +
   3.154 +    public void reset() {
   3.155 +        bits = null;
   3.156 +        oldBits = null;
   3.157 +        currentState = BitsState.UNKNOWN;
   3.158 +    }
   3.159 +
   3.160 +    public boolean isReset() {
   3.161 +        return currentState == BitsState.UNKNOWN;
   3.162 +    }
   3.163 +
   3.164 +    public Bits assign(Bits someBits) {
   3.165 +        lastOperation = ASSIGN;
   3.166 +        oldBits = bits;
   3.167 +        bits = someBits.dup().bits;
   3.168 +        changed();
   3.169 +        currentState = BitsState.NORMAL;
   3.170 +        return this;
   3.171      }
   3.172  
   3.173      /** Return a copy of this set.
   3.174       */
   3.175 -    public Bits dup() {
   3.176 -        int[] newbits = new int[bits.length];
   3.177 -        System.arraycopy(bits, 0, newbits, 0, bits.length);
   3.178 -        return new Bits(newbits);
   3.179 +    private Bits dup() {
   3.180 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.181 +        Bits tmp = new Bits();
   3.182 +        if (currentState != BitsState.NORMAL) {
   3.183 +            tmp.bits = bits;
   3.184 +        } else {
   3.185 +            tmp.bits = new int[bits.length];
   3.186 +            System.arraycopy(bits, 0, tmp.bits, 0, bits.length);
   3.187 +        }
   3.188 +        currentState = BitsState.NORMAL;
   3.189 +        return tmp;
   3.190      }
   3.191  
   3.192      /** Include x in this set.
   3.193       */
   3.194      public void incl(int x) {
   3.195 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.196          Assert.check(x >= 0);
   3.197 +        oldBits = bits;
   3.198 +        lastOperation = INCL_BIT;
   3.199          sizeTo((x >>> wordshift) + 1);
   3.200          bits[x >>> wordshift] = bits[x >>> wordshift] |
   3.201              (1 << (x & wordmask));
   3.202 +        changed();
   3.203 +        currentState = BitsState.NORMAL;
   3.204      }
   3.205  
   3.206  
   3.207      /** Include [start..limit) in this set.
   3.208       */
   3.209      public void inclRange(int start, int limit) {
   3.210 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.211 +        oldBits = bits;
   3.212 +        lastOperation = INCL_RANGE;
   3.213          sizeTo((limit >>> wordshift) + 1);
   3.214 -        for (int x = start; x < limit; x++)
   3.215 +        for (int x = start; x < limit; x++) {
   3.216              bits[x >>> wordshift] = bits[x >>> wordshift] |
   3.217                  (1 << (x & wordmask));
   3.218 +        }
   3.219 +        changed();
   3.220 +        currentState = BitsState.NORMAL;
   3.221      }
   3.222  
   3.223      /** Exclude [start...end] from this set.
   3.224       */
   3.225      public void excludeFrom(int start) {
   3.226 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.227 +        oldBits = bits;
   3.228 +        lastOperation = EXCL_RANGE;
   3.229          Bits temp = new Bits();
   3.230          temp.sizeTo(bits.length);
   3.231          temp.inclRange(0, start);
   3.232 -        andSet(temp);
   3.233 +        internalAndSet(temp);
   3.234 +        changed();
   3.235 +        currentState = BitsState.NORMAL;
   3.236      }
   3.237  
   3.238      /** Exclude x from this set.
   3.239       */
   3.240      public void excl(int x) {
   3.241 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.242          Assert.check(x >= 0);
   3.243 +        oldBits = bits;
   3.244 +        lastOperation = EXCL_BIT;
   3.245          sizeTo((x >>> wordshift) + 1);
   3.246          bits[x >>> wordshift] = bits[x >>> wordshift] &
   3.247              ~(1 << (x & wordmask));
   3.248 +        changed();
   3.249 +        currentState = BitsState.NORMAL;
   3.250      }
   3.251  
   3.252      /** Is x an element of this set?
   3.253       */
   3.254      public boolean isMember(int x) {
   3.255 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.256          return
   3.257              0 <= x && x < (bits.length << wordshift) &&
   3.258              (bits[x >>> wordshift] & (1 << (x & wordmask))) != 0;
   3.259 @@ -130,38 +268,66 @@
   3.260      /** {@literal this set = this set & xs}.
   3.261       */
   3.262      public Bits andSet(Bits xs) {
   3.263 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.264 +        oldBits = bits;
   3.265 +        lastOperation = AND_SET;
   3.266 +        internalAndSet(xs);
   3.267 +        changed();
   3.268 +        currentState = BitsState.NORMAL;
   3.269 +        return this;
   3.270 +    }
   3.271 +
   3.272 +    private void internalAndSet(Bits xs) {
   3.273 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.274          sizeTo(xs.bits.length);
   3.275 -        for (int i = 0; i < xs.bits.length; i++)
   3.276 +        for (int i = 0; i < xs.bits.length; i++) {
   3.277              bits[i] = bits[i] & xs.bits[i];
   3.278 -        return this;
   3.279 +        }
   3.280      }
   3.281  
   3.282      /** this set = this set | xs.
   3.283       */
   3.284      public Bits orSet(Bits xs) {
   3.285 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.286 +        oldBits = bits;
   3.287 +        lastOperation = OR_SET;
   3.288          sizeTo(xs.bits.length);
   3.289 -        for (int i = 0; i < xs.bits.length; i++)
   3.290 +        for (int i = 0; i < xs.bits.length; i++) {
   3.291              bits[i] = bits[i] | xs.bits[i];
   3.292 +        }
   3.293 +        changed();
   3.294 +        currentState = BitsState.NORMAL;
   3.295          return this;
   3.296      }
   3.297  
   3.298      /** this set = this set \ xs.
   3.299       */
   3.300      public Bits diffSet(Bits xs) {
   3.301 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.302 +        oldBits = bits;
   3.303 +        lastOperation = DIFF_SET;
   3.304          for (int i = 0; i < bits.length; i++) {
   3.305              if (i < xs.bits.length) {
   3.306                  bits[i] = bits[i] & ~xs.bits[i];
   3.307              }
   3.308          }
   3.309 +        changed();
   3.310 +        currentState = BitsState.NORMAL;
   3.311          return this;
   3.312      }
   3.313  
   3.314      /** this set = this set ^ xs.
   3.315       */
   3.316      public Bits xorSet(Bits xs) {
   3.317 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.318 +        oldBits = bits;
   3.319 +        lastOperation = XOR_SET;
   3.320          sizeTo(xs.bits.length);
   3.321 -        for (int i = 0; i < xs.bits.length; i++)
   3.322 +        for (int i = 0; i < xs.bits.length; i++) {
   3.323              bits[i] = bits[i] ^ xs.bits[i];
   3.324 +        }
   3.325 +        changed();
   3.326 +        currentState = BitsState.NORMAL;
   3.327          return this;
   3.328      }
   3.329  
   3.330 @@ -187,6 +353,7 @@
   3.331       *  }</pre>
   3.332       */
   3.333      public int nextBit(int x) {
   3.334 +        Assert.check(currentState != BitsState.UNKNOWN);
   3.335          int windex = x >>> wordshift;
   3.336          if (windex >= bits.length) return -1;
   3.337          int word = bits[windex] & ~((1 << (x & wordmask))-1);
   3.338 @@ -202,17 +369,20 @@
   3.339      /** a string representation of this set.
   3.340       */
   3.341      public String toString() {
   3.342 -        char[] digits = new char[bits.length * wordlen];
   3.343 -        for (int i = 0; i < bits.length * wordlen; i++)
   3.344 -            digits[i] = isMember(i) ? '1' : '0';
   3.345 -        return new String(digits);
   3.346 +        if (bits.length > 0) {
   3.347 +            char[] digits = new char[bits.length * wordlen];
   3.348 +            for (int i = 0; i < bits.length * wordlen; i++)
   3.349 +                digits[i] = isMember(i) ? '1' : '0';
   3.350 +            return new String(digits);
   3.351 +        } else {
   3.352 +            return "[]";
   3.353 +        }
   3.354      }
   3.355  
   3.356      /** Test Bits.nextBit(int). */
   3.357      public static void main(String[] args) {
   3.358          java.util.Random r = new java.util.Random();
   3.359          Bits bits = new Bits();
   3.360 -        int dupCount = 0;
   3.361          for (int i=0; i<125; i++) {
   3.362              int k;
   3.363              do {

mercurial