1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot; 24 25 import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL; 26 import static org.graalvm.compiler.debug.DebugOptions.Dump; 27 import static org.graalvm.compiler.debug.DebugOptions.DumpPath; 28 import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; 29 30 import java.io.ByteArrayOutputStream; 31 import java.io.File; 32 import java.io.FileNotFoundException; 33 import java.io.FileOutputStream; 34 import java.io.PrintStream; 35 36 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 37 import org.graalvm.compiler.debug.DebugContext; 38 import org.graalvm.compiler.debug.DebugRetryableTask; 39 import org.graalvm.compiler.debug.TTY; 40 import org.graalvm.compiler.options.OptionValues; 41 import org.graalvm.compiler.printer.GraalDebugHandlersFactory; 42 43 import jdk.vm.ci.code.BailoutException; 44 45 /** 46 * Utility for retrying a compilation that throws an exception where the retry enables extra logging 47 * for subsequently diagnosing the failure. 48 */ 49 public abstract class HotSpotRetryableCompilation<T> extends DebugRetryableTask<T> { 50 51 protected final HotSpotGraalRuntimeProvider runtime; 52 53 public HotSpotRetryableCompilation(HotSpotGraalRuntimeProvider runtime) { 54 this.runtime = runtime; 55 } 56 57 /** 58 * Gets a value that represents the compilation unit being compiled. 59 */ 60 @Override 61 public abstract String toString(); 62 63 @Override 64 protected DebugContext getRetryContext(DebugContext initialDebug, Throwable t) { 65 if (t instanceof BailoutException) { 66 return null; 67 } 68 69 OptionValues initialOptions = initialDebug.getOptions(); 70 if (Dump.hasBeenSet(initialOptions)) { 71 // If dumping is explicitly enabled, Graal is being debugged 72 // so don't interfere with what the user is expecting to see. 73 return null; 74 } 75 76 String outputDirectory = runtime.getOutputDirectory(); 77 if (outputDirectory == null) { 78 return null; 79 } 80 String dumpName = GraalDebugHandlersFactory.sanitizedFileName(toString()); 81 File dumpPath = new File(outputDirectory, dumpName); 82 dumpPath.mkdirs(); 83 if (!dumpPath.exists()) { 84 TTY.println("Warning: could not create dump directory " + dumpPath); 85 return null; 86 } 87 88 TTY.println("Retrying compilation of " + this + " due to " + t); 89 retryLogPath = new File(dumpPath, "retry.log").getPath(); 90 log("Exception causing retry", t); 91 OptionValues retryOptions = new OptionValues(initialOptions, 92 Dump, ":" + VERBOSE_LEVEL, 93 MethodFilter, null, 94 DumpPath, dumpPath.getPath()); 95 SnippetReflectionProvider snippetReflection = runtime.getHostProviders().getSnippetReflection(); 96 return DebugContext.create(retryOptions, new GraalDebugHandlersFactory(snippetReflection)); 97 } 98 99 private String retryLogPath; 100 101 /** 102 * Prints a message to a retry log file. 103 * 104 * @param message the message to print 105 * @param t if non-{@code null}, the stack trace for this exception is written to the retry log 106 * after {@code message} 107 */ 108 protected void log(String message, Throwable t) { 109 if (retryLogPath != null) { 110 try (PrintStream retryLog = new PrintStream(new FileOutputStream(retryLogPath), true)) { 111 StringBuilder buf = new StringBuilder(Thread.currentThread() + ": " + message); 112 if (t != null) { 113 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 114 t.printStackTrace(new PrintStream(baos)); 115 buf.append(System.lineSeparator()).append(baos.toString()); 116 } 117 retryLog.println(buf); 118 } catch (FileNotFoundException e) { 119 TTY.println("Warning: could not open retry log file " + retryLogPath + " [" + e + "]"); 120 } 121 } 122 } 123 }