changeset 21031:e1c063565b3c

Graal Services: use services files in jre/lib/graal/services
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Wed, 15 Apr 2015 18:21:00 +0200
parents c8166c23047d
children 9507c925abe9
files graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java mx/mx_graal.py src/share/vm/graal/graalRuntime.cpp
diffstat 3 files changed, 97 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Wed Apr 15 17:14:56 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Wed Apr 15 18:21:00 2015 +0200
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.options.*;
 
 /**
@@ -38,7 +37,6 @@
  * generated code is comprised of:
  * <ul>
  * <li>{@code -G} command line option parsing {@linkplain #genSetOption(PrintStream) helper}</li>
- * <li>{@link Service} loading {@linkplain #genGetServiceImpls(PrintStream) helper}</li>
  * </ul>
  *
  * The purpose of the generated code is to avoid executing Graal related Java code as much as
@@ -93,7 +91,6 @@
     public static void main(String[] args) {
         PrintStream out = System.out;
         try {
-            genGetServiceImpls(out);
             genSetOption(out);
         } catch (Throwable t) {
             t.printStackTrace(out);
@@ -102,65 +99,6 @@
     }
 
     /**
-     * Generates code for {@code GraalRuntime::get_service_impls()}.
-     */
-    private static void genGetServiceImpls(PrintStream out) throws Exception {
-        final List<Class<? extends Service>> services = new ArrayList<>();
-        for (ZipEntry zipEntry : graalJars) {
-            String name = zipEntry.getName();
-            if (name.startsWith("META-INF/services/")) {
-                String serviceName = name.substring("META-INF/services/".length());
-                Class<?> c = Class.forName(serviceName);
-                if (Service.class.isAssignableFrom(c)) {
-                    @SuppressWarnings("unchecked")
-                    Class<? extends Service> sc = (Class<? extends Service>) c;
-
-                    services.add(sc);
-                }
-            }
-        }
-
-        Set<Integer> lengths = new TreeSet<>();
-        for (Class<?> service : services) {
-            lengths.add(toInternalName(service).length());
-        }
-
-        out.println("Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {");
-        out.println("  switch (serviceKlass->name()->utf8_length()) {");
-        for (int len : lengths) {
-            boolean printedCase = false;
-            for (Class<?> service : services) {
-                String serviceName = toInternalName(service);
-                if (len == serviceName.length()) {
-                    if (!printedCase) {
-                        printedCase = true;
-                        out.println("  case " + len + ":");
-                    }
-                    out.printf("    if (serviceKlass->name()->equals(\"%s\", %d)) {%n", serviceName, serviceName.length());
-                    List<Class<?>> impls = new ArrayList<>();
-                    for (Object impl : ServiceLoader.load(service)) {
-                        impls.add(impl.getClass());
-                    }
-
-                    out.printf("      objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), %d, CHECK_NH);%n", impls.size());
-                    out.println("      objArrayHandle services(THREAD, servicesOop);");
-                    for (int i = 0; i < impls.size(); i++) {
-                        String name = toInternalName(impls.get(i));
-                        out.printf("      %sservice = create_Service(\"%s\", CHECK_NH);%n", (i == 0 ? "Handle " : ""), name);
-                        out.printf("      services->obj_at_put(%d, service());%n", i);
-                    }
-                    out.println("      return services;");
-                    out.println("    }");
-                }
-            }
-
-        }
-        out.println("  }");
-        out.println("  return Handle();");
-        out.println("}");
-    }
-
-    /**
      * Generates code for {@code GraalRuntime::set_option()} and
      * {@code GraalRuntime::set_option_bool()}.
      */
--- a/mx/mx_graal.py	Wed Apr 15 17:14:56 2015 +0200
+++ b/mx/mx_graal.py	Wed Apr 15 18:21:00 2015 +0200
@@ -87,15 +87,16 @@
 _untilVersion = None
 
 class JDKDeployedDist:
-    def __init__(self, name, isExtension):
+    def __init__(self, name, isExtension = False, isGraalClassLoader = False):
         self.name = name
         self.isExtension = isExtension
+        self.isGraalClassLoader = isGraalClassLoader
 
 _jdkDeployedDists = [
-    JDKDeployedDist('TRUFFLE', isExtension=False),
-    JDKDeployedDist('GRAAL_LOADER', isExtension=False),
-    JDKDeployedDist('GRAAL', isExtension=False),
-    JDKDeployedDist('GRAAL_TRUFFLE', isExtension=False)
+    JDKDeployedDist('TRUFFLE'),
+    JDKDeployedDist('GRAAL_LOADER'),
+    JDKDeployedDist('GRAAL', isGraalClassLoader=True),
+    JDKDeployedDist('GRAAL_TRUFFLE', isGraalClassLoader=True)
 ]
 
 JDK_UNIX_PERMISSIONS_DIR = 0755
@@ -483,7 +484,7 @@
         for jdkDist in _jdkDeployedDists:
             dist = mx.distribution(jdkDist.name)
             if exists(dist.path):
-                _installDistInJdks(dist, jdkDist.isExtension)
+                _installDistInJdks(jdkDist)
 
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
@@ -593,14 +594,13 @@
         shutil.move(tmp, dstLib)
         os.chmod(dstLib, permissions)
 
