diff -r a9f1805e3ba9 -r 1d395a623f16 langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Jul 05 16:39:28 2017 +0200 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Jul 23 19:55:30 2008 -0700 @@ -63,6 +63,7 @@ // TEMP, until we have a more efficient way to save doc comment info import com.sun.tools.javac.parser.DocCommentScanner; +import java.util.HashMap; import java.util.Queue; import javax.lang.model.SourceVersion; @@ -444,7 +445,25 @@ */ public Todo todo; - private Set> deferredSugar = new HashSet>(); + protected enum CompileState { + TODO(0), + ATTR(1), + FLOW(2); + CompileState(int value) { + this.value = value; + } + boolean isDone(CompileState other) { + return value >= other.value; + } + private int value; + }; + protected class CompileStates extends HashMap,CompileState> { + boolean isDone(Env env, CompileState cs) { + CompileState ecs = get(env); + return ecs != null && ecs.isDone(cs); + } + } + private CompileStates compileStates = new CompileStates(); /** The set of currently compiled inputfiles, needed to ensure * we don't accidentally overwrite an input file when -s is set. @@ -1039,6 +1058,9 @@ * @returns the attributed parse tree */ public Env attribute(Env env) { + if (compileStates.isDone(env, CompileState.ATTR)) + return env; + if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); if (verbose) @@ -1055,6 +1077,7 @@ env.toplevel.sourcefile); try { attr.attribClass(env.tree.pos(), env.enclClass.sym); + compileStates.put(env, CompileState.ATTR); } finally { log.useSource(prev); @@ -1094,7 +1117,7 @@ if (errorCount() > 0) return; - if (relax || deferredSugar.contains(env)) { + if (relax || compileStates.isDone(env, CompileState.FLOW)) { results.append(env); return; } @@ -1109,6 +1132,7 @@ make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); flow.analyzeTree(env.tree, localMake); + compileStates.put(env, CompileState.FLOW); if (errorCount() > 0) return; @@ -1146,7 +1170,7 @@ * the current implicitSourcePolicy is taken into account. * The preparation stops as soon as an error is found. */ - protected void desugar(Env env, Queue, JCClassDecl>> results) { + protected void desugar(final Env env, Queue, JCClassDecl>> results) { if (errorCount() > 0) return; @@ -1155,13 +1179,30 @@ return; } - if (desugarLater(env)) { - if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[defer " + env.enclClass.sym + "]"); - todo.append(env); - return; + /** + * As erasure (TransTypes) destroys information needed in flow analysis, + * including information in supertypes, we need to ensure that supertypes + * are processed through attribute and flow before subtypes are translated. + */ + class ScanNested extends TreeScanner { + Set> dependencies = new HashSet>(); + public void visitClassDef(JCClassDecl node) { + Type st = types.supertype(node.sym.type); + if (st.tag == TypeTags.CLASS) { + ClassSymbol c = st.tsym.outermostClass(); + Env stEnv = enter.getEnv(c); + if (stEnv != null && env != stEnv) + dependencies.add(stEnv); + } + super.visitClassDef(node); + } } - deferredSugar.remove(env); + ScanNested scanner = new ScanNested(); + scanner.scan(env.tree); + for (Env dep: scanner.dependencies) { + if (!compileStates.isDone(dep, CompileState.FLOW)) + flow(attribute(dep)); + } if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]"); @@ -1234,43 +1275,6 @@ } - /** - * Determine if a class needs to be desugared later. As erasure - * (TransTypes) destroys information needed in flow analysis, we - * need to ensure that supertypes are translated before derived - * types are translated. - */ - public boolean desugarLater(final Env env) { - if (compilePolicy == CompilePolicy.BY_FILE) - return false; - if (!devVerbose && deferredSugar.contains(env)) - // guarantee that compiler terminates - return false; - class ScanNested extends TreeScanner { - Set externalSupers = new HashSet(); - public void visitClassDef(JCClassDecl node) { - Type st = types.supertype(node.sym.type); - if (st.tag == TypeTags.CLASS) { - ClassSymbol c = st.tsym.outermostClass(); - Env stEnv = enter.getEnv(c); - if (stEnv != null && env != stEnv) - externalSupers.add(st.tsym); - } - super.visitClassDef(node); - } - } - ScanNested scanner = new ScanNested(); - scanner.scan(env.tree); - if (scanner.externalSupers.isEmpty()) - return false; - if (!deferredSugar.add(env) && devVerbose) { - throw new AssertionError(env.enclClass.sym + " was deferred, " + - "second time has these external super types " + - scanner.externalSupers); - } - return true; - } - /** Generates the source or class file for a list of classes. * The decision to generate a source file or a class file is * based upon the compiler's options.