src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java
changeset 51736 42d99cb7f50f
parent 51436 091c0d22e735
child 52578 7dd81e82d083
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Fri Sep 14 13:18:52 2018 +0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Sep 13 22:45:12 2018 -0700
@@ -41,6 +41,7 @@
 import java.io.PrintStream;
 import java.util.Map;
 
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.PathUtilities;
@@ -181,15 +182,64 @@
                 actionKey = CompilationFailureAction;
                 causeType = "failure";
             }
-            ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
+            synchronized (CompilationFailureAction) {
+                // Serialize all compilation failure handling.
+                // This prevents retry compilation storms and interleaving
+                // of compilation exception messages.
+                // It also allows for reliable testing of CompilationWrapper
+                // by avoiding a race whereby retry compilation output from a
+                // forced crash (i.e., use of GraalCompilerOptions.CrashAt)
+                // is truncated.
 
-            action = adjustAction(initialOptions, actionKey, action);
+                ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
+
+                action = adjustAction(initialOptions, actionKey, action);
+
+                if (action == ExceptionAction.Silent) {
+                    return handleException(cause);
+                }
 
-            if (action == ExceptionAction.Silent) {
-                return handleException(cause);
-            }
+                if (action == ExceptionAction.Print) {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    try (PrintStream ps = new PrintStream(baos)) {
+                        ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
+                        cause.printStackTrace(ps);
+                        ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                        causeType,
+                                        actionKey.getName(), ExceptionAction.Silent,
+                                        actionKey.getName(), ExceptionAction.Silent);
+                        ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
+                                        "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
+                                        causeType,
+                                        actionKey.getName(), ExceptionAction.Diagnose,
+                                        ExceptionAction.ExitVM,
+                                        actionKey.getName(), ExceptionAction.Diagnose);
+                    }
+                    TTY.print(baos.toString());
+                    return handleException(cause);
+                }
 
-            if (action == ExceptionAction.Print) {
+                // action is Diagnose or ExitVM
+
+                if (Dump.hasBeenSet(initialOptions)) {
+                    // If dumping is explicitly enabled, Graal is being debugged
+                    // so don't interfere with what the user is expecting to see.
+                    return handleException(cause);
+                }
+
+                String dir = this.outputDirectory.getPath();
+                if (dir == null) {
+                    return handleException(cause);
+                }
+                String dumpName = PathUtilities.sanitizeFileName(toString());
+                File dumpPath = new File(dir, dumpName);
+                dumpPath.mkdirs();
+                if (!dumpPath.exists()) {
+                    TTY.println("Warning: could not create diagnostics directory " + dumpPath);
+                    return handleException(cause);
+                }
+
+                String message;
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 try (PrintStream ps = new PrintStream(baos)) {
                     ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
@@ -198,63 +248,16 @@
                                     causeType,
                                     actionKey.getName(), ExceptionAction.Silent,
                                     actionKey.getName(), ExceptionAction.Silent);
-                    ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
-                                    "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
+                    ps.printf("To print a message for a compilation %s without retrying the compilation, " +
+                                    "set %s to %s (e.g., -Dgraal.%s=%s).%n",
                                     causeType,
-                                    actionKey.getName(), ExceptionAction.Diagnose,
-                                    ExceptionAction.ExitVM,
-                                    actionKey.getName(), ExceptionAction.Diagnose);
+                                    actionKey.getName(), ExceptionAction.Print,
+                                    actionKey.getName(), ExceptionAction.Print);
+                    ps.println("Retrying compilation of " + this);
+                    message = baos.toString();
                 }
-                synchronized (CompilationFailureAction) {
-                    // Synchronize to prevent compilation exception
-                    // messages from interleaving.
-                    TTY.println(baos.toString());
-                }
-                return handleException(cause);
-            }
-
-            // action is Diagnose or ExitVM
-
-            if (Dump.hasBeenSet(initialOptions)) {
-                // If dumping is explicitly enabled, Graal is being debugged
-                // so don't interfere with what the user is expecting to see.
-                return handleException(cause);
-            }
 
-            String dir = this.outputDirectory.getPath();
-            if (dir == null) {
-                return handleException(cause);
-            }
-            String dumpName = PathUtilities.sanitizeFileName(toString());
-            File dumpPath = new File(dir, dumpName);
-            dumpPath.mkdirs();
-            if (!dumpPath.exists()) {
-                TTY.println("Warning: could not create diagnostics directory " + dumpPath);
-                return handleException(cause);
-            }
-
-            String message;
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            try (PrintStream ps = new PrintStream(baos)) {
-                ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
-                cause.printStackTrace(ps);
-                ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                causeType,
-                                actionKey.getName(), ExceptionAction.Silent,
-                                actionKey.getName(), ExceptionAction.Silent);
-                ps.printf("To print a message for a compilation %s without retrying the compilation, " +
-                                "set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                causeType,
-                                actionKey.getName(), ExceptionAction.Print,
-                                actionKey.getName(), ExceptionAction.Print);
-                ps.println("Retrying compilation of " + this);
-                message = baos.toString();
-            }
-
-            synchronized (CompilationFailureAction) {
-                // Synchronize here to serialize retry compilations. This
-                // mitigates retry compilation storms.
-                TTY.println(message);
+                TTY.print(message);
                 File retryLogFile = new File(dumpPath, "retry.log");
                 try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
                     ps.print(message);
@@ -267,7 +270,7 @@
                                 MethodFilter, null,
                                 DumpPath, dumpPath.getPath());
 
-                try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) {
+                try (DebugContext retryDebug = createRetryDebugContext(retryOptions); DebugCloseable s = retryDebug.disableIntercept()) {
                     T res = performCompilation(retryDebug);
                     maybeExitVM(action);
                     return res;
@@ -283,16 +286,8 @@
 
     private void maybeExitVM(ExceptionAction action) {
         if (action == ExitVM) {
-            synchronized (ExceptionAction.class) {
-                try {
-                    // Give other compiler threads a chance to flush
-                    // error handling output.
-                    ExceptionAction.class.wait(2000);
-                } catch (InterruptedException e) {
-                }
-                TTY.println("Exiting VM after retry compilation of " + this);
-                System.exit(-1);
-            }
+            TTY.println("Exiting VM after retry compilation of " + this);
+            System.exit(-1);
         }
     }
 
@@ -303,22 +298,24 @@
     private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
         ExceptionAction action = initialAction;
         int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
-        synchronized (problemsHandledPerAction) {
-            while (action != ExceptionAction.Silent) {
-                int problems = problemsHandledPerAction.getOrDefault(action, 0);
-                if (problems >= maxProblems) {
-                    if (problems == maxProblems) {
-                        TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
-                                        MaxCompilationProblemsPerAction, maxProblems);
-                        // Ensure that the message above is only printed once
-                        problemsHandledPerAction.put(action, problems + 1);
+        if (action != ExceptionAction.ExitVM) {
+            synchronized (problemsHandledPerAction) {
+                while (action != ExceptionAction.Silent) {
+                    int problems = problemsHandledPerAction.getOrDefault(action, 0);
+                    if (problems >= maxProblems) {
+                        if (problems == maxProblems) {
+                            TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
+                                            MaxCompilationProblemsPerAction, maxProblems);
+                            // Ensure that the message above is only printed once
+                            problemsHandledPerAction.put(action, problems + 1);
+                        }
+                        action = action.quieter();
+                    } else {
+                        break;
                     }
-                    action = action.quieter();
-                } else {
-                    break;
                 }
+                problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
             }
-            problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
         }
         return action;
     }