-def _installDistInJdksExt(dist):
-    _installDistInJdks(dist, True)
-
-def _installDistInJdks(dist, ext=False):
+def _installDistInJdks(deployableDist):
     """
     Installs the jar(s) for a given Distribution into all existing Graal JDKs
     """
 
+    dist = mx.distribution(deployableDist.name)
+
     if dist.name == 'GRAAL_TRUFFLE':
         # The content in graalRuntime.inline.hpp is generated from Graal
         # classes that implement com.oracle.graal.api.runtime.Service
@@ -614,12 +614,28 @@
     if exists(jdks):
         for e in os.listdir(jdks):
             jreLibDir = join(jdks, e, 'jre', 'lib')
-            if ext:
+            if deployableDist.isExtension:
                 jreLibDir = join(jreLibDir, 'ext')
             if exists(jreLibDir):
                 _copyToJdk(dist.path, jreLibDir)
                 if dist.sourcesPath:
                     _copyToJdk(dist.sourcesPath, join(jdks, e))
+                if deployableDist.isGraalClassLoader:
+                    assert not deployableDist.isExtension
+                    # deploy services files
+                    jreGraalServicesDir = join(jreLibDir, 'graal', 'services')
+                    if not exists(jreGraalServicesDir):
+                        os.makedirs(jreGraalServicesDir)
+                    with zipfile.ZipFile(dist.path) as zf:
+                        for member in zf.namelist():
+                            if not member.startswith('META-INF/services'):
+                                continue
+                            serviceName = basename(member)
+                            # we don't handle directories
+                            assert serviceName
+                            target = join(jreGraalServicesDir, serviceName)
+                            with zf.open(member) as serviceFile, open(target, "w+") as targetFile:
+                                shutil.copyfileobj(serviceFile, targetFile)
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
@@ -2556,7 +2572,10 @@
     _vm_prefix = opts.vm_prefix
 
     for jdkDist in _jdkDeployedDists:
-        if jdkDist.isExtension:
-            mx.distribution(jdkDist.name).add_update_listener(_installDistInJdksExt)
-        else:
-            mx.distribution(jdkDist.name).add_update_listener(_installDistInJdks)
+        def _close(jdkDeployable):
+            def _install(dist):
+                mx.log("install " + dist.name)
+                assert dist.name == jdkDeployable.name, dist.name + "!=" + jdkDeployable.name
+                _installDistInJdks(jdkDeployable)
+            return _install
+        mx.distribution(jdkDist.name).add_update_listener(_close(jdkDist))
--- a/src/share/vm/graal/graalRuntime.cpp	Wed Apr 15 17:14:56 2015 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Apr 15 18:21:00 2015 +0200
@@ -630,9 +630,10 @@
   return GraalRuntime::get_HotSpotGraalRuntime_jobject();
 JVM_END
 
-// private static String[] Graal.getServiceImpls(Class service)
+// private static String[] Services.getServiceImpls(Class service)
 JVM_ENTRY(jobject, JVM_GetGraalServiceImpls(JNIEnv *env, jclass c, jclass serviceClass))
   HandleMark hm;
+  ResourceMark rm;
   KlassHandle serviceKlass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(serviceClass)));
   return JNIHandles::make_local(THREAD, GraalRuntime::get_service_impls(serviceKlass, THREAD)());
 JVM_END
@@ -1074,4 +1075,65 @@
   return klass;
 }
 
+Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {
+  const char* home = Arguments::get_java_home();
+  const char* serviceName = serviceKlass->external_name();
+  size_t path_len = strlen(home) + strlen("/lib/graal/services/") + strlen(serviceName) + 1;
+  char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
+  char sep = os::file_separator()[0];
+  sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName);
+  struct stat st;
+  if (os::stat(path, &st) == 0) {
+    int file_handle = os::open(path, 0, 0);
+    if (file_handle != -1) {
+      char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size + 1);
+      int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
+      if (num_read == -1) {
+        warning("Error reading file %s due to %s", path, strerror(errno));
+      } else if (num_read != st.st_size) {
+        warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
+      }
+      os::close(file_handle);
+      if (num_read == st.st_size) {
+        buffer[num_read] = '\0';
+        GrowableArray<char*>* implNames = new GrowableArray<char*>();
+        char* line = buffer;
+        while (line - buffer < num_read) {
+          char* nl = strchr(line, '\n');
+          if (nl != NULL) {
+            *nl = '\0';
+          }
+          // Turn all '.'s into '/'s
+          for (size_t index = 0; line[index] != '\0'; index++) {
+            if (line[index] == '.') {
+              line[index] = '/';
+            }
+          }
+          implNames->append(line);
+          if (nl != NULL) {
+            line = nl + 1;
+          } else {
+            // File without newline at the end
+            break;
+          }
+        }
+
+        objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH);
+        objArrayHandle services(THREAD, servicesOop);
+        for (int i = 0; i < implNames->length(); ++i) {
+          char* implName = implNames->at(i);
+          Handle service = create_Service(implName, CHECK_NH);
+          services->obj_at_put(i, service());
+        }
+        return services;
+      }
+    } else {
+      warning("Error opening file %s due to %s", path, strerror(errno));
+    }
+  } else {
+    warning("Error opening file %s due to %s", path, strerror(errno));
+  }
+  return Handle();
+}
+
 #include "graalRuntime.inline.hpp"