--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/applications/ctw/Modules.java Thu Apr 13 11:23:37 2017 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from boot "modules" jimage -- lib/modules.
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver/timeout=0 sun.hotspot.tools.ctw.CtwRunner modules
+ */
+
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Thu Apr 13 09:42:10 2017 -0400
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Thu Apr 13 11:23:37 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,8 @@
Compiler.getMethodCount(),
System.currentTimeMillis() - start);
passed = true;
+ } catch (Throwable t){
+ t.printStackTrace(ERR);
} finally {
// <clinit> might have started new threads
System.exit(passed ? 0 : 1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Thu Apr 13 11:23:37 2017 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.hotspot.tools.ctw;
+
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.ProcessTools;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Runs CompileTheWorld for exact one target. If an error occurs during
+ * compilation of class N, this driver class saves error information and
+ * restarts CTW from class N + 1. All saved errors are reported at the end.
+ * <pre>
+ * Usage: <target to compile>
+ * </pre>
+ */
+public class CtwRunner {
+ private static final Predicate<String> IS_CLASS_LINE = Pattern.compile(
+ "^\\[\\d+\\]\\s*\\S+\\s*$").asPredicate();
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1) {
+ throw new Error("Usage: <artifact to compile>");
+ }
+ new CtwRunner(args[0]).run();
+ }
+
+ private final List<Throwable> errors;
+ private final Path targetPath;
+ private final String targetName;
+
+ private CtwRunner(String target) {
+ if (target.equals("modules")) {
+ targetPath = Paths
+ .get(Utils.TEST_JDK)
+ .resolve("lib")
+ .resolve(target);
+ } else {
+ targetPath = Paths.get(target).toAbsolutePath();
+ }
+ targetName = targetPath.getFileName().toString();
+ errors = new ArrayList<>();
+ }
+
+
+ private void run() {
+ startCtwforAllClasses();
+ if (!errors.isEmpty()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("There were ")
+ .append(errors.size())
+ .append(" errors:[");
+ System.err.println(sb.toString());
+ for (Throwable e : errors) {
+ sb.append("{")
+ .append(e.getMessage())
+ .append("}");
+ e.printStackTrace(System.err);
+ System.err.println();
+ }
+ sb.append("]");
+ throw new AssertionError(sb.toString());
+ }
+ }
+
+
+ private void startCtwforAllClasses() {
+ long classStart = 0;
+ boolean done = false;
+ while (!done) {
+ String[] cmd = cmd(classStart);
+ try {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ /* addTestVmAndJavaOptions = */ true,
+ cmd);
+ String commandLine = pb.command()
+ .stream()
+ .collect(Collectors.joining(" "));
+ String phase = phaseName(classStart);
+ Path out = Paths.get(".", phase + ".out");
+ System.out.printf("%s %dms START : [%s]%n" +
+ "cout/cerr are redirected to %s%n",
+ phase, TimeUnit.NANOSECONDS.toMillis(System.nanoTime()),
+ commandLine, out);
+ int exitCode = pb.redirectErrorStream(true)
+ .redirectOutput(out.toFile())
+ .start()
+ .waitFor();
+ System.out.printf("%s %dms END : exit code = %d%n",
+ phase, TimeUnit.NANOSECONDS.toMillis(System.nanoTime()),
+ exitCode);
+ long lastClassIndex = getLastClassIndex(out);
+ if (exitCode == 0) {
+ done = true;
+ } else {
+ if (lastClassIndex == 0) {
+ errors.add(new Error(phase + ": failed during preload"
+ + " with classStart = " + classStart));
+ // skip one class
+ ++classStart;
+ } else {
+ errors.add(new Error(phase + ": failed during"
+ + " compilation of class #" + lastClassIndex));
+ // continue with the next class
+ classStart = lastClassIndex + 1;
+ }
+ }
+ } catch (Exception e) {
+ throw new Error("failed to run from " + classStart, e);
+ }
+ }
+ }
+
+ private long getLastClassIndex(Path errFile) {
+ long result = 0;
+ try {
+ String line = Files.newBufferedReader(errFile)
+ .lines()
+ .filter(IS_CLASS_LINE)
+ .reduce((a, b) -> b).orElse(null);
+ if (line != null) {
+ int open = line.indexOf('[') + 1;
+ int close = line.indexOf(']');
+ result = Long.parseLong(line.substring(open, close));
+ }
+ } catch (IOException ioe) {
+ throw new Error("can not read " + errFile + " : "
+ + ioe.getMessage(), ioe);
+ }
+ return result;
+ }
+
+ private String[] cmd(long classStart) {
+ String phase = phaseName(classStart);
+ return new String[]{
+ "-Xbatch",
+ "-XX:-UseCounterDecay",
+ "-XX:-ShowMessageBoxOnError",
+ "-XX:+UnlockDiagnosticVMOptions",
+ // define phase start
+ "-DCompileTheWorldStartAt=" + classStart,
+ // CTW library uses WhiteBox API
+ "-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.",
+ // export jdk.internal packages used by CTW library
+ "--add-exports", "java.base/jdk.internal.jimage=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED",
+ // enable diagnostic logging
+ "-XX:+LogCompilation",
+ // use phase specific log and hs_err file
+ String.format("-XX:LogFile=hotspot_%s_%%p.log", phase),
+ String.format("-XX:ErrorFile=hs_err_%s_%%p.log", phase),
+ // MethodHandle MUST NOT be compiled
+ "-XX:CompileCommand=exclude,java/lang/invoke/MethodHandle.*",
+ // CTW entry point
+ CompileTheWorld.class.getName(),
+ targetPath.toString(),
+ };
+ }
+
+ private String phaseName(long classStart) {
+ return String.format("%s_%d", targetName, classStart);
+ }
+
+}