8068489: remove unnecessary complexity in Flow and Bits, after JDK-8064857

Reviewed-by: mcimadamore, jjg
This commit is contained in:
Vicente Romero 2015-02-18 17:07:06 -08:00
parent 0a57971dd9
commit 7bf016c7b1
2 changed files with 265 additions and 380 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -353,17 +353,17 @@ public class Flow {
this.tree = tree;
}
void resolveJump(JCTree tree) {
void resolveJump() {
//do nothing
}
}
abstract void markDead(JCTree tree);
abstract void markDead();
/** Record an outward transfer of control. */
void recordExit(JCTree tree, P pe) {
void recordExit(P pe) {
pendingExits.append(pe);
markDead(tree);
markDead();
}
/** Resolve all jumps of this statement. */
@ -377,7 +377,7 @@ public class Flow {
P exit = exits.head;
if (exit.tree.hasTag(jk.treeTag) &&
jk.getTarget(exit.tree) == tree) {
exit.resolveJump(tree);
exit.resolveJump();
resolved = true;
} else {
pendingExits.append(exit);
@ -424,7 +424,7 @@ public class Flow {
private boolean alive;
@Override
void markDead(JCTree tree) {
void markDead() {
alive = false;
}
@ -692,21 +692,21 @@ public class Flow {
}
public void visitBreak(JCBreak tree) {
recordExit(tree, new PendingExit(tree));
recordExit(new PendingExit(tree));
}
public void visitContinue(JCContinue tree) {
recordExit(tree, new PendingExit(tree));
recordExit(new PendingExit(tree));
}
public void visitReturn(JCReturn tree) {
scan(tree.expr);
recordExit(tree, new PendingExit(tree));
recordExit(new PendingExit(tree));
}
public void visitThrow(JCThrow tree) {
scan(tree.expr);
markDead(tree);
markDead();
}
public void visitApply(JCMethodInvocation tree) {
@ -803,7 +803,7 @@ public class Flow {
}
@Override
void markDead(JCTree tree) {
void markDead() {
//do nothing
}
@ -1201,16 +1201,16 @@ public class Flow {
}
public void visitBreak(JCBreak tree) {
recordExit(tree, new FlowPendingExit(tree, null));
recordExit(new FlowPendingExit(tree, null));
}
public void visitContinue(JCContinue tree) {
recordExit(tree, new FlowPendingExit(tree, null));
recordExit(new FlowPendingExit(tree, null));
}
public void visitReturn(JCReturn tree) {
scan(tree.expr);
recordExit(tree, new FlowPendingExit(tree, null));
recordExit(new FlowPendingExit(tree, null));
}
public void visitThrow(JCThrow tree) {
@ -1228,7 +1228,7 @@ public class Flow {
else {
markThrown(tree, tree.expr.type);
}
markDead(tree);
markDead();
}
public void visitApply(JCMethodInvocation tree) {
@ -1375,12 +1375,11 @@ public class Flow {
* effectively-final local variables/parameters.
*/
public abstract class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer<P>.AbstractAssignPendingExit>
extends BaseAnalyzer<P> {
public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
/** The set of definitely assigned variables.
*/
protected Bits inits;
final Bits inits;
/** The set of definitely unassigned variables.
*/
@ -1428,20 +1427,20 @@ public class Flow {
*/
WriteableScope unrefdResources;
/** Set when processing a loop body the second time for DU analysis. */
/** Modified when processing a loop body the second time for DU analysis. */
FlowKind flowKind = FlowKind.NORMAL;
/** The starting position of the analysed tree */
/** The starting position of the analyzed tree */
int startPos;
public class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit {
public class AssignPendingExit extends BaseAnalyzer.PendingExit {
final Bits inits;
final Bits uninits;
final Bits exit_inits = new Bits(true);
final Bits exit_uninits = new Bits(true);
public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
super(tree);
this.inits = inits;
this.uninits = uninits;
@ -1450,13 +1449,13 @@ public class Flow {
}
@Override
public void resolveJump(JCTree tree) {
public void resolveJump() {
inits.andSet(exit_inits);
uninits.andSet(exit_uninits);
}
}
public AbstractAssignAnalyzer() {
public AssignAnalyzer() {
this.inits = new Bits();
uninits = new Bits();
uninitsTry = new Bits();
@ -1469,7 +1468,7 @@ public class Flow {
private boolean isInitialConstructor = false;
@Override
protected void markDead(JCTree tree) {
protected void markDead() {
if (!isInitialConstructor) {
inits.inclRange(returnadr, nextadr);
} else {
@ -1516,35 +1515,43 @@ public class Flow {
}
sym.adr = nextadr;
vardecls[nextadr] = varDecl;
exclVarFromInits(varDecl, nextadr);
inits.excl(nextadr);
uninits.incl(nextadr);
nextadr++;
}
protected void exclVarFromInits(JCTree tree, int adr) {
inits.excl(adr);
}
protected void assignToInits(JCTree tree, Bits bits) {
inits.assign(bits);
}
protected void andSetInits(JCTree tree, Bits bits) {
inits.andSet(bits);
}
protected void orSetInits(JCTree tree, Bits bits) {
inits.orSet(bits);
}
/** Record an initialization of a trackable variable.
*/
void letInit(DiagnosticPosition pos, VarSymbol sym) {
if (sym.adr >= firstadr && trackable(sym)) {
if (uninits.isMember(sym.adr)) {
if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
if (!uninits.isMember(sym.adr)) {
//assignment targeting an effectively final variable
//makes the variable lose its status of effectively final
//if the variable is _not_ definitively unassigned
sym.flags_field &= ~EFFECTIVELY_FINAL;
} else {
uninit(sym);
}
}
else if ((sym.flags() & FINAL) != 0) {
if ((sym.flags() & PARAMETER) != 0) {
if ((sym.flags() & UNION) != 0) { //multi-catch parameter
log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
}
else {
log.error(pos, "final.parameter.may.not.be.assigned",
sym);
}
} else if (!uninits.isMember(sym.adr)) {
log.error(pos, flowKind.errKey, sym);
} else {
uninit(sym);
}
}
inits.incl(sym.adr);
} else if ((sym.flags() & FINAL) != 0) {
log.error(pos, "var.might.already.be.assigned", sym);
}
}
//where
@ -1579,7 +1586,14 @@ public class Flow {
checkInit(pos, sym, "var.might.not.have.been.initialized");
}
void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {}
void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
trackable(sym) &&
!inits.isMember(sym.adr)) {
log.error(pos, errkey, sym);
inits.incl(sym.adr);
}
}
/** Utility method to reset several Bits instances.
*/
@ -1603,7 +1617,7 @@ public class Flow {
/** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
*/
protected void merge(JCTree tree) {
protected void merge() {
inits.assign(initsWhenFalse.andSet(initsWhenTrue));
uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
}
@ -1619,7 +1633,7 @@ public class Flow {
if (tree != null) {
scan(tree);
if (inits.isReset()) {
merge(tree);
merge();
}
}
}
@ -1637,7 +1651,7 @@ public class Flow {
*/
void scanCond(JCTree tree) {
if (tree.type.isFalse()) {
if (inits.isReset()) merge(tree);
if (inits.isReset()) merge();
initsWhenTrue.assign(inits);
initsWhenTrue.inclRange(firstadr, nextadr);
uninitsWhenTrue.assign(uninits);
@ -1645,7 +1659,7 @@ public class Flow {
initsWhenFalse.assign(inits);
uninitsWhenFalse.assign(uninits);
} else if (tree.type.isTrue()) {
if (inits.isReset()) merge(tree);
if (inits.isReset()) merge();
initsWhenFalse.assign(inits);
initsWhenFalse.inclRange(firstadr, nextadr);
uninitsWhenFalse.assign(uninits);
@ -1664,16 +1678,22 @@ public class Flow {
/* ------------ Visitor methods for various sorts of trees -------------*/
@Override
public void visitClassDef(JCClassDecl tree) {
if (tree.sym == null) {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
if (tree.sym == null) {
return;
}
JCClassDecl classDefPrev = classDef;
int firstadrPrev = firstadr;
int nextadrPrev = nextadr;
ListBuffer<P> pendingExitsPrev = pendingExits;
ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
pendingExits = new ListBuffer<>();
if (tree.name != names.empty) {
@ -1735,13 +1755,28 @@ public class Flow {
firstadr = firstadrPrev;
classDef = classDefPrev;
}
} finally {
lint = lintPrev;
}
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
if (tree.body == null) {
return;
}
/* MemberEnter can generate synthetic methods ignore them
*/
if ((tree.sym.flags() & SYNTHETIC) != 0) {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
if (tree.body == null) {
return;
}
/* Ignore synthetic methods, except for translated lambda methods.
*/
if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
@ -1793,27 +1828,30 @@ public class Flow {
}
}
}
List<P> exits = pendingExits.toList();
List<AssignPendingExit> exits = pendingExits.toList();
pendingExits = new ListBuffer<>();
while (exits.nonEmpty()) {
P exit = exits.head;
AssignPendingExit exit = exits.head;
exits = exits.tail;
Assert.check(exit.tree.hasTag(RETURN), exit.tree);
if (isInitialConstructor) {
assignToInits(exit.tree, exit.exit_inits);
inits.assign(exit.exit_inits);
for (int i = firstadr; i < nextadr; i++) {
checkInit(exit.tree.pos(), vardecls[i].sym);
}
}
}
} finally {
assignToInits(tree, initsPrev);
inits.assign(initsPrev);
uninits.assign(uninitsPrev);
nextadr = nextadrPrev;
firstadr = firstadrPrev;
returnadr = returnadrPrev;
isInitialConstructor = lastInitialConstructor;
}
} finally {
lint = lintPrev;
}
}
protected void initParam(JCVariableDecl def) {
@ -1822,6 +1860,9 @@ public class Flow {
}
public void visitVarDef(JCVariableDecl tree) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try{
boolean track = trackable(tree.sym);
if (track && tree.sym.owner.kind == MTH) {
newVar(tree);
@ -1832,6 +1873,9 @@ public class Flow {
letInit(tree.pos(), tree.sym);
}
}
} finally {
lint = lintPrev;
}
}
public void visitBlock(JCBlock tree) {
@ -1840,18 +1884,14 @@ public class Flow {
nextadr = nextadrPrev;
}
int getLogNumberOfErrors() {
return 0;
}
public void visitDoLoop(JCDoWhileLoop tree) {
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
int prevErrors = getLogNumberOfErrors();
int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
@ -1862,28 +1902,28 @@ public class Flow {
initsSkip.assign(initsWhenFalse);
uninitsSkip.assign(uninitsWhenFalse);
}
if (getLogNumberOfErrors() != prevErrors ||
if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
break;
assignToInits(tree.cond, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
flowKind = FlowKind.SPECULATIVE_LOOP;
} while (true);
flowKind = prevFlowKind;
assignToInits(tree, initsSkip);
inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
}
public void visitWhileLoop(JCWhileLoop tree) {
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
int prevErrors = getLogNumberOfErrors();
int prevErrors = log.nerrors;
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
do {
@ -1892,11 +1932,11 @@ public class Flow {
initsSkip.assign(initsWhenFalse) ;
uninitsSkip.assign(uninitsWhenFalse);
}
assignToInits(tree, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scan(tree.body);
resolveContinues(tree);
if (getLogNumberOfErrors() != prevErrors ||
if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
break;
@ -1907,13 +1947,13 @@ public class Flow {
flowKind = prevFlowKind;
//a variable is DA/DU after the while statement, if it's DA/DU assuming the
//branch is not taken AND if it's DA/DU before any break statement
assignToInits(tree.body, initsSkip);
inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
}
public void visitForLoop(JCForLoop tree) {
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
int nextadrPrev = nextadr;
@ -1921,7 +1961,7 @@ public class Flow {
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
int prevErrors = getLogNumberOfErrors();
int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
@ -1931,7 +1971,7 @@ public class Flow {
initsSkip.assign(initsWhenFalse);
uninitsSkip.assign(uninitsWhenFalse);
}
assignToInits(tree.body, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
} else if (!flowKind.isFinal()) {
initsSkip.assign(inits);
@ -1942,7 +1982,7 @@ public class Flow {
scan(tree.body);
resolveContinues(tree);
scan(tree.step);
if (getLogNumberOfErrors() != prevErrors ||
if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
break;
@ -1952,7 +1992,7 @@ public class Flow {
flowKind = prevFlowKind;
//a variable is DA/DU after a for loop, if it's DA/DU assuming the
//branch is not taken AND if it's DA/DU before any break statement
assignToInits(tree.body, initsSkip);
inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
@ -1961,7 +2001,7 @@ public class Flow {
public void visitForeachLoop(JCEnhancedForLoop tree) {
visitVarDef(tree.var);
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
int nextadrPrev = nextadr;
@ -1971,13 +2011,13 @@ public class Flow {
letInit(tree.pos(), tree.var.sym);
pendingExits = new ListBuffer<>();
int prevErrors = getLogNumberOfErrors();
int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
scan(tree.body);
resolveContinues(tree);
if (getLogNumberOfErrors() != prevErrors ||
if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
break;
@ -1985,21 +2025,21 @@ public class Flow {
flowKind = FlowKind.SPECULATIVE_LOOP;
} while (true);
flowKind = prevFlowKind;
assignToInits(tree.body, initsStart);
inits.assign(initsStart);
uninits.assign(uninitsStart.andSet(uninits));
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
}
public void visitLabelled(JCLabeledStatement tree) {
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
scan(tree.body);
resolveBreaks(tree, prevPendingExits);
}
public void visitSwitch(JCSwitch tree) {
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
int nextadrPrev = nextadr;
scanExpr(tree.selector);
@ -2007,7 +2047,7 @@ public class Flow {
final Bits uninitsSwitch = new Bits(uninits);
boolean hasDefault = false;
for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
assignToInits(l.head, initsSwitch);
inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
JCCase c = l.head;
if (c.pat == null) {
@ -2016,19 +2056,19 @@ public class Flow {
scanExpr(c.pat);
}
if (hasDefault) {
assignToInits(null, initsSwitch);
inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
}
scan(c.stats);
addVars(c.stats, initsSwitch, uninitsSwitch);
if (!hasDefault) {
assignToInits(l.head.stats.last(), initsSwitch);
inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
}
// Warn about fall-through if lint switch fallthrough enabled.
}
if (!hasDefault) {
andSetInits(null, initsSwitch);
inits.andSet(initsSwitch);
}
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
@ -2047,16 +2087,10 @@ public class Flow {
}
}
boolean isEnabled(Lint.LintCategory lc) {
return false;
}
void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {}
public void visitTry(JCTry tree) {
ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
final Bits uninitsTryPrev = new Bits(uninitsTry);
ListBuffer<P> prevPendingExits = pendingExits;
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
final Bits initsTry = new Bits(inits);
uninitsTry.assign(uninits);
@ -2079,10 +2113,10 @@ public class Flow {
int nextadrCatch = nextadr;
if (!resourceVarDecls.isEmpty() &&
isEnabled(Lint.LintCategory.TRY)) {
lint.isEnabled(Lint.LintCategory.TRY)) {
for (JCVariableDecl resVar : resourceVarDecls) {
if (unrefdResources.includes(resVar.sym)) {
reportWarning(Lint.LintCategory.TRY, resVar.pos(),
log.warning(Lint.LintCategory.TRY, resVar.pos(),
"try.resource.not.referenced", resVar.sym);
unrefdResources.remove(resVar.sym);
}
@ -2098,7 +2132,7 @@ public class Flow {
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
JCVariableDecl param = l.head.param;
assignToInits(tree.body, initsCatchPrev);
inits.assign(initsCatchPrev);
uninits.assign(uninitsCatchPrev);
scan(param);
/* If this is a TWR and we are executing the code from Gen,
@ -2111,9 +2145,9 @@ public class Flow {
nextadr = nextadrCatch;
}
if (tree.finalizer != null) {
assignToInits(tree.finalizer, initsTry);
inits.assign(initsTry);
uninits.assign(uninitsTry);
ListBuffer<P> exits = pendingExits;
ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
scan(tree.finalizer);
if (!tree.finallyCanCompleteNormally) {
@ -2123,19 +2157,19 @@ public class Flow {
// FIX: this doesn't preserve source order of exits in catch
// versus finally!
while (exits.nonEmpty()) {
P exit = exits.next();
AssignPendingExit exit = exits.next();
if (exit.exit_inits != null) {
exit.exit_inits.orSet(inits);
exit.exit_uninits.andSet(uninits);
}
pendingExits.append(exit);
}
orSetInits(tree, initsEnd);
inits.orSet(initsEnd);
}
} else {
assignToInits(tree, initsEnd);
inits.assign(initsEnd);
uninits.assign(uninitsEnd);
ListBuffer<P> exits = pendingExits;
ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
while (exits.nonEmpty()) pendingExits.append(exits.next());
}
@ -2146,7 +2180,7 @@ public class Flow {
scanCond(tree.cond);
final Bits initsBeforeElse = new Bits(initsWhenFalse);
final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
assignToInits(tree.cond, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
if (tree.truepart.type.hasTag(BOOLEAN) &&
tree.falsepart.type.hasTag(BOOLEAN)) {
@ -2159,7 +2193,7 @@ public class Flow {
final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
assignToInits(tree.truepart, initsBeforeElse);
inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scanCond(tree.falsepart);
initsWhenTrue.andSet(initsAfterThenWhenTrue);
@ -2170,10 +2204,10 @@ public class Flow {
scanExpr(tree.truepart);
final Bits initsAfterThen = new Bits(inits);
final Bits uninitsAfterThen = new Bits(uninits);
assignToInits(tree.truepart, initsBeforeElse);
inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scanExpr(tree.falsepart);
andSetInits(tree.falsepart, initsAfterThen);
inits.andSet(initsAfterThen);
uninits.andSet(uninitsAfterThen);
}
}
@ -2182,46 +2216,42 @@ public class Flow {
scanCond(tree.cond);
final Bits initsBeforeElse = new Bits(initsWhenFalse);
final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
assignToInits(tree.cond, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scan(tree.thenpart);
if (tree.elsepart != null) {
final Bits initsAfterThen = new Bits(inits);
final Bits uninitsAfterThen = new Bits(uninits);
assignToInits(tree.thenpart, initsBeforeElse);
inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scan(tree.elsepart);
andSetInits(tree.elsepart, initsAfterThen);
inits.andSet(initsAfterThen);
uninits.andSet(uninitsAfterThen);
} else {
andSetInits(tree.thenpart, initsBeforeElse);
inits.andSet(initsBeforeElse);
uninits.andSet(uninitsBeforeElse);
}
}
protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
return null;
}
@Override
public void visitBreak(JCBreak tree) {
recordExit(tree, createNewPendingExit(tree, inits, uninits));
recordExit(new AssignPendingExit(tree, inits, uninits));
}
@Override
public void visitContinue(JCContinue tree) {
recordExit(tree, createNewPendingExit(tree, inits, uninits));
recordExit(new AssignPendingExit(tree, inits, uninits));
}
@Override
public void visitReturn(JCReturn tree) {
scanExpr(tree.expr);
recordExit(tree, createNewPendingExit(tree, inits, uninits));
recordExit(new AssignPendingExit(tree, inits, uninits));
}
public void visitThrow(JCThrow tree) {
scanExpr(tree.expr);
markDead(tree.expr);
markDead();
}
public void visitApply(JCMethodInvocation tree) {
@ -2240,7 +2270,7 @@ public class Flow {
final Bits prevUninits = new Bits(uninits);
final Bits prevInits = new Bits(inits);
int returnadrPrev = returnadr;
ListBuffer<P> prevPending = pendingExits;
ListBuffer<AssignPendingExit> prevPending = pendingExits;
try {
returnadr = nextadr;
pendingExits = new ListBuffer<>();
@ -2259,7 +2289,7 @@ public class Flow {
finally {
returnadr = returnadrPrev;
uninits.assign(prevUninits);
assignToInits(tree, prevInits);
inits.assign(prevInits);
pendingExits = prevPending;
}
}
@ -2275,11 +2305,11 @@ public class Flow {
scanCond(tree.cond);
uninitsExit.andSet(uninitsWhenTrue);
if (tree.detail != null) {
assignToInits(tree, initsWhenFalse);
inits.assign(initsWhenFalse);
uninits.assign(uninitsWhenFalse);
scanExpr(tree.detail);
}
assignToInits(tree, initsExit);
inits.assign(initsExit);
uninits.assign(uninitsExit);
}
@ -2308,8 +2338,7 @@ public class Flow {
if (enforceThisDotInit &&
tree.selected.hasTag(IDENT) &&
((JCIdent)tree.selected).name == names._this &&
tree.sym.kind == VAR)
{
tree.sym.kind == VAR) {
checkInit(tree.pos(), (VarSymbol)tree.sym);
}
}
@ -2347,7 +2376,7 @@ public class Flow {
scanCond(tree.lhs);
final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
assignToInits(tree.lhs, initsWhenTrue);
inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scanCond(tree.rhs);
initsWhenFalse.andSet(initsWhenFalseLeft);
@ -2357,7 +2386,7 @@ public class Flow {
scanCond(tree.lhs);
final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
assignToInits(tree.lhs, initsWhenFalse);
inits.assign(initsWhenFalse);
uninits.assign(uninitsWhenFalse);
scanCond(tree.rhs);
initsWhenTrue.andSet(initsWhenTrueLeft);
@ -2428,136 +2457,6 @@ public class Flow {
}
}
public class AssignAnalyzer extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> {
public class AssignPendingExit extends AbstractAssignAnalyzer<AssignPendingExit>.AbstractAssignPendingExit {
public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
super(tree, inits, uninits);
}
}
@Override
protected AssignPendingExit createNewPendingExit(JCTree tree,
Bits inits, Bits uninits) {
return new AssignPendingExit(tree, inits, uninits);
}
/** Record an initialization of a trackable variable.
*/
@Override
void letInit(DiagnosticPosition pos, VarSymbol sym) {
if (sym.adr >= firstadr && trackable(sym)) {
if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
if (!uninits.isMember(sym.adr)) {
//assignment targeting an effectively final variable
//makes the variable lose its status of effectively final
//if the variable is _not_ definitively unassigned
sym.flags_field &= ~EFFECTIVELY_FINAL;
} else {
uninit(sym);
}
}
else if ((sym.flags() & FINAL) != 0) {
if ((sym.flags() & PARAMETER) != 0) {
if ((sym.flags() & UNION) != 0) { //multi-catch parameter
log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
}
else {
log.error(pos, "final.parameter.may.not.be.assigned",
sym);
}
} else if (!uninits.isMember(sym.adr)) {
log.error(pos, flowKind.errKey, sym);
} else {
uninit(sym);
}
}
inits.incl(sym.adr);
} else if ((sym.flags() & FINAL) != 0) {
log.error(pos, "var.might.already.be.assigned", sym);
}
}
@Override
void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
trackable(sym) &&
!inits.isMember(sym.adr)) {
log.error(pos, errkey, sym);
inits.incl(sym.adr);
}
}
@Override
void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos,
String key, Object ... args) {
log.warning(lc, pos, key, args);
}
@Override
int getLogNumberOfErrors() {
return log.nerrors;
}
@Override
boolean isEnabled(Lint.LintCategory lc) {
return lint.isEnabled(lc);
}
@Override
public void visitClassDef(JCClassDecl tree) {
if (tree.sym == null) {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
super.visitClassDef(tree);
} finally {
lint = lintPrev;
}
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
if (tree.body == null) {
return;
}
/* MemberEnter can generate synthetic methods ignore them
*/
if ((tree.sym.flags() & SYNTHETIC) != 0) {
return;
}
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try {
super.visitMethodDef(tree);
} finally {
lint = lintPrev;
}
}
@Override
public void visitVarDef(JCVariableDecl tree) {
if (tree.init == null) {
super.visitVarDef(tree);
} else {
Lint lintPrev = lint;
lint = lint.augment(tree.sym);
try{
super.visitVarDef(tree);
} finally {
lint = lintPrev;
}
}
}
}
/**
* This pass implements the last step of the dataflow analysis, namely
* the effectively-final analysis check. This checks that every local variable
@ -2572,7 +2471,7 @@ public class Flow {
JCTree currentTree; //local class or lambda
@Override
void markDead(JCTree tree) {
void markDead() {
//do nothing
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -84,20 +84,6 @@ public class Bits {
}
public enum BitsOpKind {
INIT,
CLEAR,
INCL_BIT,
EXCL_BIT,
ASSIGN,
AND_SET,
OR_SET,
DIFF_SET,
XOR_SET,
INCL_RANGE,
EXCL_RANGE,
}
private final static int wordlen = 32;
private final static int wordshift = 5;
private final static int wordmask = wordlen - 1;