8221118: Avoid eagerly creating JCDiagnostic for CompletionFailures

Reviewed-by: jjg, mcimadamore, forax
This commit is contained in:
Ron Shapiro 2019-03-29 07:38:34 -07:00
parent 4255a28d8d
commit b6cdfa908f
5 changed files with 36 additions and 24 deletions
src/jdk.compiler/share/classes/com/sun/tools/javac
test/langtools/tools/javac/defaultMethods

@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
import javax.tools.JavaFileManager; import javax.tools.JavaFileManager;
@ -222,7 +223,7 @@ public class ClassFinder {
jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null; jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null;
profile = Profile.instance(context); profile = Profile.instance(context);
cachedCompletionFailure = new CompletionFailure(null, (JCDiagnostic) null, dcfh); cachedCompletionFailure = new CompletionFailure(null, () -> null, dcfh);
cachedCompletionFailure.setStackTrace(new StackTraceElement[0]); cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
} }
@ -298,9 +299,12 @@ public class ClassFinder {
try { try {
fillIn(p); fillIn(p);
} catch (IOException ex) { } catch (IOException ex) {
JCDiagnostic msg = throw new CompletionFailure(
diagFactory.fragment(Fragments.ExceptionMessage(ex.getLocalizedMessage())); sym,
throw new CompletionFailure(sym, msg, dcfh).initCause(ex); () -> diagFactory.fragment(
Fragments.ExceptionMessage(ex.getLocalizedMessage())),
dcfh)
.initCause(ex);
} }
} }
if (!reader.filling) if (!reader.filling)
@ -337,9 +341,8 @@ public class ClassFinder {
*/ */
void fillIn(ClassSymbol c) { void fillIn(ClassSymbol c) {
if (completionFailureName == c.fullname) { if (completionFailureName == c.fullname) {
JCDiagnostic msg = throw new CompletionFailure(
diagFactory.fragment(Fragments.UserSelectedCompletionFailure); c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
throw new CompletionFailure(c, msg, dcfh);
} }
currentOwner = c; currentOwner = c;
JavaFileObject classfile = c.classfile; JavaFileObject classfile = c.classfile;
@ -390,16 +393,15 @@ public class ClassFinder {
} }
// where // where
private CompletionFailure classFileNotFound(ClassSymbol c) { private CompletionFailure classFileNotFound(ClassSymbol c) {
JCDiagnostic diag = return newCompletionFailure(
diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname)); c, () -> diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname)));
return newCompletionFailure(c, diag);
} }
/** Static factory for CompletionFailure objects. /** Static factory for CompletionFailure objects.
* In practice, only one can be used at a time, so we share one * In practice, only one can be used at a time, so we share one
* to reduce the expense of allocating new exception objects. * to reduce the expense of allocating new exception objects.
*/ */
private CompletionFailure newCompletionFailure(TypeSymbol c, private CompletionFailure newCompletionFailure(TypeSymbol c,
JCDiagnostic diag) { Supplier<JCDiagnostic> diag) {
if (!cacheCompletionFailure) { if (!cacheCompletionFailure) {
// log.warning("proc.messager", // log.warning("proc.messager",
// Log.getLocalizedString("class.file.not.found", c.flatname)); // Log.getLocalizedString("class.file.not.found", c.flatname));
@ -408,7 +410,7 @@ public class ClassFinder {
} else { } else {
CompletionFailure result = cachedCompletionFailure; CompletionFailure result = cachedCompletionFailure;
result.sym = c; result.sym = c;
result.diag = diag; result.resetDiagnostic(diag);
return result; return result;
} }
} }
@ -782,7 +784,7 @@ public class ClassFinder {
public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag, public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
JCDiagnostic.Factory diagFactory, DeferredCompletionFailureHandler dcfh) { JCDiagnostic.Factory diagFactory, DeferredCompletionFailureHandler dcfh) {
super(sym, createBadClassFileDiagnostic(file, diag, diagFactory), dcfh); super(sym, () -> createBadClassFileDiagnostic(file, diag, diagFactory), dcfh);
} }
// where // where
private static JCDiagnostic createBadClassFileDiagnostic( private static JCDiagnostic createBadClassFileDiagnostic(

@ -32,6 +32,7 @@ import java.util.EnumSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.function.Supplier;
import javax.lang.model.element.Element; import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind; import javax.lang.model.element.ElementKind;
@ -2131,26 +2132,31 @@ public abstract class Symbol extends AnnoConstruct implements Element {
/** A diagnostic object describing the failure /** 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.dcfh = dcfh;
this.sym = sym; this.sym = sym;
this.diag = diag; this.diagSupplier = diagSupplier;
// this.printStackTrace();//DEBUG // this.printStackTrace();//DEBUG
} }
public JCDiagnostic getDiagnostic() { public JCDiagnostic getDiagnostic() {
if (diag == null && diagSupplier != null) {
diag = diagSupplier.get();
}
return diag; return diag;
} }
@Override @Override
public String getMessage() { public String getMessage() {
return diag.getMessage(null); return getDiagnostic().getMessage(null);
} }
public JCDiagnostic getDetailValue() { public JCDiagnostic getDetailValue() {
return diag; return getDiagnostic();
} }
@Override @Override
@ -2159,6 +2165,11 @@ public abstract class Symbol extends AnnoConstruct implements Element {
return this; return this;
} }
public void resetDiagnostic(Supplier<JCDiagnostic> diagSupplier) {
this.diagSupplier = diagSupplier;
this.diag = null;
}
} }
/** /**

@ -3079,7 +3079,7 @@ public class ClassReader {
} }
} catch (Exception e) { } catch (Exception e) {
throw new CompletionFailure(sym, throw new CompletionFailure(sym,
ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())), () -> ClassReader.this.diagFactory.fragment(Fragments.ExceptionMessage(e.getMessage())),
dcfh); dcfh);
} }

@ -805,9 +805,8 @@ public class JavaCompiler {
*/ */
public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure { public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
if (completionFailureName == c.fullname) { if (completionFailureName == c.fullname) {
JCDiagnostic msg = throw new CompletionFailure(
diagFactory.fragment(Fragments.UserSelectedCompletionFailure); c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
throw new CompletionFailure(c, msg, dcfh);
} }
JavaFileObject filename = c.classfile; JavaFileObject filename = c.classfile;
JavaFileObject prev = log.useSource(filename); JavaFileObject prev = log.useSource(filename);
@ -835,7 +834,7 @@ public class JavaCompiler {
// have enough modules available to access java.lang, and // have enough modules available to access java.lang, and
// so risk getting FatalError("no.java.lang") from MemberEnter. // so risk getting FatalError("no.java.lang") from MemberEnter.
if (!modules.enter(List.of(tree), c)) { 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); enter.complete(List.of(tree), c);

@ -79,7 +79,7 @@ public class BadClassfile {
clazz.complete(); clazz.complete();
} catch (BadClassFile f) { } catch (BadClassFile f) {
JCDiagnostic embeddedDiag = (JCDiagnostic) f.diag.getArgs()[1]; JCDiagnostic embeddedDiag = (JCDiagnostic) f.getDiagnostic().getArgs()[1];
assertEquals(expected, embeddedDiag.getCode()); assertEquals(expected, embeddedDiag.getCode());
assertEquals(Integer.toString(Target.JDK1_7.majorVersion), embeddedDiag.getArgs()[0]); assertEquals(Integer.toString(Target.JDK1_7.majorVersion), embeddedDiag.getArgs()[0]);
assertEquals(Integer.toString(Target.JDK1_7.minorVersion), embeddedDiag.getArgs()[1]); assertEquals(Integer.toString(Target.JDK1_7.minorVersion), embeddedDiag.getArgs()[1]);