8231903: [Graal] Update com.oracle.mxtool.junit classes
authorepavlova
Wed, 09 Oct 2019 10:59:45 -0700
changeset 58523 fb3d408c7a7e
parent 58522 17a34e111667
child 58524 e84d8379815b
8231903: [Graal] Update com.oracle.mxtool.junit classes Reviewed-by: kvn
test/hotspot/jtreg/ProblemList-graal.txt
test/hotspot/jtreg/compiler/graalunit/CoreAarch64Test.java
test/hotspot/jtreg/compiler/graalunit/CoreJdk9Test.java
test/hotspot/jtreg/compiler/graalunit/EA9Test.java
test/hotspot/jtreg/compiler/graalunit/TestPackages.txt
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/FindClassesByAnnotatedMethods.java
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/JLModule.java
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/ModuleSupport.java
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/MxJUnitWrapper.java
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TextRunListener.java
test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TimingDecorator.java
test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Wed Oct 09 10:59:45 2019 -0700
@@ -236,7 +236,6 @@
 runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java        8222582 generic-all
 
 # Graal unit tests
-org.graalvm.compiler.core.test.CheckGraalInvariants                              8205081
 org.graalvm.compiler.core.test.OptionsVerifierTest                               8205081
 org.graalvm.compiler.hotspot.test.CompilationWrapperTest                         8205081
 org.graalvm.compiler.replacements.test.classfile.ClassfileBytecodeProviderTest   8205081
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreAarch64Test.java	Wed Oct 09 10:59:45 2019 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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
+ * @requires vm.opt.final.EnableJVMCI == true
+ *
+ * @modules jdk.internal.vm.compiler
+ *
+ * @library /test/lib /compiler/graalunit /
+ *
+ * @build compiler.graalunit.common.GraalUnitTestLauncher
+ *
+ * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
+ *
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.aarch64.test -exclude ExcludeList.txt
+ */
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreJdk9Test.java	Wed Oct 09 10:59:45 2019 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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
+ * @requires vm.opt.final.EnableJVMCI == true
+ *
+ * @modules jdk.internal.vm.compiler
+ *
+ * @library /test/lib /compiler/graalunit /
+ *
+ * @build compiler.graalunit.common.GraalUnitTestLauncher
+ *
+ * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
+ *
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test -exclude ExcludeList.txt
+ */
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/EA9Test.java	Wed Oct 09 20:12:46 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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
- * @requires vm.opt.final.EnableJVMCI == true
- *
- * @modules jdk.internal.vm.compiler
- *
- * @library /test/lib /compiler/graalunit /
- *
- * @build compiler.graalunit.common.GraalUnitTestLauncher
- *
- * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
- *
- * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test.ea -exclude ExcludeList.txt
- */
-
-/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt	Wed Oct 09 10:59:45 2019 -0700
@@ -4,18 +4,19 @@
 AsmAarch64    org.graalvm.compiler.asm.aarch64.test
 AsmAmd64      org.graalvm.compiler.asm.amd64.test
 AsmSparc      org.graalvm.compiler.asm.sparc.test
-CoreAmd64     org.graalvm.compiler.core.amd64.test
 Core          org.graalvm.compiler.core.test       @requires !vm.graal.enabled
 EA            org.graalvm.compiler.core.test.ea
-EA9           org.graalvm.compiler.core.jdk9.test.ea
+CoreAmd64     org.graalvm.compiler.core.amd64.test
+CoreAarch64   org.graalvm.compiler.core.aarch64.test
+CoreJdk9      org.graalvm.compiler.core.jdk9.test
 Debug         org.graalvm.compiler.debug.test
 Graph         org.graalvm.compiler.graph.test      @requires vm.graal.enabled
