< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java

Print this page
rev 52509 : [mq]: graal


  24 
  25 package org.graalvm.compiler.core;
  26 
  27 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
  28 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
  29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
  30 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
  31 import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
  32 import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
  33 import static org.graalvm.compiler.debug.DebugOptions.Dump;
  34 import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
  35 import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
  36 
  37 import java.io.ByteArrayOutputStream;
  38 import java.io.File;
  39 import java.io.FileOutputStream;
  40 import java.io.IOException;
  41 import java.io.PrintStream;
  42 import java.util.Map;
  43 
  44 import org.graalvm.compiler.debug.DebugCloseable;
  45 import org.graalvm.compiler.debug.DebugContext;
  46 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
  47 import org.graalvm.compiler.debug.PathUtilities;
  48 import org.graalvm.compiler.debug.TTY;
  49 import org.graalvm.compiler.options.EnumOptionKey;
  50 import org.graalvm.compiler.options.OptionValues;
  51 
  52 import jdk.vm.ci.code.BailoutException;
  53 
  54 /**
  55  * Wrapper for a compilation that centralizes what action to take based on
  56  * {@link GraalCompilerOptions#CompilationBailoutAction} and
  57  * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
  58  * compilation.
  59  */
  60 public abstract class CompilationWrapper<T> {
  61 
  62     /**
  63      * Actions to take upon an exception being raised during compilation performed via
  64      * {@link CompilationWrapper}. The actions are with respect to what the user sees on the


 146         return actionKey.getValue(options);
 147     }
 148 
 149     /**
 150      * Perform the compilation wrapped by this object.
 151      *
 152      * @param debug the debug context to use for the compilation
 153      */
 154     protected abstract T performCompilation(DebugContext debug);
 155 
 156     /**
 157      * Gets a value that represents the input to the compilation.
 158      */
 159     @Override
 160     public abstract String toString();
 161 
 162     /**
 163      * Creates the {@link DebugContext} to use when retrying a compilation.
 164      *
 165      * @param options the options for configuring the debug context

 166      */
 167     protected abstract DebugContext createRetryDebugContext(OptionValues options);
 168 
 169     @SuppressWarnings("try")
 170     public final T run(DebugContext initialDebug) {
 171         try {
 172             return performCompilation(initialDebug);
 173         } catch (Throwable cause) {
 174             OptionValues initialOptions = initialDebug.getOptions();
 175 
 176             String causeType = "failure";
 177             EnumOptionKey<ExceptionAction> actionKey;
 178             if (cause instanceof BailoutException) {
 179                 actionKey = CompilationBailoutAction;
 180                 causeType = "bailout";
 181             } else {
 182                 actionKey = CompilationFailureAction;
 183                 causeType = "failure";
 184             }
 185             synchronized (CompilationFailureAction) {
 186                 // Serialize all compilation failure handling.
 187                 // This prevents retry compilation storms and interleaving


 210                                         actionKey.getName(), ExceptionAction.Silent);
 211                         ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
 212                                         "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
 213                                         causeType,
 214                                         actionKey.getName(), ExceptionAction.Diagnose,
 215                                         ExceptionAction.ExitVM,
 216                                         actionKey.getName(), ExceptionAction.Diagnose);
 217                     }
 218                     TTY.print(baos.toString());
 219                     return handleException(cause);
 220                 }
 221 
 222                 // action is Diagnose or ExitVM
 223 
 224                 if (Dump.hasBeenSet(initialOptions)) {
 225                     // If dumping is explicitly enabled, Graal is being debugged
 226                     // so don't interfere with what the user is expecting to see.
 227                     return handleException(cause);
 228                 }
 229 


 230                 String dir = this.outputDirectory.getPath();
 231                 if (dir == null) {
 232                     return handleException(cause);
 233                 }
 234                 String dumpName = PathUtilities.sanitizeFileName(toString());
 235                 File dumpPath = new File(dir, dumpName);
 236                 dumpPath.mkdirs();
 237                 if (!dumpPath.exists()) {
 238                     TTY.println("Warning: could not create diagnostics directory " + dumpPath);
 239                     return handleException(cause);





 240                 }
 241 
 242                 String message;
 243                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 244                 try (PrintStream ps = new PrintStream(baos)) {
 245                     ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
 246                     cause.printStackTrace(ps);
 247                     ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
 248                                     causeType,
 249                                     actionKey.getName(), ExceptionAction.Silent,
 250                                     actionKey.getName(), ExceptionAction.Silent);
 251                     ps.printf("To print a message for a compilation %s without retrying the compilation, " +
 252                                     "set %s to %s (e.g., -Dgraal.%s=%s).%n",
 253                                     causeType,
 254                                     actionKey.getName(), ExceptionAction.Print,
 255                                     actionKey.getName(), ExceptionAction.Print);

 256                     ps.println("Retrying compilation of " + this);



 257                     message = baos.toString();
 258                 }
 259 
 260                 TTY.print(message);




 261                 File retryLogFile = new File(dumpPath, "retry.log");
 262                 try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
 263                     ps.print(message);
 264                 } catch (IOException ioe) {
 265                     TTY.printf("Error writing to %s: %s%n", retryLogFile, ioe);
 266                 }
 267 
 268                 OptionValues retryOptions = new OptionValues(initialOptions,
 269                                 Dump, ":" + VERBOSE_LEVEL,
 270                                 MethodFilter, null,
 271                                 DumpPath, dumpPath.getPath());
 272 
 273                 try (DebugContext retryDebug = createRetryDebugContext(retryOptions); DebugCloseable s = retryDebug.disableIntercept()) {


 274                     T res = performCompilation(retryDebug);

 275                     maybeExitVM(action);
 276                     return res;
 277                 } catch (Throwable ignore) {


 278                     // Failures during retry are silent
 279                     T res = handleException(cause);
 280                     maybeExitVM(action);
 281                     return res;







 282                 }
 283             }
 284         }
 285     }
 286 
 287     private void maybeExitVM(ExceptionAction action) {
 288         if (action == ExitVM) {
 289             TTY.println("Exiting VM after retry compilation of " + this);
 290             System.exit(-1);
 291         }
 292     }
 293 
 294     /**
 295      * Adjusts {@code initialAction} if necessary based on
 296      * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
 297      */
 298     private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
 299         ExceptionAction action = initialAction;
 300         int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
 301         if (action != ExceptionAction.ExitVM) {




  24 
  25 package org.graalvm.compiler.core;
  26 
  27 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
  28 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
  29 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
  30 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
  31 import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
  32 import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
  33 import static org.graalvm.compiler.debug.DebugOptions.Dump;
  34 import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
  35 import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
  36 
  37 import java.io.ByteArrayOutputStream;
  38 import java.io.File;
  39 import java.io.FileOutputStream;
  40 import java.io.IOException;
  41 import java.io.PrintStream;
  42 import java.util.Map;
  43 

  44 import org.graalvm.compiler.debug.DebugContext;
  45 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
  46 import org.graalvm.compiler.debug.PathUtilities;
  47 import org.graalvm.compiler.debug.TTY;
  48 import org.graalvm.compiler.options.EnumOptionKey;
  49 import org.graalvm.compiler.options.OptionValues;
  50 
  51 import jdk.vm.ci.code.BailoutException;
  52 
  53 /**
  54  * Wrapper for a compilation that centralizes what action to take based on
  55  * {@link GraalCompilerOptions#CompilationBailoutAction} and
  56  * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
  57  * compilation.
  58  */
  59 public abstract class CompilationWrapper<T> {
  60 
  61     /**
  62      * Actions to take upon an exception being raised during compilation performed via
  63      * {@link CompilationWrapper}. The actions are with respect to what the user sees on the


 145         return actionKey.getValue(options);
 146     }
 147 
 148     /**
 149      * Perform the compilation wrapped by this object.
 150      *
 151      * @param debug the debug context to use for the compilation
 152      */
 153     protected abstract T performCompilation(DebugContext debug);
 154 
 155     /**
 156      * Gets a value that represents the input to the compilation.
 157      */
 158     @Override
 159     public abstract String toString();
 160 
 161     /**
 162      * Creates the {@link DebugContext} to use when retrying a compilation.
 163      *
 164      * @param options the options for configuring the debug context
 165      * @param logStream the log stream to use in the debug context
 166      */
 167     protected abstract DebugContext createRetryDebugContext(OptionValues options, PrintStream logStream);
 168 
 169     @SuppressWarnings("try")
 170     public final T run(DebugContext initialDebug) {
 171         try {
 172             return performCompilation(initialDebug);
 173         } catch (Throwable cause) {
 174             OptionValues initialOptions = initialDebug.getOptions();
 175 
 176             String causeType = "failure";
 177             EnumOptionKey<ExceptionAction> actionKey;
 178             if (cause instanceof BailoutException) {
 179                 actionKey = CompilationBailoutAction;
 180                 causeType = "bailout";
 181             } else {
 182                 actionKey = CompilationFailureAction;
 183                 causeType = "failure";
 184             }
 185             synchronized (CompilationFailureAction) {
 186                 // Serialize all compilation failure handling.
 187                 // This prevents retry compilation storms and interleaving


 210                                         actionKey.getName(), ExceptionAction.Silent);
 211                         ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
 212                                         "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
 213                                         causeType,
 214                                         actionKey.getName(), ExceptionAction.Diagnose,
 215                                         ExceptionAction.ExitVM,
 216                                         actionKey.getName(), ExceptionAction.Diagnose);
 217                     }
 218                     TTY.print(baos.toString());
 219                     return handleException(cause);
 220                 }
 221 
 222                 // action is Diagnose or ExitVM
 223 
 224                 if (Dump.hasBeenSet(initialOptions)) {
 225                     // If dumping is explicitly enabled, Graal is being debugged
 226                     // so don't interfere with what the user is expecting to see.
 227                     return handleException(cause);
 228                 }
 229 
 230                 File dumpPath = null;
 231                 try {
 232                     String dir = this.outputDirectory.getPath();
 233                     if (dir != null) {


 234                         String dumpName = PathUtilities.sanitizeFileName(toString());
 235                         dumpPath = new File(dir, dumpName);
 236                         dumpPath.mkdirs();
 237                         if (!dumpPath.exists()) {
 238                             TTY.println("Warning: could not create diagnostics directory " + dumpPath);
 239                             dumpPath = null;
 240                         }
 241                     }
 242                 } catch (Throwable t) {
 243                     TTY.println("Warning: could not create Graal diagnostic directory");
 244                     t.printStackTrace(TTY.out);
 245                 }
 246 
 247                 String message;
 248                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 249                 try (PrintStream ps = new PrintStream(baos)) {
 250                     ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
 251                     cause.printStackTrace(ps);
 252                     ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
 253                                     causeType,
 254                                     actionKey.getName(), ExceptionAction.Silent,
 255                                     actionKey.getName(), ExceptionAction.Silent);
 256                     ps.printf("To print a message for a compilation %s without retrying the compilation, " +
 257                                     "set %s to %s (e.g., -Dgraal.%s=%s).%n",
 258                                     causeType,
 259                                     actionKey.getName(), ExceptionAction.Print,
 260                                     actionKey.getName(), ExceptionAction.Print);
 261                     if (dumpPath != null) {
 262                         ps.println("Retrying compilation of " + this);
 263                     } else {
 264                         ps.println("Not retrying compilation of " + this + " as the dump path could not be created.");
 265                     }
 266                     message = baos.toString();
 267                 }
 268 
 269                 TTY.print(message);
 270                 if (dumpPath == null) {
 271                     return handleException(cause);
 272                 }
 273 
 274                 File retryLogFile = new File(dumpPath, "retry.log");
 275                 try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
 276                     ps.print(message);
 277                 } catch (IOException ioe) {
 278                     TTY.printf("Error writing to %s: %s%n", retryLogFile, ioe);
 279                 }
 280 
 281                 OptionValues retryOptions = new OptionValues(initialOptions,
 282                                 Dump, ":" + VERBOSE_LEVEL,
 283                                 MethodFilter, null,
 284                                 DumpPath, dumpPath.getPath());
 285 
 286                 ByteArrayOutputStream logBaos = new ByteArrayOutputStream();
 287                 PrintStream ps = new PrintStream(logBaos);
 288                 try (DebugContext retryDebug = createRetryDebugContext(retryOptions, ps)) {
 289                     T res = performCompilation(retryDebug);
 290                     ps.println("There was no exception during retry.");
 291                     maybeExitVM(action);
 292                     return res;
 293                 } catch (Throwable e) {
 294                     ps.println("Exception during retry:");
 295                     e.printStackTrace(ps);
 296                     // Failures during retry are silent
 297                     T res = handleException(cause);
 298                     maybeExitVM(action);
 299                     return res;
 300                 } finally {
 301                     ps.close();
 302                     try (FileOutputStream fos = new FileOutputStream(retryLogFile, true)) {
 303                         fos.write(logBaos.toByteArray());
 304                     } catch (Throwable e) {
 305                         TTY.printf("Error writing to %s: %s%n", retryLogFile, e);
 306                     }
 307                 }
 308             }
 309         }
 310     }
 311 
 312     private void maybeExitVM(ExceptionAction action) {
 313         if (action == ExitVM) {
 314             TTY.println("Exiting VM after retry compilation of " + this);
 315             System.exit(-1);
 316         }
 317     }
 318 
 319     /**
 320      * Adjusts {@code initialAction} if necessary based on
 321      * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
 322      */
 323     private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
 324         ExceptionAction action = initialAction;
 325         int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
 326         if (action != ExceptionAction.ExitVM) {


< prev index next >