Fri, 26 Apr 2013 10:17:01 +0100
8008562: javac, a refactoring to Bits is necessary in order to provide a change history
Reviewed-by: mcimadamore
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 {