8143081: [ctw] Test CompileTheWorld.java needs to be updated for Jigsaw
authortpivovarova
Tue, 28 Jun 2016 19:58:15 +0300
changeset 40033 dbd5f9838049
parent 40032 bc2e42cd23ea
child 40035 bae79d28e9b1
8143081: [ctw] Test CompileTheWorld.java needs to be updated for Jigsaw Reviewed-by: iignatyev
hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java
hotspot/test/testlibrary/ctw/Makefile
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java
hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java	Tue Jun 28 19:58:15 2016 +0300
@@ -28,6 +28,8 @@
 import sun.hotspot.code.NMethod;
 import sun.hotspot.cpuinfo.CPUInfo;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.util.concurrent.Callable;
--- a/hotspot/test/testlibrary/ctw/Makefile	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/Makefile	Tue Jun 28 19:58:15 2016 +0300
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2016. 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
@@ -35,12 +35,13 @@
 SRC_DIR = src
 BUILD_DIR = build
 OUTPUT_DIR = $(BUILD_DIR)/classes
-WHITEBOX_DIR = ../whitebox
+TESTLIBRARY_DIR = ../../../../test/lib
 
 JAVAC = $(JDK_HOME)/bin/javac
 JAR = $(JDK_HOME)/bin/jar
 
-SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
+SRC_FILES = $(shell find $(SRC_DIR) $(TESTLIBRARY_DIR)/share/classes -name '*.java')
+WB_SRC_FILES = $(shell find $(TESTLIBRARY_DIR)/sun/hotspot -name '*.java')
 
 MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld
 
@@ -52,22 +53,29 @@
 	@rm -rf ctw.jar wb.jar
 
 cleantmp:
-	@rm -rf filelist manifest.mf
+	@rm -rf filelist wb_filelist manifest.mf
 	@rm -rf $(BUILD_DIR)
 
-ctw.jar: filelist wb.jar manifest.mf
+ctw.jar: filelist wb.jar
 	@mkdir -p $(OUTPUT_DIR)
