6726015: JavaCompiler: replace desugarLater by compileStates
authorjjg
Wed, 23 Jul 2008 19:55:30 -0700
changeset 936 1d395a623f16
parent 871 a9f1805e3ba9
child 937 457a11ae2e84
6726015: JavaCompiler: replace desugarLater by compileStates Reviewed-by: mcimadamore
langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
langtools/test/tools/javac/6199662/Tree.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<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 @@
      * @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 @@
                                   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<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 @@
             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);
+            }
         }
-        deferredSugar.remove(env);
+        ScanNested scanner = new ScanNested();
+        scanner.scan(env.tree);
+        for (Env<AttrContext> 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<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.
--- a/langtools/test/tools/javac/6199662/Tree.java	Wed Jul 05 16:39:28 2017 +0200
+++ b/langtools/test/tools/javac/6199662/Tree.java	Wed Jul 23 19:55:30 2008 -0700
@@ -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