changeset 21887:543f150e7fa0

com.oracle.jvmci.service.Service is now a marker for service implementations available via JVMCI; removed Truffle -> JVMCI dependency
author Doug Simon <doug.simon@oracle.com>
date Tue, 09 Jun 2015 22:44:34 +0200
parents b1234c06ea49
children 878786299d2d
files graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java jvmci/com.oracle.jvmci.service.processor/src/com/oracle/jvmci/service/processor/ServiceProviderProcessor.java jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Service.java jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/ServiceProvider.java jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Services.java mx/FilterTypes.java mx/mx_graal.py mx/suite.py
diffstat 10 files changed, 80 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntimeAccess.java	Tue Jun 09 22:44:34 2015 +0200
@@ -26,7 +26,7 @@
 import com.oracle.truffle.api.*;
 
 @ServiceProvider(TruffleRuntimeAccess.class)
-public class HotSpotTruffleRuntimeAccess implements TruffleRuntimeAccess {
+public class HotSpotTruffleRuntimeAccess implements TruffleRuntimeAccess, Service {
     public TruffleRuntime getRuntime() {
         return HotSpotTruffleRuntime.makeInstance();
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Tue Jun 09 22:44:34 2015 +0200
@@ -24,9 +24,9 @@
  */
 package com.oracle.truffle.api;
 
+import java.lang.reflect.*;
 import java.security.*;
 
-import com.oracle.jvmci.service.*;
 import com.oracle.truffle.api.impl.*;
 
 /**
@@ -55,11 +55,22 @@
         return AccessController.doPrivileged(new PrivilegedAction<TruffleRuntime>() {
             public TruffleRuntime run() {
                 TruffleRuntimeAccess access = null;
+                Class<?> servicesClass = null;
                 try {
-                    access = Services.loadSingle(TruffleRuntimeAccess.class, false);
-                } catch (NoClassDefFoundError e) {
+                    servicesClass = Class.forName("com.oracle.jvmci.service.Services");
+                } catch (ClassNotFoundException e) {
                     // JVMCI is unavailable
                 }
+                if (servicesClass != null) {
+                    try {
+                        Method m = servicesClass.getDeclaredMethod("loadSingle", Class.class, boolean.class);
+                        access = (TruffleRuntimeAccess) m.invoke(null, TruffleRuntimeAccess.class, false);
+                    } catch (Throwable e) {
+                        // Fail fast for other errors
+                        throw (InternalError) new InternalError().initCause(e);
+                    }
+                }
+                // TODO: try standard ServiceLoader?
                 if (access != null) {
                     return access.getRuntime();
                 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java	Tue Jun 09 22:44:34 2015 +0200
@@ -24,13 +24,10 @@
  */
 package com.oracle.truffle.api;
 
-import com.oracle.jvmci.service.*;
-
 /**
- * A {@linkplain Service JVMCI service} that provides access to a {@link TruffleRuntime}
- * implementation.
+ * A service that provides access to a {@link TruffleRuntime} implementation.
  */
-public interface TruffleRuntimeAccess extends Service {
+public interface TruffleRuntimeAccess {
 
     /**
      * Gets the {@link TruffleRuntime} implementation available via this access object.
--- a/jvmci/com.oracle.jvmci.service.processor/src/com/oracle/jvmci/service/processor/ServiceProviderProcessor.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.service.processor/src/com/oracle/jvmci/service/processor/ServiceProviderProcessor.java	Tue Jun 09 22:44:34 2015 +0200
@@ -46,13 +46,13 @@
     }
 
     private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) {
-        if (!processingEnv.getTypeUtils().isSubtype(serviceInterface, baseJVMCIServiceInterface.asType())) {
-            String msg = String.format("Service interface class %s doesn't extend JVMCI service interface %s", serviceInterface, baseJVMCIServiceInterface);
+        if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), baseJVMCIServiceInterface.asType())) {
+            String msg = String.format("Service implementation class %s must implement %s", serviceProvider.getSimpleName(), baseJVMCIServiceInterface);
             processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
             return false;
         }
         if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) {
-            String msg = String.format("Service provider class %s doesn't implement service interface %s", serviceProvider.getSimpleName(), serviceInterface);
+            String msg = String.format("Service provider class %s must implement service interface %s", serviceProvider.getSimpleName(), serviceInterface);
             processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
             return false;
         }
--- a/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Service.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Service.java	Tue Jun 09 22:44:34 2015 +0200
@@ -22,15 +22,11 @@
  */
 package com.oracle.jvmci.service;
 
-import java.util.*;
-
 /**
- * Denotes a JVMCI service that can be loaded by {@link Services#load(Class)} or
- * {@link Services#loadSingle(Class, boolean)}. JVMCI services differ from
- * {@linkplain ServiceLoader#load(Class) standard} services in that they may have implementations
- * hidden behind a class loader not accessible to applications. For this reason,
- * {@link Services#load(Class)} and {@link Services#loadSingle(Class, boolean)} perform
- * {@link SecurityManager} checks.
+ * Marker interface for a service implementation that can be loaded by {@link Services#load(Class)}
+ * or {@link Services#loadSingle(Class, boolean)}. These implementations are hidden behind a class
+ * loader not accessible to applications. For this reason, {@link Services#load(Class)} and
+ * {@link Services#loadSingle(Class, boolean)} perform {@link SecurityManager} checks.
  *
  * @see Services
  * @see ServiceProvider
--- a/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/ServiceProvider.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/ServiceProvider.java	Tue Jun 09 22:44:34 2015 +0200
@@ -25,9 +25,8 @@
 import java.lang.annotation.*;
 
 /**
- * Annotates a class that implements a {@linkplain Service JVMCI service}. This annotation is used
- * by the JVMCI build system to deploy the necessary files used to {@linkplain Services#load(Class)
- * load} JVMCI services at runtime.
+ * Annotates a JVMCI implementation of a service. This annotation is used by the JVMCI build system
+ * to deploy the necessary files used to {@linkplain Services#load(Class) load} services at runtime.
  */
 @Retention(RetentionPolicy.CLASS)
 @Target(ElementType.TYPE)
--- a/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Services.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/jvmci/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Services.java	Tue Jun 09 22:44:34 2015 +0200
@@ -27,7 +27,7 @@
 import sun.reflect.*;
 
 /**
- * An mechanism for loading {@linkplain Service JVMCI services}.
+ * An mechanism for loading services that have a {@linkplain Service JVMCI implementation}.
  */
 public class Services {
 
@@ -39,9 +39,9 @@
      */
     private static final boolean SuppressNoClassDefFoundError = Boolean.getBoolean(SUPPRESS_PROPERTY_NAME);
 
-    private static final ClassValue<List<Service>> cache = new ClassValue<List<Service>>() {
+    private static final ClassValue<List<?>> cache = new ClassValue<List<?>>() {
         @Override
-        protected List<Service> computeValue(Class<?> type) {
+        protected List<?> computeValue(Class<?> type) {
             try {
                 return Arrays.asList(getServiceImpls(type));
             } catch (NoClassDefFoundError e) {
@@ -59,14 +59,14 @@
     };
 
     /**
-     * Gets an {@link Iterable} of the implementations available for a given JVMCI service.
+     * Gets an {@link Iterable} of the JVMCI implementations available for a given service.
      *
      * @throws SecurityException if a security manager is present and it denies
      *             <tt>{@link RuntimePermission}("jvmciServices")</tt>
      */
     @SuppressWarnings("unchecked")
     @CallerSensitive
-    public static <S extends Service> Iterable<S> load(Class<S> service) {
+    public static <S> Iterable<S> load(Class<S> service) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission("jvmciServices"));
@@ -79,8 +79,8 @@
     }
 
     /**
-     * Gets the implementation for a given service for which at most one implementation must be
-     * available.
+     * Gets the JVMCI implementation for a given service for which at most one implementation must
+     * be available.
      *
      * @param service the service whose implementation is being requested
      * @param required specifies if an {@link InternalError} should be thrown if no implementation
@@ -88,9 +88,9 @@
      * @throws SecurityException if a security manager is present and it denies
      *             <tt>{@link RuntimePermission}("jvmciServices")</tt>
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked"})
     @CallerSensitive
-    public static <S extends Service> S loadSingle(Class<S> service, boolean required) {
+    public static <S> S loadSingle(Class<S> service, boolean required) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission("jvmciServices"));
--- a/mx/FilterTypes.java	Tue Jun 09 22:31:05 2015 +0200
+++ b/mx/FilterTypes.java	Tue Jun 09 22:44:34 2015 +0200
@@ -23,41 +23,46 @@
 
 public class FilterTypes {
 
-    /**
-     * Prints to {@link System#out} the values in {@code args[1 .. N]} that denote classes that are
-     * {@link Class#isAssignableFrom(Class) assignable} to the type denoted in {@code args[0]}. The
-     * values are separated by {@code "|"}.
-     */
     public static void main(String... args) throws Exception {
         Class<?> jvmciServiceInterface = Class.forName(args[0]);
-        boolean needSep = false;
         StringBuilder buf = new StringBuilder();
         for (int i = 1; i < args.length; ++i) {
-            String serviceName = args[i];
-            Class<?> service = lookupService(serviceName);
-            if (service != null && jvmciServiceInterface.isAssignableFrom(service)) {
+            String[] e = args[i].split("=");
+            String serviceName = e[0];
+            String implNames = e[1];
+
+            StringBuilder impls = new StringBuilder();
+            for (String implName : implNames.split(",")) {
+                Class<?> impl = lookup(implName);
+                if (impl != null && jvmciServiceInterface.isAssignableFrom(impl)) {
+                    if (impls.length() != 0) {
+                        impls.append(',');
+                    }
+                    impls.append(implName);
+                }
+            }
+            if (impls.length() != 0) {
                 if (buf.length() != 0) {
-                    buf.append('|');
+                    buf.append(' ');
                 }
-                buf.append(serviceName);
-                needSep = true;
+                buf.append(serviceName).append('=').append(impls);
             }
         }
         System.out.print(buf);
     }
-    
-    private static Class<?> lookupService(String serviceName) {
-    	try {
-    		// This can fail in the case of running against a JDK
-    		// with out of date JVMCI jars. In that case, just print
-    		// a warning sinc the expectation is that the jars will be
-    		// updated later on.
-    	    return Class.forName(serviceName, false, FilterTypes.class.getClassLoader());
-    	} catch (ClassNotFoundException e) {
-    		// Must be stderr to avoid polluting the result being
-    		// written to stdout.
-    		System.err.println(e);
-    		return null;
-    	}
+
+    private static Class<?> lookup(String name) {
+        try {
+            // This can fail in the case of running against a JDK
+            // with out of date JVMCI jars. In that case, just print
+            // a warning since the expectation is that the jars will be
+            // updated later on.
+            return Class.forName(name, false, FilterTypes.class.getClassLoader());
+        } catch (ClassNotFoundException e) {
+            // Must be stderr to avoid polluting the result being
+            // written to stdout.
+            System.err.println(e);
+            return null;
+        }
     }
 }
--- a/mx/mx_graal.py	Tue Jun 09 22:31:05 2015 +0200
+++ b/mx/mx_graal.py	Tue Jun 09 22:44:34 2015 +0200
@@ -550,18 +550,24 @@
         shutil.move(tmp, dstLib)
         os.chmod(dstLib, permissions)
 
-def _filterJVMCIServices(serviceImplNames, classpath):
+def _filterJVMCIServices(servicesMap, classpath):
     """
     Filters and returns the names in 'serviceImplNames' that denote
     types available in 'classpath' implementing or extending
     com.oracle.jvmci.service.Service.
     """
     _, binDir = mx._compile_mx_class('FilterTypes', os.pathsep.join(classpath), myDir=dirname(__file__))
-    cmd = [mx.java().java, '-cp', mx._cygpathU2W(os.pathsep.join([binDir] + classpath)), 'FilterTypes', 'com.oracle.jvmci.service.Service'] + serviceImplNames
-    services = subprocess.check_output(cmd)
-    if len(services) == 0:
-        return []
-    return services.split('|')
+    serialized = [k + '=' + ','.join(v) for k, v in servicesMap.iteritems()]
+    cmd = [mx.java().java, '-cp', mx._cygpathU2W(os.pathsep.join([binDir] + classpath)), 'FilterTypes', 'com.oracle.jvmci.service.Service'] + serialized
+    serialized = subprocess.check_output(cmd)
+    if len(serialized) == 0:
+        return {}
+    servicesMap = {}
+    for e in serialized.split(' '):
+        k, v = e.split('=')
+        impls = v.split(',')
+        servicesMap[k] = impls
+    return servicesMap
 
 def _extractJVMCIFiles(jdkJars, jvmciJars, servicesDir, optionsDir, cleanDestination=True):
     if cleanDestination:
@@ -602,9 +608,8 @@
                         with zf.open(member) as optionsFile, \
                              file(targetpath, "wb") as target:
                             shutil.copyfileobj(optionsFile, target)
-    jvmciServices = _filterJVMCIServices(servicesMap.keys(), jdkJars)
-    for serviceName in jvmciServices:
-        serviceImpls = servicesMap[serviceName]
+    servicesMap = _filterJVMCIServices(servicesMap, jdkJars)
+    for serviceName, serviceImpls in servicesMap.iteritems():
         fd, tmp = tempfile.mkstemp(prefix=serviceName)
         f = os.fdopen(fd, 'w+')
         for serviceImpl in serviceImpls:
@@ -614,7 +619,6 @@
         shutil.move(tmp, target)
         if mx.get_os() != 'windows':
             os.chmod(target, JDK_UNIX_PERMISSIONS_FILE)
-    return (jvmciServices, optionsFiles)
 
 def _updateJVMCIFiles(jdkDir):
     jreJVMCIDir = join(jdkDir, 'jre', 'lib', 'jvmci')
--- a/mx/suite.py	Tue Jun 09 22:31:05 2015 +0200
+++ b/mx/suite.py	Tue Jun 09 22:44:34 2015 +0200
@@ -1071,7 +1071,6 @@
     "com.oracle.truffle.api" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
-      "dependencies" : ["com.oracle.jvmci.service"],
       "javaCompliance" : "1.7",
       "workingSets" : "API,Truffle",
     },