6726015: JavaCompiler: replace desugarLater by compileStates

Reviewed-by: mcimadamore
This commit is contained in:
Jonathan Gibbons 2008-07-23 19:55:30 -07:00
parent f42262c039
commit f3eff961d3
2 changed files with 51 additions and 47 deletions

View File

@ -63,6 +63,7 @@ import static com.sun.tools.javac.util.ListBuffer.lb;
// 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 class JavaCompiler implements ClassReader.SourceCompleter {
*/
public Todo todo;
private Set<Env<AttrContext>> deferredSugar = new HashSet<Env<AttrContext>>();
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<Env<AttrContext>,CompileState> {
boolean isDone(Env<AttrContext> 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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
* @returns the attributed parse tree
*/
public Env<AttrContext> attribute(Env<AttrContext> 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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
if (errorCount() > 0)
return;
if (relax || deferredSugar.contains(env)) {
if (relax || compileStates.isDone(env, CompileState.FLOW)) {
results.append(env);
return;
}
@ -1109,6 +1132,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
* the current implicitSourcePolicy is taken into account.
* The preparation stops as soon as an error is found.
*/
protected void desugar(Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
if (errorCount() > 0)
return;
@ -1155,13 +1179,30 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
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<Env<AttrContext>> dependencies = new HashSet<Env<AttrContext>>();
public void visitClassDef(JCClassDecl node) {
Type st = types.supertype(node.sym.type);
if (st.tag == TypeTags.CLASS) {
ClassSymbol c = st.tsym.outermostClass();
Env<AttrContext> stEnv = enter.getEnv(c);
if (stEnv != null && env != stEnv)
dependencies.add(stEnv);
}
super.visitClassDef(node);
}
}
ScanNested scanner = new ScanNested();
scanner.scan(env.tree);
for (Env<AttrContext> dep: scanner.dependencies) {
if (!compileStates.isDone(dep, CompileState.FLOW))
flow(attribute(dep));
}
deferredSugar.remove(env);
if (verboseCompilePolicy)
log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]");
@ -1234,43 +1275,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
/**
* 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<AttrContext> env) {
if (compilePolicy == CompilePolicy.BY_FILE)
return false;
if (!devVerbose && deferredSugar.contains(env))
// guarantee that compiler terminates
return false;
class ScanNested extends TreeScanner {
Set<Symbol> externalSupers = new HashSet<Symbol>();
public void visitClassDef(JCClassDecl node) {
Type st = types.supertype(node.sym.type);
if (st.tag == TypeTags.CLASS) {
ClassSymbol c = st.tsym.outermostClass();
Env<AttrContext> 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.

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 6199662 6325201
* @bug 6199662 6325201 6726015
* @summary javac: compilation success depends on compilation order
*
* @compile Tree.java TreeScanner.java TreeInfo.java