+Hotspot       org.graalvm.compiler.hotspot.test
 HotspotAarch64 org.graalvm.compiler.hotspot.aarch64.test
 HotspotAmd64  org.graalvm.compiler.hotspot.amd64.test
 HotspotJdk9   org.graalvm.compiler.hotspot.jdk9.test
 HotspotSparc  org.graalvm.compiler.hotspot.sparc.test @requires vm.simpleArch == "sparcv9"
 HotspotLir    org.graalvm.compiler.hotspot.lir.test
-Hotspot       org.graalvm.compiler.hotspot.test
 Loop          org.graalvm.compiler.loop.test
 Nodes         org.graalvm.compiler.nodes.test      @requires vm.graal.enabled
 Options       org.graalvm.compiler.options.test
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/FindClassesByAnnotatedMethods.java	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/FindClassesByAnnotatedMethods.java	Wed Oct 09 10:59:45 2019 -0700
@@ -73,7 +73,7 @@
             System.out.print(jarFilePath);
             while (e.hasMoreElements()) {
                 JarEntry je = e.nextElement();
-                if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                if (je.isDirectory() || !je.getName().endsWith(".class") || je.getName().equals("module-info.class")) {
                     continue;
                 }
                 Set<String> methodAnnotationTypes = new HashSet<>();
@@ -84,6 +84,8 @@
                 } catch (UnsupportedClassVersionError ucve) {
                     isSupported = false;
                     unsupportedClasses++;
+                } catch (Throwable t) {
+                    throw new InternalError("Error while parsing class from " + je + " in " + jarFilePath, t);
                 }
                 String className = je.getName().substring(0, je.getName().length() - ".class".length()).replaceAll("/", ".");
                 if (!isSupported) {
@@ -129,7 +131,7 @@
     /*
      * Small bytecode parser that extract annotations.
      */
-    private static final int MAJOR_VERSION_JAVA7 = 51;
+    private static final int MAJOR_VERSION_JAVA6 = 50;
     private static final int MAJOR_VERSION_OFFSET = 44;
     private static final byte CONSTANT_Utf8 = 1;
     private static final byte CONSTANT_Integer = 3;
@@ -146,6 +148,8 @@
     private static final byte CONSTANT_MethodType = 16;
     private static final byte CONSTANT_Dynamic = 17;
     private static final byte CONSTANT_InvokeDynamic = 18;
+    private static final byte CONSTANT_Module = 19;
+    private static final byte CONSTANT_Package = 20;
 
     private static void readClassfile(DataInputStream stream, Collection<String> methodAnnotationTypes) throws IOException {
         // magic
@@ -154,7 +158,7 @@
 
         int minor = stream.readUnsignedShort();
         int major = stream.readUnsignedShort();
-        if (major < MAJOR_VERSION_JAVA7) {
+        if (major < MAJOR_VERSION_JAVA6) {
             throw new UnsupportedClassVersionError("Unsupported class file version: " + major + "." + minor);
         }
         // Starting with JDK8, ignore a classfile that has a newer format than the current JDK.
@@ -210,7 +214,9 @@
             switch (tag) {
                 case CONSTANT_Class:
                 case CONSTANT_String:
-                case CONSTANT_MethodType: {
+                case CONSTANT_MethodType:
+                case CONSTANT_Module:
+                case CONSTANT_Package: {
                     skipFully(stream, 2);
                     break;
                 }
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/JLModule.java	Wed Oct 09 20:12:46 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * 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 com.oracle.mxtool.junit;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Set;
-
-/**
- * Facade for the {@code java.lang.Module} class introduced in JDK9 that allows tests to be
- * developed against JDK8 but use module logic if deployed on JDK9.
- */
-class JLModule {
-
-    private final Object realModule;
-
-    JLModule(Object module) {
-        this.realModule = module;
-    }
-
-    private static final Class<?> moduleClass;
-    private static final Class<?> layerClass;
-
-    private static final Method bootMethod;
-    private static final Method modulesMethod;
-    private static final Method getModuleMethod;
-    private static final Method getUnnamedModuleMethod;
-    private static final Method getNameMethod;
-    private static final Method getPackagesMethod;
-    private static final Method isExportedMethod;
-    private static final Method isExported2Method;
-    private static final Method addExportsMethod;
-    private static final Method addOpensMethod;
-    static {
-        try {
-            moduleClass = findModuleClass();
-            Class<?> modulesClass = Class.forName("jdk.internal.module.Modules");
-            layerClass = findModuleLayerClass();
-            bootMethod = layerClass.getMethod("boot");
-            modulesMethod = layerClass.getMethod("modules");
-            getModuleMethod = Class.class.getMethod("getModule");
-            getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
-            getNameMethod = moduleClass.getMethod("getName");
-            getPackagesMethod = moduleClass.getMethod("getPackages");
-            isExportedMethod = moduleClass.getMethod("isExported", String.class);
-            isExported2Method = moduleClass.getMethod("isExported", String.class, moduleClass);
-            addExportsMethod = modulesClass.getDeclaredMethod("addExports", moduleClass, String.class, moduleClass);
-            addOpensMethod = getDeclaredMethodOptional(modulesClass, "addOpens", moduleClass, String.class, moduleClass);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e.
-    protected static Class<?> findModuleClass() throws ClassNotFoundException {
-        try {
-            return Class.forName("java.lang.Module");
-        } catch (ClassNotFoundException e) {
-            return Class.forName("java.lang.reflect.Module");
-        }
-    }
-
-    // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e.
-    protected static Class<?> findModuleLayerClass() throws ClassNotFoundException {
-        try {
-            return Class.forName("java.lang.ModuleLayer");
-        } catch (ClassNotFoundException e) {
-            return Class.forName("java.lang.reflect.Layer");
-        }
-    }
-
-    private static Method getDeclaredMethodOptional(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
-        try {
-            return declaringClass.getDeclaredMethod(name, parameterTypes);
-        } catch (NoSuchMethodException e) {
-            return null;
-        }
-    }
-
-    public static JLModule fromClass(Class<?> cls) {
-        try {
-            return new JLModule(getModuleMethod.invoke(cls));
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static JLModule find(String name) {
-        try {
-            Object bootLayer = bootMethod.invoke(null);
-            Set<Object> modules = (Set<Object>) modulesMethod.invoke(bootLayer);
-            for (Object m : modules) {
-                JLModule module = new JLModule(m);
-                String mname = module.getName();
-                if (mname.equals(name)) {
-                    return module;
-                }
-            }
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-        return null;
-    }
-
-    public static JLModule getUnnamedModuleFor(ClassLoader cl) {
-        try {
-            return new JLModule(getUnnamedModuleMethod.invoke(cl));
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public String getName() {
-        try {
-            return (String) getNameMethod.invoke(realModule);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    /**
-     * Exports all packages in this module to a given module.
-     */
-    public void exportAllPackagesTo(JLModule module) {
-        if (this != module) {
-            for (String pkg : getPackages()) {
-                // Export all JVMCI packages dynamically instead
-                // of requiring a long list of -XaddExports
-                // options on the JVM command line.
-                if (!isExported(pkg, module)) {
-                    addExports(pkg, module);
-                    addOpens(pkg, module);
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public Iterable<String> getPackages() {
-        try {
-            // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e#l1.15
-            Object res = getPackagesMethod.invoke(realModule);
-            if (res instanceof String[]) {
-                return Arrays.asList((String[]) res);
-            }
-            return (Set<String>) res;
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public boolean isExported(String pn) {
-        try {
-            return (Boolean) isExportedMethod.invoke(realModule, pn);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public boolean isExported(String pn, JLModule other) {
-        try {
-            return (Boolean) isExported2Method.invoke(realModule, pn, other.realModule);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public void addExports(String pn, JLModule other) {
-        try {
-            addExportsMethod.invoke(null, realModule, pn, other.realModule);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public void addOpens(String pn, JLModule other) {
-        if (addOpensMethod != null) {
-            try {
-                addOpensMethod.invoke(null, realModule, pn, other.realModule);
-            } catch (Exception e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        return realModule.toString();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/ModuleSupport.java	Wed Oct 09 10:59:45 2019 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, 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 com.oracle.mxtool.junit;
+
+import java.io.PrintStream;
+import java.util.Set;
+
+/**
+ * Interface to {@code java.lang.Module} related functionality.
+ */
+class ModuleSupport {
+
+    /**
+     * @param out stream to use for printing warnings
+     */
+    ModuleSupport(PrintStream out) {
+    }
+
+    /**
+     * Exports and opens packages based on {@code spec}. See further documentation in
+     * {@code mx_unittest.py}.
+     *
+     * @param spec
+     * @param context
+     * @param opened the set of opens performed are added to this set in the format
+     *            {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+     *            {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+     * @param exported the set of exports performed are added to this set in the format
+     *            {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+     *            {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+     */
+    void openPackages(String spec, Object context, Set<String> opened, Set<String> exported) {
+        // Nop on JDK 8
+    }
+
+    /**
+     * Updates modules specified in {@code AddExport} annotations on {@code classes} to export and
+     * open packages to the annotation classes' declaring modules.
+     *
+     * @param classes
+     * @param opened the set of opens performed are added to this set in the format
+     *            {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+     *            {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+     * @param exported the set of exports performed are added to this set in the format
+     *            {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+     *            {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+     */
+    void processAddExportsAnnotations(Set<Class<?>> classes, Set<String> opened, Set<String> exported) {
+        // Nop on JDK 8
+    }
+}
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/MxJUnitWrapper.java	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/MxJUnitWrapper.java	Wed Oct 09 10:59:45 2019 -0700
@@ -29,18 +29,13 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.ServiceLoader;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.TreeSet;
 
 import org.junit.internal.JUnitSystem;
 import org.junit.internal.RealSystem;
@@ -59,6 +54,14 @@
 
 public class MxJUnitWrapper {
 
+    // Unit tests that start a JVM subprocess can use these system properties to
+    // add --add-exports and --add-opens as necessary to the JVM command line.
+    //
+    // Known usages:
+    // org.graalvm.compiler.test.SubprocessUtil.getPackageOpeningOptions()
+    public static final String OPENED_PACKAGES_PROPERTY_NAME = "com.oracle.mxtool.junit.opens";
+    public static final String EXPORTED_PACKAGES_PROPERTY_NAME = "com.oracle.mxtool.junit.exports";
+
     public static class MxJUnitConfig {
 
         public boolean verbose = false;
@@ -136,14 +139,25 @@
 
         String[] expandedArgs = expandArgs(args);
         int i = 0;
+        List<String> testSpecs = new ArrayList<>();
+        List<String> openPackagesSpecs = new ArrayList<>();
         while (i < expandedArgs.length) {
             String each = expandedArgs[i];
             if (each.charAt(0) == '-') {
                 // command line arguments
                 if (each.contentEquals("-JUnitVerbose")) {
                     config.verbose = true;
+                    config.enableTiming = true;
+                } else if (each.contentEquals("-JUnitOpenPackages")) {
+                    if (i + 1 >= expandedArgs.length) {
+                        system.out().println("Must include argument for -JUnitAddExports");
+                        System.exit(1);
+                    }
+                    openPackagesSpecs.add(expandedArgs[++i]);
                 } else if (each.contentEquals("-JUnitVeryVerbose")) {
+                    config.verbose = true;
                     config.veryVerbose = true;
+                    config.enableTiming = true;
                 } else if (each.contentEquals("-JUnitFailFast")) {
                     config.failFast = true;
                 } else if (each.contentEquals("-JUnitEnableTiming")) {
@@ -172,21 +186,35 @@
                 }
 
             } else {
-
-                try {
-                    builder.addTestSpec(each);
-                } catch (MxJUnitRequest.BuilderException ex) {
-                    system.out().println(ex.getMessage());
-                    System.exit(1);
-                }
+                testSpecs.add(each);
             }
             i++;
         }
 
-        MxJUnitRequest request = builder.build();
+        ModuleSupport moduleSupport = new ModuleSupport(system.out());
+        Set<String> opened = new TreeSet<>();
+        Set<String> exported = new TreeSet<>();
+        for (String spec : openPackagesSpecs) {
+            moduleSupport.openPackages(spec, "-JUnitOpenPackages", opened, exported);
+        }
 
-        if (System.getProperty("java.specification.version").compareTo("1.9") >= 0) {
-            addExports(request.classes, system.out());
+        for (String spec : testSpecs) {
+            try {
+                builder.addTestSpec(spec);
+            } catch (MxJUnitRequest.BuilderException ex) {
+                system.out().println(ex.getMessage());
+                System.exit(1);
+            }
+        }
+
+        MxJUnitRequest request = builder.build();
+        moduleSupport.processAddExportsAnnotations(request.classes, opened, exported);
+
+        if (!opened.isEmpty()) {
+            System.setProperty(OPENED_PACKAGES_PROPERTY_NAME, String.join(System.lineSeparator(), opened));
+        }
+        if (!exported.isEmpty()) {
+            System.setProperty(EXPORTED_PACKAGES_PROPERTY_NAME, String.join(System.lineSeparator(), exported));
         }
 
         for (RunListener p : ServiceLoader.load(RunListener.class)) {
@@ -285,8 +313,6 @@
         return result;
     }
 
-    private static final Pattern MODULE_PACKAGE_RE = Pattern.compile("([^/]+)/(.+)");
-
     private static class Timing<T> implements Comparable<Timing<T>> {
         final T subject;
         final long value;
@@ -344,93 +370,6 @@
     }
 
     /**
-     * Adds the super types of {@code cls} to {@code supertypes}.
-     */
-    private static void gatherSupertypes(Class<?> cls, Set<Class<?>> supertypes) {
-        if (!supertypes.contains(cls)) {
-            supertypes.add(cls);
-            Class<?> superclass = cls.getSuperclass();
-            if (superclass != null) {
-                gatherSupertypes(superclass, supertypes);
-            }
-            for (Class<?> iface : cls.getInterfaces()) {
-                gatherSupertypes(iface, supertypes);
-            }
-        }
-    }
-
-    /**
-     * Updates modules specified in {@code AddExport} annotations on {@code classes} to export
-     * concealed packages to the annotation classes' declaring modules.
-     */
-    private static void addExports(Set<Class<?>> classes, PrintStream out) {
-        Set<Class<?>> types = new HashSet<>();
-        for (Class<?> cls : classes) {
-            gatherSupertypes(cls, types);
-        }
-        for (Class<?> cls : types) {
-            Annotation[] annos = cls.getAnnotations();
-            for (Annotation a : annos) {
-                Class<? extends Annotation> annotationType = a.annotationType();
-                if (annotationType.getSimpleName().equals("AddExports")) {
-                    Optional<String[]> value = getElement("value", String[].class, a);
-                    if (value.isPresent()) {
-                        for (String export : value.get()) {
-                            Matcher m = MODULE_PACKAGE_RE.matcher(export);
-                            if (m.matches()) {
-                                String moduleName = m.group(1);
-                                String packageName = m.group(2);
-                                JLModule module = JLModule.find(moduleName);
-                                if (module == null) {
-                                    out.printf("%s: Cannot find module named %s specified in \"AddExports\" annotation: %s%n", cls.getName(), moduleName, a);
-                                } else {
-                                    if (packageName.equals("*")) {
-                                        module.exportAllPackagesTo(JLModule.fromClass(cls));
-                                    } else {
-                                        module.addExports(packageName, JLModule.fromClass(cls));
-                                        module.addOpens(packageName, JLModule.fromClass(cls));
-                                    }
-                                }
-                            } else {
-                                out.printf("%s: Ignoring \"AddExports\" annotation with value not matching <module>/<package> pattern: %s%n", cls.getName(), a);
-                            }
-                        }
-                    } else {
-                        out.printf("%s: Ignoring \"AddExports\" annotation without `String value` element: %s%n", cls.getName(), a);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Gets the value of the element named {@code name} of type {@code type} from {@code annotation}
-     * if present.
-     *
-     * @return the requested element value wrapped in an {@link Optional} or
-     *         {@link Optional#empty()} if {@code annotation} has no element named {@code name}
-     * @throws AssertionError if {@code annotation} has an element of the given name but whose type
-     *             is not {@code type} or if there's some problem reading the value via reflection
-     */
-    private static <T> Optional<T> getElement(String name, Class<T> type, Annotation annotation) {
-        Class<? extends Annotation> annotationType = annotation.annotationType();
-        Method valueAccessor;
-        try {
-            valueAccessor = annotationType.getMethod(name);
-            if (!valueAccessor.getReturnType().equals(type)) {
-                throw new AssertionError(String.format("Element %s of %s is of type %s, not %s ", name, annotationType.getName(), valueAccessor.getReturnType().getName(), type.getName()));
-            }
-        } catch (NoSuchMethodException e) {
-            return Optional.empty();
-        }
-        try {
-            return Optional.of(type.cast(valueAccessor.invoke(annotation)));
-        } catch (Exception e) {
-            throw new AssertionError(String.format("Could not read %s element from %s", name, annotation), e);
-        }
-    }
-
-    /**
      * Expand any arguments starting with @ and return the resulting argument array.
      *
      * @return the expanded argument array
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TextRunListener.java	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TextRunListener.java	Wed Oct 09 10:59:45 2019 -0700
@@ -74,7 +74,8 @@
     }
 
     public static RunListener createRunListener(MxRunListener l) {
-        return new TextListener(l.getWriter()) {
+        PrintStream theWriter = l.getWriter();
+        return new TextListener(theWriter) {
             private Class<?> lastClass;
             private int passedInLastClass;
             private int failedInLastClass;
@@ -143,6 +144,15 @@
             public void testAssumptionFailure(Failure failure) {
                 l.testAssumptionFailure(failure);
             }
+
+            @Override
+            protected void printFailure(Failure each, String prefix) {
+                // Print out the test message in the same format used to run a single test:
+                // my.package.MyClass#methodName
+                String header = each.getDescription().getClassName() + "#" + each.getDescription().getMethodName();
+                theWriter.println(prefix + ") " + header);
+                theWriter.print(each.getTrace());
+            }
         };
     }
 }
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TimingDecorator.java	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TimingDecorator.java	Wed Oct 09 10:59:45 2019 -0700
@@ -22,8 +22,8 @@
  */
 package com.oracle.mxtool.junit;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.junit.runner.Description;
 
@@ -40,8 +40,8 @@
 
     TimingDecorator(MxRunListener l) {
         super(l);
-        this.classTimes = new HashMap<>();
-        this.testTimes = new HashMap<>();
+        this.classTimes = new ConcurrentHashMap<>();
+        this.testTimes = new ConcurrentHashMap<>();
     }
 
     @Override
--- a/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java	Wed Oct 09 20:12:46 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java	Wed Oct 09 10:59:45 2019 -0700
@@ -229,6 +229,8 @@
         javaFlags.add("jdk.internal.vm.compiler,jdk.internal.vm.ci");
         javaFlags.add("--add-exports");
         javaFlags.add("java.base/jdk.internal.module=ALL-UNNAMED");
+        javaFlags.add("--add-exports");
+        javaFlags.add("java.base/jdk.internal.misc=ALL-UNNAMED");
         javaFlags.addAll(getModuleExports("jdk.internal.vm.compiler", "ALL-UNNAMED"));
         javaFlags.addAll(getModuleExports("jdk.internal.vm.ci", "ALL-UNNAMED,jdk.internal.vm.compiler"));