-	$(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
-	$(JAR) cfm ctw.jar manifest.mf -C $(OUTPUT_DIR) .
+	$(JAVAC) -XaddExports:java.base/jdk.internal.jimage=ALL-UNNAMED \
+		-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED \
+		-XaddExports:java.base/jdk.internal.reflect=ALL-UNNAMED \
+		-sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
+	$(JAR) --create --file=$@ --main-class $(MAIN_CLASS) -C $(OUTPUT_DIR) .
 
-wb.jar: 
-	make -C ${WHITEBOX_DIR} wb.jar
-	cp ${WHITEBOX_DIR}/wb.jar ./
-	make -C ${WHITEBOX_DIR} clean
+wb.jar: wb_filelist
+	@mkdir -p $(OUTPUT_DIR)
+	$(JAVAC)  -sourcepath $(TESTLIBRARY_DIR) \
+		-d $(OUTPUT_DIR) \
+		-cp $(OUTPUT_DIR) \
+		@wb_filelist
+	$(JAR) --create --file=$@ -C $(OUTPUT_DIR) .
+
+wb_filelist: $(WB_SRC_FILES)
+	@rm -f $@
+	@echo $(WB_SRC_FILES) > $@
 
 filelist: $(SRC_FILES)
 	@rm -f $@
 	@echo $(SRC_FILES) > $@
-
-manifest.mf:
-	@echo "Main-Class: ${MAIN_CLASS}" > manifest.mf
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java	Tue Jun 28 19:58:15 2016 +0300
@@ -54,7 +54,7 @@
 
     @Override
     public void process() {
-        System.out.println("# dir: " + root);
+        CompileTheWorld.OUT.println("# dir: " + root);
         if (!Files.exists(root)) {
             return;
         }
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java	Tue Jun 28 19:58:15 2016 +0300
@@ -50,7 +50,7 @@
 
     @Override
     public void process() {
-        System.out.println("# jar: " + root);
+        CompileTheWorld.OUT.println("# jar: " + root);
         if (!Files.exists(root)) {
             return;
         }
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java	Tue Jun 28 19:58:15 2016 +0300
@@ -40,7 +40,7 @@
 
     @Override
     public void process() {
-        System.out.println("# jar_in_dir: " + root);
+        CompileTheWorld.OUT.println("# jar_in_dir: " + root);
         if (!Files.exists(root)) {
             return;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java	Tue Jun 28 19:58:15 2016 +0300
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, 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.internal.jimage.ImageReader;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.concurrent.Executor;
+
+/**
+ * Handler for jimage-files containing classes to compile.
+ */
+public class ClassPathJimageEntry extends PathHandler {
+    public ClassPathJimageEntry(Path root, Executor executor) {
+        super(root, executor);
+        try {
+            URL url = root.toUri().toURL();
+            setLoader(new URLClassLoader(new URL[]{url}));
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void process() {
+        CompileTheWorld.OUT.println("# jimage: " + root);
+        if (!Files.exists(root)) {
+            return;
+        }
+        try {
+            ImageReader reader = ImageReader.open(root);
+            Arrays.stream(reader.getEntryNames())
+                    .filter(name -> name.endsWith(".class"))
+                    .filter(name -> !name.endsWith("module-info.class"))
+                    .map(Utils::fileNameToClassName)
+                    .forEach(this::processClass);
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+    }
+}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java	Tue Jun 28 19:58:15 2016 +0300
@@ -40,7 +40,7 @@
 
     @Override
     public void process() {
-        System.out.println("# list: " + root);
+        CompileTheWorld.OUT.println("# list: " + root);
         if (!Files.exists(root)) {
             return;
         }
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java	Tue Jun 28 19:58:15 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -33,14 +33,20 @@
 import java.util.concurrent.*;
 
 public class CompileTheWorld {
+    // in case when a static constructor changes System::out and System::err
+    // we hold these values of output streams
+    public static final PrintStream OUT = System.out;
+    public static final PrintStream ERR = System.err;
     /**
-     * Entry point. Compiles classes in {@code args}, or all classes in
-     * boot-classpath if args is empty
+     * Entry point. Compiles classes in {@code paths}
      *
-     * @param args paths to jar/zip, dir contains classes, or to .lst file
-     *             contains list of classes to compile
+     * @param paths paths to jar/zip, dir contains classes, or to .lst file
+     *              contains list of classes to compile
      */
-    public static void main(String[] args) {
+    public static void main(String[] paths) {
+        if (paths.length == 0) {
+            throw new IllegalArgumentException("Expect a path to a compile target.");
+        }
         String logfile = Utils.LOG_FILE;
         PrintStream os = null;
         if (logfile != null) {
@@ -62,12 +68,6 @@
             } catch (java.lang.NoClassDefFoundError e) {
                 // compact1, compact2 support
             }
-            String[] paths = args;
-            boolean skipRtJar = false;
-            if (args.length == 0) {
-                paths = getDefaultPaths();
-                skipRtJar = true;
-            }
             ExecutorService executor = createExecutor();
             long start = System.currentTimeMillis();
             try {
@@ -75,17 +75,13 @@
                 for (int i = 0, n = paths.length; i < n
                         && !PathHandler.isFinished(); ++i) {
                     path = paths[i];
-                    if (skipRtJar && i > 0 && isRtJar(path)) {
-                        // rt.jar is not first, so skip it
-                        continue;
-                    }
                     PathHandler.create(path, executor).process();
                 }
             } finally {
                 await(executor);
             }
-            System.out.printf("Done (%d classes, %d methods, %d ms)%n",
-                    Compiler.getClassCount(),
+            CompileTheWorld.OUT.printf("Done (%d classes, %d methods, %d ms)%n",
+                    PathHandler.getClassCount(),
                     Compiler.getMethodCount(),
                     System.currentTimeMillis() - start);
         } finally {
@@ -93,6 +89,9 @@
                 os.close();
             }
         }
+        // in case when a static constructor creates and runs a new thread
+        // we force it to exit
+        System.exit(0);
     }
 
     private static ExecutorService createExecutor() {
@@ -111,13 +110,6 @@
         return result;
     }
 
-    private static String[] getDefaultPaths() {
-        String property = System.getProperty("sun.boot.class.path");
-        System.out.println(
-                "# use 'sun.boot.class.path' as args: " + property);
-        return Utils.PATH_SEPARATOR.split(property);
-    }
-
     private static void await(ExecutorService executor) {
         executor.shutdown();
         while (!executor.isTerminated()) {
@@ -130,10 +122,6 @@
         }
     }
 
-    private static boolean isRtJar(String path) {
-        return Utils.endsWithIgnoreCase(path, File.separator + "rt.jar");
-    }
-
     private static class CurrentThreadExecutor extends AbstractExecutorService {
         private boolean isShutdown;
 
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java	Tue Jun 28 19:58:15 2016 +0300
@@ -26,7 +26,6 @@
 import sun.hotspot.WhiteBox;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.reflect.ConstantPool;
-
 import java.lang.reflect.Executable;
 
 import java.util.Objects;
@@ -38,18 +37,11 @@
  * Also contains compiled methods and classes counters.
  */
 public class Compiler {
-    private Compiler() { }
-    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
-    private static final AtomicLong CLASS_COUNT = new AtomicLong(0L);
-    private static final AtomicLong METHOD_COUNT = new AtomicLong(0L);
-    private static volatile boolean CLASSES_LIMIT_REACHED = false;
 
-    /**
-     * @return count of processed classes
-     */
-    public static long getClassCount() {
-        return CLASS_COUNT.get();
-    }
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final AtomicLong METHOD_COUNT = new AtomicLong(0L);
+
+    private Compiler() { }
 
     /**
      * @return count of processed methods
@@ -59,58 +51,41 @@
     }
 
     /**
-     * @return {@code true} if classes limit is reached
-     */
-    public static boolean isLimitReached() {
-        return CLASSES_LIMIT_REACHED;
-    }
-
-    /**
      * Compiles all methods and constructors.
      *
      * @param aClass class to compile
+     * @param id an id of the class
      * @param executor executor used for compile task invocation
      * @throws NullPointerException if {@code class} or {@code executor}
      *                              is {@code null}
      */
-    public static void compileClass(Class aClass, Executor executor) {
+    public static void compileClass(Class<?> aClass, long id, Executor executor) {
         Objects.requireNonNull(aClass);
         Objects.requireNonNull(executor);
-        long id = CLASS_COUNT.incrementAndGet();
-        if (id > Utils.COMPILE_THE_WORLD_STOP_AT) {
-            CLASS_COUNT.decrementAndGet();
-            CLASSES_LIMIT_REACHED = true;
-            return;
-        }
+        try {
+            ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
+                    getConstantPool(aClass);
+            if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
+                preloadClasses(aClass.getName(), id, constantPool);
+            }
+            long methodCount = 0;
+            for (Executable e : aClass.getDeclaredConstructors()) {
+                ++methodCount;
+                executor.execute(new CompileMethodCommand(id, e));
+            }
+            for (Executable e : aClass.getDeclaredMethods()) {
+                ++methodCount;
+                executor.execute(new CompileMethodCommand(id, e));
+            }
+            METHOD_COUNT.addAndGet(methodCount);
 
-        if (id >= Utils.COMPILE_THE_WORLD_START_AT) {
-            String name = aClass.getName();
-            try {
-                System.out.printf("[%d]\t%s%n", id, name);
-                ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
-                        getConstantPool(aClass);
-                if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
-                    preloadClasses(name, id, constantPool);
-                }
-                long methodCount = 0;
-                for (Executable e : aClass.getDeclaredConstructors()) {
-                    ++methodCount;
-                    executor.execute(new CompileMethodCommand(id, name, e));
-                }
-                for (Executable e : aClass.getDeclaredMethods()) {
-                    ++methodCount;
-                    executor.execute(new CompileMethodCommand(id, name, e));
-                }
-                METHOD_COUNT.addAndGet(methodCount);
-
-                if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0
-                        && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) {
-                    WHITE_BOX.deoptimizeAll();
-                }
-            } catch (Throwable t) {
-                System.out.printf("[%d]\t%s\tskipping %s%n", id, name, t);
-                t.printStackTrace();
+            if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0
+                    && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) {
+                WHITE_BOX.deoptimizeAll();
             }
+        } catch (Throwable t) {
+            CompileTheWorld.OUT.printf("[%d]\t%s\tskipping %s%n", id, aClass.getName(), t);
+            t.printStackTrace();
         }
     }
 
@@ -124,8 +99,8 @@
                 }
             }
         } catch (Throwable t) {
-            System.out.printf("[%d]\t%s\tpreloading failed : %s%n", id,
-                    className, t);
+            CompileTheWorld.OUT.printf("[%d]\t%s\tpreloading failed : %s%n",
+                    id, className, t);
         }
     }
 
@@ -142,13 +117,11 @@
 
         /**
          * @param classId   id of class
-         * @param className name of class
          * @param method    compiled for compilation
          */
-        public CompileMethodCommand(long classId, String className,
-                Executable method) {
+        public CompileMethodCommand(long classId, Executable method) {
             this.classId = classId;
-            this.className = className;
+            this.className = method.getDeclaringClass().getName();
             this.method = method;
         }
 
@@ -158,10 +131,10 @@
             if (Utils.TIERED_COMPILATION) {
                 for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) {
                     WHITE_BOX.deoptimizeMethod(method);
-                    compileMethod(method, i);
+                    compileAtLevel(i);
                 }
             } else {
-                compileMethod(method, compLevel);
+                compileAtLevel(compLevel);
             }
         }
 
@@ -183,29 +156,29 @@
             }
         }
 
-        private void compileMethod(Executable method, int compLevel) {
+        private void compileAtLevel(int compLevel) {
             if (WHITE_BOX.isMethodCompilable(method, compLevel)) {
                 try {
                     WHITE_BOX.enqueueMethodForCompilation(method, compLevel);
                     waitCompilation();
                     int tmp = WHITE_BOX.getMethodCompilationLevel(method);
                     if (tmp != compLevel) {
-                        logMethod(method, "compilation level = " + tmp
+                        log("compilation level = " + tmp
                                 + ", but not " + compLevel);
                     } else if (Utils.IS_VERBOSE) {
-                        logMethod(method, "compilation level = " + tmp + ". OK");
+                        log("compilation level = " + tmp + ". OK");
                     }
                 } catch (Throwable t) {
-                    logMethod(method, "error on compile at " + compLevel
+                    log("error on compile at " + compLevel
                             + " level");
                     t.printStackTrace();
                 }
             } else if (Utils.IS_VERBOSE) {
-                logMethod(method, "not compilable at " + compLevel);
+                log("not compilable at " + compLevel);
             }
         }
 
-        private void logMethod(Executable method, String message) {
+        private void log(String message) {
             StringBuilder builder = new StringBuilder("[");
             builder.append(classId);
             builder.append("]\t");
@@ -226,7 +199,7 @@
                 builder.append('\t');
                 builder.append(message);
             }
-            System.err.println(builder);
+            CompileTheWorld.ERR.println(builder);
         }
     }
 
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java	Tue Jun 28 19:58:15 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -23,12 +23,14 @@
 
 package sun.hotspot.tools.ctw;
 
+import jdk.internal.misc.Unsafe;
+
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.io.File;
 
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 import java.util.concurrent.Executor;
@@ -38,6 +40,8 @@
  * Concrete subclasses should implement method {@link #process()}.
  */
 public abstract class PathHandler {
+    private static final AtomicLong CLASS_COUNT = new AtomicLong(0L);
+    private static volatile boolean CLASSES_LIMIT_REACHED = false;
     private static final Pattern JAR_IN_DIR_PATTERN
             = Pattern.compile("^(.*[/\\\\])?\\*$");
     protected final Path root;
@@ -81,6 +85,8 @@
                 return new ClassPathJarEntry(p, executor);
             } else if (isListFile(p)) {
                 return new ClassesListInFile(p, executor);
+            } else if (isJimageFile(p)) {
+                return new ClassPathJimageEntry(p, executor);
             } else {
                 return new ClassPathDirEntry(p, executor);
             }
@@ -96,6 +102,13 @@
         return false;
     }
 
+    private static boolean isJimageFile(Path path) {
+        String filename = path.getFileName().toString();
+        return Files.isRegularFile(path)
+                && ("modules".equals(filename)
+                || Utils.endsWithIgnoreCase(filename, ".jimage"));
+    }
+
     private static boolean isListFile(Path path) {
         if (Files.isRegularFile(path)) {
             String name = path.toString();
@@ -122,24 +135,50 @@
     }
 
     /**
-     * Processes specificed class.
+     * Processes specified class.
      * @param name fully qualified name of class to process
      */
     protected final void processClass(String name) {
-        try {
-            Class aClass = Class.forName(name, true, loader);
-            Compiler.compileClass(aClass, executor);
-        } catch (ClassNotFoundException | LinkageError e) {
-            System.out.printf("Class %s loading failed : %s%n", name,
-                e.getMessage());
+        Objects.requireNonNull(name);
+        if (CLASSES_LIMIT_REACHED) {
+            return;
+        }
+        long id = CLASS_COUNT.incrementAndGet();
+        if (id > Utils.COMPILE_THE_WORLD_STOP_AT) {
+            CLASSES_LIMIT_REACHED = true;
+            return;
+        }
+        if (id >= Utils.COMPILE_THE_WORLD_START_AT) {
+            try {
+                Class<?> aClass = loader.loadClass(name);
+                CompileTheWorld.OUT.printf("[%d]\t%s%n", id, name);
+                Compiler.compileClass(aClass, id, executor);
+            } catch (ClassNotFoundException e) {
+                CompileTheWorld.OUT.printf("Class %s loading failed : %s%n",
+                        name, e.getMessage());
+            }
         }
     }
 
     /**
-     * @return {@code true} if processing should be stopped
+     * @return count of processed classes
+     */
+    public static long getClassCount() {
+        long id = CLASS_COUNT.get();
+        if (id < Utils.COMPILE_THE_WORLD_START_AT) {
+            return 0;
+        }
+        if (id > Utils.COMPILE_THE_WORLD_STOP_AT) {
+            return Utils.COMPILE_THE_WORLD_STOP_AT - Utils.COMPILE_THE_WORLD_START_AT + 1;
+        }
+        return id - Utils.COMPILE_THE_WORLD_START_AT + 1;
+    }
+
+    /**
+     * @return {@code true} if classes limit is reached and processing should be stopped
      */
     public static boolean isFinished() {
-        return Compiler.isLimitReached();
+        return CLASSES_LIMIT_REACHED;
     }
 
 }
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java	Mon Jun 27 17:23:15 2016 +0300
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java	Tue Jun 28 19:58:15 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -207,7 +207,12 @@
      */
     public static String fileNameToClassName(String filename) {
         assert isClassFile(filename);
-        return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
-                       .replace(File.separatorChar, '.');
+        // workaround for the class naming in jimage : /<module>/<class_name>
+        final char nameSeparator = '/';
+        int nameStart = filename.charAt(0) == nameSeparator
+                ? filename.indexOf(nameSeparator, 1) + 1
+                : 0;
+        return filename.substring(nameStart, filename.length() - CLASSFILE_EXT.length())
+                       .replace(nameSeparator, '.');
     }
 }