8221118: Avoid eagerly creating JCDiagnostic for CompletionFailures
authorronsh
Fri, 29 Mar 2019 07:38:34 -0700
changeset 54339 f69a2f675f19
parent 54338 7a34a3270270
child 54340 2221f042556d
8221118: Avoid eagerly creating JCDiagnostic for CompletionFailures Reviewed-by: jjg, mcimadamore, forax
src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
test/langtools/tools/javac/defaultMethods/BadClassfile.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Tue Mar 26 12:12:49 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java	Fri Mar 29 07:38:34 2019 -0700
@@ -33,6 +33,7 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.function.Supplier;
 
 import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
@@ -222,7 +223,7 @@
         jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null;
 
         profile = Profile.instance(context);
-        cachedCompletionFailure = new CompletionFailure(null, (JCDiagnostic) null, dcfh);
+        cachedCompletionFailure = new CompletionFailure(null, () -> null, dcfh);
         cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
     }
 
@@ -298,9 +299,12 @@
             try {
                 fillIn(p);
             } catch (IOException ex) {
-                JCDiagnostic msg =
-                        diagFactory.fragment(Fragments.ExceptionMessage(ex.getLocalizedMessage()));
-                throw new CompletionFailure(sym, msg, dcfh).initCause(ex);
+                throw new CompletionFailure(
+                        sym,
+                        () -> diagFactory.fragment(
+                            Fragments.ExceptionMessage(ex.getLocalizedMessage())),
+                        dcfh)
+                    .initCause(ex);
             }
         }
         if (!reader.filling)
@@ -337,9 +341,8 @@
      */
     void fillIn(ClassSymbol c) {
         if (completionFailureName == c.fullname) {
-            JCDiagnostic msg =
-                    diagFactory.fragment(Fragments.UserSelectedCompletionFailure);
-            throw new CompletionFailure(c, msg, dcfh);
+            throw new CompletionFailure(
+                c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
         }
         currentOwner = c;
         JavaFileObject classfile = c.classfile;
@@ -390,16 +393,15 @@
     }
     // where
         private CompletionFailure classFileNotFound(ClassSymbol c) {
-            JCDiagnostic diag =
-                diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname));
-            return newCompletionFailure(c, diag);
+            return newCompletionFailure(
+                c, () -> diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname)));
         }
         /** Static factory for CompletionFailure objects.
          *  In practice, only one can be used at a time, so we share one
          *  to reduce the expense of allocating new exception objects.
          */
         private CompletionFailure newCompletionFailure(TypeSymbol c,
-                                                       JCDiagnostic diag) {
+                                                       Supplier<JCDiagnostic> diag) {
             if (!cacheCompletionFailure) {
                 // log.warning("proc.messager",
                 //             Log.getLocalizedString("class.file.not.found", c.flatname));
@@ -408,7 +410,7 @@
             } else {
                 CompletionFailure result = cachedCompletionFailure;
                 result.sym = c;
-                result.diag = diag;
+                result.resetDiagnostic(diag);
                 return result;
             }
         }
@@ -782,7 +784,7 @@
 
         public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
                 JCDiagnostic.Factory diagFactory, DeferredCompletionFailureHandler dcfh) {
-            super(sym, createBadClassFileDiagnostic(file, diag, diagFactory), dcfh);
+            super(sym, () -> createBadClassFileDiagnostic(file, diag, diagFactory), dcfh);
         }
         // where
         private static JCDiagnostic createBadClassFileDiagnostic(
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Mar 26 12:12:49 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Mar 29 07:38:34 2019 -0700
@@ -32,6 +32,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
+import java.util.function.Supplier;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
@@ -2131,26 +2132,31 @@
 
         /** A diagnostic object describing the failure
          */
-        public JCDiagnostic diag;
+        private JCDiagnostic diag;
 
-        public CompletionFailure(Symbol sym, JCDiagnostic diag, DeferredCompletionFailureHandler dcfh) {
+        private Supplier<JCDiagnostic> diagSupplier;
+
+        public CompletionFailure(Symbol sym, Supplier<JCDiagnostic> diagSupplier, DeferredCompletionFailureHandler dcfh) {
             this.dcfh = dcfh;
             this.sym = sym;
-            this.diag = diag;
+            this.diagSupplier = diagSupplier;
 //          this.printStackTrace();//DEBUG
         }
 
         public JCDiagnostic getDiagnostic() {
+            if (diag == null && diagSupplier != null) {
+                diag = diagSupplier.get();
+            }
             return diag;
         }
 
         @Override
         public String getMessage() {
-            return diag.getMessage(null);
+            return getDiagnostic().getMessage(null);
         }
 
         public JCDiagnostic getDetailValue() {
-            return diag;
+            return getDiagnostic();
         }
 
         @Override
@@ -2159,6 +2165,11 @@
             return this;
         }
 
+        public void resetDiagnostic(Supplier<JCDiagnostic> diagSupplier) {
+            this.diagSupplier = diagSupplier;
+            this.diag = null;
+        }
+
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Tue Mar 26 12:12:49 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Mar 29 07:38:34 2019 -0700
@@ -3079,7 +3079,7 @@
                 }
             } catch (Exception e) {
                 throw new CompletionFailure(sym,
-                                            ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())),
+                                            () -> ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())),
                                             dcfh);
             }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Tue Mar 26 12:12:49 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Mar 29 07:38:34 2019 -0700
@@ -805,9 +805,8 @@
      */
     public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
         if (completionFailureName == c.fullname) {
-            JCDiagnostic msg =
-                    diagFactory.fragment(Fragments.UserSelectedCompletionFailure);
-            throw new CompletionFailure(c, msg, dcfh);
+            throw new CompletionFailure(
+                c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
         }
         JavaFileObject filename = c.classfile;
         JavaFileObject prev = log.useSource(filename);
@@ -835,7 +834,7 @@
         // have enough modules available to access java.lang, and
         // so risk getting FatalError("no.java.lang") from MemberEnter.
         if (!modules.enter(List.of(tree), c)) {
-            throw new CompletionFailure(c, diags.fragment(Fragments.CantResolveModules), dcfh);
+            throw new CompletionFailure(c, () -> diags.fragment(Fragments.CantResolveModules), dcfh);
         }
 
         enter.complete(List.of(tree), c);
--- a/test/langtools/tools/javac/defaultMethods/BadClassfile.java	Tue Mar 26 12:12:49 2019 -0400
+++ b/test/langtools/tools/javac/defaultMethods/BadClassfile.java	Fri Mar 29 07:38:34 2019 -0700
@@ -79,7 +79,7 @@
 
             clazz.complete();
         } catch (BadClassFile f) {
-            JCDiagnostic embeddedDiag = (JCDiagnostic) f.diag.getArgs()[1];
+            JCDiagnostic embeddedDiag = (JCDiagnostic) f.getDiagnostic().getArgs()[1];
             assertEquals(expected, embeddedDiag.getCode());
             assertEquals(Integer.toString(Target.JDK1_7.majorVersion), embeddedDiag.getArgs()[0]);
             assertEquals(Integer.toString(Target.JDK1_7.minorVersion), embeddedDiag.getArgs()[1]);