diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java index d4dff8c3d349..139b2c4cd953 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/StackSlotLimitTest.java @@ -99,10 +99,7 @@ public static boolean testSnippet1() { @Test public void test1() { - // OptionValues options = new OptionValues(getInitialOptions(), HighTier.Options.Inline, - // false); - OptionValues options = getInitialOptions(); - test(options, "testSnippet1"); + test("testSnippet1"); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/ObjdumpDisassemblerProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/ObjdumpDisassemblerProvider.java index d6cc6d4ed72a..3509a611668d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/ObjdumpDisassemblerProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/code/ObjdumpDisassemblerProvider.java @@ -36,6 +36,9 @@ import java.util.regex.Pattern; import jdk.graal.compiler.code.CompilationResult.CodeAnnotation; +import jdk.graal.compiler.core.common.NativeImageSupport; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionType; @@ -72,13 +75,14 @@ static class Options { } // cached validity of candidate objdump executables. - private Map<String, Boolean> objdumpCache = new HashMap<>(); + private static final Map<String, Boolean> objdumpCache = new HashMap<>(); private static Process createProcess(String[] cmd) { ProcessBuilder pb = new ProcessBuilder(cmd); try { return pb.start(); } catch (IOException e) { + TTY.printf("WARNING: Error executing '%s' (%s)%n", String.join(" ", cmd), e); } return null; } @@ -90,6 +94,9 @@ public boolean isAvailable(OptionValues options) { @Override public String disassembleCompiledCode(OptionValues options, CodeCacheProvider codeCache, CompilationResult compResult) { + if (NativeImageSupport.inRuntimeCode() && !ENABLE_OBJDUMP) { + throw new GraalError("Objdump not available"); + } String objdump = getObjdump(options); if (objdump == null) { return null; @@ -129,8 +136,7 @@ public String disassembleCompiledCode(OptionValues options, CodeCacheProvider co putAnnotation(annotations, a.getPosition(), a.toString()); } for (Infopoint infopoint : compResult.getInfopoints()) { - if (infopoint instanceof Call) { - Call call = (Call) infopoint; + if (infopoint instanceof Call call) { if (call.debugInfo != null) { putAnnotation(annotations, call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); } @@ -170,15 +176,14 @@ public String disassembleCompiledCode(OptionValues options, CodeCacheProvider co String errLine = ebr.readLine(); if (errLine != null) { System.err.println("Error output from executing: " + CollectionsUtil.mapAndJoin(cmdline, e -> quoteShellArg(String.valueOf(e)), " ")); - System.err.println(errLine); - while ((errLine = ebr.readLine()) != null) { + do { System.err.println(errLine); - } + } while ((errLine = ebr.readLine()) != null); } } return sb.toString(); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(TTY.out); return null; } finally { if (tmp != null) { @@ -188,9 +193,9 @@ public String disassembleCompiledCode(OptionValues options, CodeCacheProvider co } /** - * Pattern for a single shell command argument that does not need to quoted. + * Pattern for a single shell command argument that does not need to be quoted. */ - private static final Pattern SAFE_SHELL_ARG = Pattern.compile("[A-Za-z0-9@%_\\-\\+=:,\\./]+"); + private static final Pattern SAFE_SHELL_ARG = Pattern.compile("[A-Za-z0-9@%_\\-+=:,./]+"); /** * Reliably quote a string as a single shell command argument. @@ -207,52 +212,78 @@ public static String quoteShellArg(String arg) { return "'" + arg.replace("'", "'\"'\"'") + "'"; } + private static final String ENABLE_OBJDUMP_PROP = "debug.jdk.graal.enableObjdump"; + + /** + * Support for objdump is excluded by default from native images (including libgraal) to reduce + * the image size. It also reduces security concerns related to running subprocesses. + * + * To objdump during development, set the {@value #ENABLE_OBJDUMP_PROP} system property to true + * when building native images. + */ + private static final boolean ENABLE_OBJDUMP = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_OBJDUMP_PROP)); + + private static boolean objdumpUnsupportedWarned; + /** * Searches for a valid GNU objdump executable. */ - private String getObjdump(OptionValues options) { + private static String getObjdump(OptionValues options) { // for security, user must provide the possible objdump locations. String candidates = Options.ObjdumpExecutables.getValue(options); if (candidates != null && !candidates.isEmpty()) { + if (NativeImageSupport.inRuntimeCode() && !ENABLE_OBJDUMP) { + if (!objdumpUnsupportedWarned) { + // Ignore races or multiple isolates - an extra warning is ok + objdumpUnsupportedWarned = true; + TTY.printf("WARNING: Objdump not supported as the %s system property was false when building.%n", + ENABLE_OBJDUMP_PROP); + } + return null; + } + for (String candidate : candidates.split(",")) { - // first checking to see if a cached verdict for this candidate exists. - Boolean cachedQuery = objdumpCache.get(candidate); - if (cachedQuery != null) { - if (cachedQuery.booleanValue()) { - return candidate; - } else { - // this candidate was previously determined to not be acceptable. - continue; + synchronized (objdumpCache) { + // first checking to see if a cached verdict for this candidate exists. + Boolean cachedQuery = objdumpCache.get(candidate); + if (cachedQuery != null) { + if (cachedQuery) { + return candidate; + } else { + // this candidate was previously determined to not be acceptable. + continue; + } } - } - try { String[] cmd = {candidate, "--version"}; - Process proc = createProcess(cmd); - if (proc == null) { - // bad candidate. - objdumpCache.put(candidate, Boolean.FALSE); - return null; - } - InputStream is = proc.getInputStream(); - int exitValue = proc.waitFor(); - if (exitValue == 0) { - byte[] buf = new byte[is.available()]; - int pos = 0; - while (pos < buf.length) { - int read = is.read(buf, pos, buf.length - pos); - pos += read; + try { + Process proc = createProcess(cmd); + if (proc == null) { + // bad candidate. + objdumpCache.put(candidate, Boolean.FALSE); + return null; } - String output = new String(buf); - if (output.contains("GNU objdump")) { - // this candidate meets the criteria. - objdumpCache.put(candidate, Boolean.TRUE); - return candidate; + InputStream is = proc.getInputStream(); + int exitValue = proc.waitFor(); + if (exitValue == 0) { + byte[] buf = new byte[is.available()]; + int pos = 0; + while (pos < buf.length) { + int read = is.read(buf, pos, buf.length - pos); + pos += read; + } + String output = new String(buf); + if (output.contains("GNU objdump")) { + // this candidate meets the criteria. + objdumpCache.put(candidate, Boolean.TRUE); + return candidate; + } } + } catch (IOException | InterruptedException e) { + TTY.printf("WARNING: Error reading input from '%s' (%s)%n", String.join(" ", cmd), e); } - } catch (IOException | InterruptedException e) { + // bad candidate. + objdumpCache.put(candidate, Boolean.FALSE); } - // bad candidate. - objdumpCache.put(candidate, Boolean.FALSE); } } return null; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java index 03788e05da65..ca74304d89a2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/IgvDumpChannel.java @@ -50,12 +50,12 @@ final class IgvDumpChannel implements WritableByteChannel { private static final String ENABLE_NETWORK_DUMPING_PROP = "debug.jdk.graal.enableNetworkDumping"; /** - * Support for IGV dumping to a network port is excluded by default from libgraal to reduce the - * libgraal image size. It also reduces security concerns related to opening random network - * connections. + * Support for IGV dumping to a network port is excluded by default from native images + * (including libgraal) to reduce the image size. It also reduces security concerns related to + * opening random network connections. * - * To enable IGV dumping to the network during libgraal based development, set the - * {@value #ENABLE_NETWORK_DUMPING_PROP} system property to true when building libgraal. + * To enable IGV dumping to the network during development, set the + * {@value #ENABLE_NETWORK_DUMPING_PROP} system property to true when building native images. */ private static final boolean ENABLE_NETWORK_DUMPING = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_NETWORK_DUMPING_PROP)); @@ -107,7 +107,7 @@ WritableByteChannel channel() throws IOException { if (!networkDumpingUnsupportedWarned) { // Ignore races or multiple isolates - an extra warning is ok networkDumpingUnsupportedWarned = true; - TTY.printf("WARNING: Graph dumping to network not supported as the %s system property was false when building libgraal - dumping to file instead.%n", + TTY.printf("WARNING: Graph dumping to network not supported as the %s system property was false when building - dumping to file instead.%n", ENABLE_NETWORK_DUMPING_PROP); } sharedChannel = createFileChannel(pathProvider, null); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java index e1aa5bf8fc82..f205890a1d05 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/GraalServices.java @@ -94,10 +94,30 @@ private static void addProviders(String arch, Class<?> service) { // Skip provider for another architecture continue; } + if (provider.getClass().getAnnotation(LibGraalSupport.HostedOnly.class) != null) { + // Skip hosted-only providers + continue; + } providers.add(provider); } } + /** + * Determines if {@code c} is annotated by {@link LibGraalService}. + */ + static boolean isLibGraalService(Class<?> c) { + if (c != null && c.getAnnotation(LibGraalService.class) != null) { + if (c.getAnnotation(LibGraalSupport.HostedOnly.class) != null) { + throw new GraalError("Class %s cannot be annotated by both %s and %s as they are mutually exclusive)", + c.getName(), + LibGraalService.class.getName(), + LibGraalSupport.HostedOnly.class.getName()); + } + return true; + } + return false; + } + static { LibGraalSupport libgraal = LibGraalSupport.INSTANCE; if (libgraal != null) { @@ -105,7 +125,7 @@ private static void addProviders(String arch, Class<?> service) { String arch = getJVMCIArch(); libgraal.getClassModuleMap().keySet().stream()// .map(GraalServices::loadClassOrNull)// - .filter(c -> c != null && c.getAnnotation(LibGraalService.class) != null)// + .filter(GraalServices::isLibGraalService)// .forEach(service -> addProviders(arch, service)); } else { libgraalServices = null;