📄 flow.java
字号:
/** * Resolve all breaks of this statement. */ boolean resolveBreaks(Tree tree, ListBuffer oldPendingExits) { boolean result = false; List exits = pendingExits.toList(); pendingExits = oldPendingExits; for (; exits.nonEmpty(); exits = exits.tail) { PendingExit exit = (Flow.PendingExit) exits.head; if (exit.tree.tag == Tree.BREAK && ((Break) exit.tree).target == tree) { inits.andSet(exit.inits); uninits.andSet(exit.uninits); result = true; } else { pendingExits.append(exit); } } return result; } /** * Resolve all continues of this statement. */ boolean resolveContinues(Tree tree) { boolean result = false; List exits = pendingExits.toList(); pendingExits = new ListBuffer(); for (; exits.nonEmpty(); exits = exits.tail) { PendingExit exit = (Flow.PendingExit) exits.head; if (exit.tree.tag == Tree.CONTINUE && ((Continue) exit.tree).target == tree) { inits.andSet(exit.inits); uninits.andSet(exit.uninits); result = true; } else { pendingExits.append(exit); } } return result; } /** * Record that statement is unreachable. */ void markDead() { inits.inclRange(firstadr, nextadr); uninits.inclRange(firstadr, nextadr); alive = false; } /** * Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets */ void split() { initsWhenFalse = inits.dup(); uninitsWhenFalse = uninits.dup(); initsWhenTrue = inits; uninitsWhenTrue = uninits; inits = uninits = null; } /** * Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. */ void merge() { inits = initsWhenFalse.andSet(initsWhenTrue); uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); } /** * Analyze a definition. */ void scanDef(Tree tree) { scanStat(tree); if (tree != null && tree.tag == Tree.BLOCK && !alive) { log.error(tree.pos, "initializer.must.be.able.to.complete.normally"); } } /** * Analyze a statement. Check that statement is reachable. */ void scanStat(Tree tree) { if (!alive && tree != null) { log.error(tree.pos, "unreachable.stmt"); if (tree.tag != Tree.SKIP) alive = true; } scan(tree); } /** * Analyze list of statements. */ void scanStats(List trees) { if (trees != null) for (List l = trees; l.nonEmpty(); l = l.tail) scanStat((Tree) l.head); } /** * Analyze an expression. Make sure to set (un)inits rather than * (un)initsWhenTrue(WhenFalse) on exit. */ void scanExpr(Tree tree) { if (tree != null) { scan(tree); if (inits == null) merge(); } } /** * Analyze a list of expressions. */ void scanExprs(List trees) { if (trees != null) for (List l = trees; l.nonEmpty(); l = l.tail) scanExpr((Tree) l.head); } /** * Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse) * rather than (un)inits on exit. */ void scanCond(Tree tree) { if (tree.type.isFalse()) { if (inits == null) merge(); initsWhenTrue = inits.dup(); initsWhenTrue.inclRange(firstadr, nextadr); uninitsWhenTrue = uninits.dup(); uninitsWhenTrue.inclRange(firstadr, nextadr); initsWhenFalse = inits; uninitsWhenFalse = uninits; } else if (tree.type.isTrue()) { if (inits == null) merge(); initsWhenFalse = inits.dup(); initsWhenFalse.inclRange(firstadr, nextadr); uninitsWhenFalse = uninits.dup(); uninitsWhenFalse.inclRange(firstadr, nextadr); initsWhenTrue = inits; uninitsWhenTrue = uninits; } else { scan(tree); if (inits != null) split(); } inits = uninits = null; } public void visitClassDef(ClassDef tree) { if (tree.sym == null) return; ClassDef classDefPrev = classDef; List thrownPrev = thrown; List caughtPrev = caught; boolean alivePrev = alive; int firstadrPrev = firstadr; int nextadrPrev = nextadr; ListBuffer pendingExitsPrev = pendingExits; pendingExits = new ListBuffer(); if (tree.name != names.empty) { caught = Type.emptyList; firstadr = nextadr; } classDef = tree; thrown = Type.emptyList; try { for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (((Tree) l.head).tag == Tree.VARDEF) { VarDef def = (VarDef) l.head; if ((def.flags & STATIC) != 0) { VarSymbol sym = def.sym; if (trackable(sym)) newVar(sym); } } } for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (((Tree) l.head).tag != Tree.METHODDEF && (TreeInfo.flags((Tree) l.head) & STATIC) != 0) { scanDef((Tree) l.head); errorUncaught(); } } if (tree.name != names.empty) { boolean firstConstructor = true; for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (TreeInfo.isInitialConstructor((Tree) l.head)) { List mthrown = ((MethodDef) l.head).sym.type.thrown(); if (firstConstructor) { caught = mthrown; firstConstructor = false; } else { caught = chk.intersect(mthrown, caught); } } } } for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (((Tree) l.head).tag == Tree.VARDEF) { VarDef def = (VarDef) l.head; if ((def.flags & STATIC) == 0) { VarSymbol sym = def.sym; if (trackable(sym)) newVar(sym); } } } for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (((Tree) l.head).tag != Tree.METHODDEF && (TreeInfo.flags((Tree) l.head) & STATIC) == 0) { scanDef((Tree) l.head); errorUncaught(); } } for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (((Tree) l.head).tag == Tree.METHODDEF) { scan((Tree) l.head); errorUncaught(); } } if (tree.name == names.empty) { for (List l = tree.defs; l.nonEmpty(); l = l.tail) { if (TreeInfo.isInitialConstructor((Tree) l.head)) { MethodDef mdef = (MethodDef) l.head; mdef.thrown = make.Types(thrown); ((MethodType) mdef.sym.type).thrown = thrown; } } thrown = chk.union(thrown, thrownPrev); } else { thrown = thrownPrev; } } finally { pendingExits = pendingExitsPrev; alive = alivePrev; nextadr = nextadrPrev; firstadr = firstadrPrev; caught = caughtPrev; classDef = classDefPrev; } } public void visitMethodDef(MethodDef tree) { if (tree.body == null) return; List caughtPrev = caught; List mthrown = tree.sym.type.thrown(); Bits initsPrev = inits.dup(); Bits uninitsPrev = uninits.dup(); int nextadrPrev = nextadr; int firstadrPrev = firstadr; assert pendingExits.isEmpty(); try { boolean isInitialConstructor = TreeInfo.isInitialConstructor(tree); if (!isInitialConstructor) firstadr = nextadr; for (List l = tree.params; l.nonEmpty(); l = l.tail) { VarDef def = (Tree.VarDef) l.head; scan(def); inits.incl(def.sym.adr); uninits.excl(def.sym.adr); } if (isInitialConstructor) caught = chk.union(caught, mthrown); else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK) caught = mthrown; alive = true; scanStat(tree.body); int endPos = TreeInfo.endPos(tree.body); if (alive && tree.sym.type.restype().tag != VOID) log.error(endPos, "missing.ret.stmt"); if (isInitialConstructor) { for (int i = firstadr; i < nextadr; i++) if (vars[i].owner == classDef.sym) checkInit(endPos, vars[i]); } List exits = pendingExits.toList(); pendingExits = new ListBuffer(); while (exits.nonEmpty()) { PendingExit exit = (Flow.PendingExit) exits.head; exits = exits.tail; if (exit.thrown == null) { assert exit.tree.tag == Tree.RETURN; if (isInitialConstructor) { inits = exit.inits; for (int i = firstadr; i < nextadr; i++) checkInit(exit.tree.pos, vars[i]); } } else { pendingExits.append(exit); } } } finally { inits = initsPrev; uninits = uninitsPrev; nextadr = nextadrPrev; firstadr = firstadrPrev; caught = caughtPrev; } } public void visitVarDef(VarDef tree) { boolean track = trackable(tree.sym); if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); if (tree.init != null) { scanExpr(tree.init); if (track) letInit(tree.pos, tree.sym); } } public void visitBlock(Block tree) { int nextadrPrev = nextadr; scanStats(tree.stats); nextadr = nextadrPrev; } public void visitDoLoop(DoLoop tree) { ListBuffer prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; do { pendingExits = new ListBuffer(); Bits uninitsEntry = uninits.dup(); scanStat(tree.body); alive |= resolveContinues(tree); scanCond(tree.cond); if (log.nerrors != 0 || loopPassTwo || uninitsEntry.diffSet(uninitsWhenTrue).nextBit(firstadr) == -1) break; inits = initsWhenTrue; uninits = uninitsEntry.andSet(uninitsWhenTrue); loopPassTwo = true; alive = true; } while (true) ; loopPassTwo = prevLoopPassTwo; inits = initsWhenFalse; uninits = uninitsWhenFalse; alive = alive && !tree.cond.type.isTrue(); alive |= resolveBreaks(tree, prevPendingExits); } public void visitWhileLoop(WhileLoop tree) { ListBuffer prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; Bits initsCond; Bits uninitsCond; do { pendingExits = new ListBuffer(); Bits uninitsEntry = uninits.dup(); scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; alive = !tree.cond.type.isFalse(); scanStat(tree.body); alive |= resolveContinues(tree); if (log.nerrors != 0 || loopPassTwo || uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1) break; uninits = uninitsEntry.andSet(uninits); loopPassTwo = true; alive = true; } while (true) ; loopPassTwo = prevLoopPassTwo; inits = initsCond; uninits = uninitsCond; alive = resolveBreaks(tree, prevPendingExits) || !tree.cond.type.isTrue(); } public void visitForLoop(ForLoop tree) { ListBuffer prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; int nextadrPrev = nextadr; scanStats(tree.init); Bits initsCond; Bits uninitsCond; do { pendingExits = new ListBuffer(); Bits uninitsEntry = uninits.dup(); if (tree.cond != null) { scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; inits = initsWhenTrue; uninits = uninitsWhenTrue; alive = !tree.cond.type.isFalse();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -