changeset 22111:3f83cc877a0e

Add support so methods for invocation plugins can be optional; add support for new unaligned Unsafe methods in JDK 9.
author twisti
date Fri, 26 Jun 2015 17:11:34 -0700
parents e11e05cc0f2e
children 91b8a0d1abc5
files graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/MethodIdMap.java
diffstat 5 files changed, 94 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java	Fri Jun 26 20:35:08 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java	Fri Jun 26 17:11:34 2015 -0700
@@ -38,8 +38,8 @@
 
     /**
      * The receiver in a non-static method. The class literal for this interface must be used with
-     * {@link MethodIdMap#put(Object, boolean, Class, String, Class...)} to denote the receiver
-     * argument for such a non-static method.
+     * {@link MethodIdMap#put(Object, boolean, boolean, Class, String, Class...)} to denote the
+     * receiver argument for such a non-static method.
      */
     public interface Receiver {
         /**
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java	Fri Jun 26 20:35:08 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java	Fri Jun 26 17:11:34 2015 -0700
@@ -159,6 +159,26 @@
         }
 
         /**
+         * Registers a plugin for an optional method with 3 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerOptional3(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, InvocationPlugin plugin) {
+            plugins.registerOptional(plugin, declaringClass, name, arg1, arg2, arg3);
+        }
+
+        /**
+         * Registers a plugin for an optional method with 4 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerOptional4(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, Class<?> arg4, InvocationPlugin plugin) {
+            plugins.registerOptional(plugin, declaringClass, name, arg1, arg2, arg3, arg4);
+        }
+
+        /**
          * Registers a plugin that implements a method based on the bytecode of a substitute method.
          *
          * @param substituteDeclaringClass the class declaring the substitute method
@@ -203,6 +223,15 @@
         this(null, metaAccess);
     }
 
+    private void register(InvocationPlugin plugin, boolean isOptional, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
+        boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
+        if (!isStatic) {
+            argumentTypes[0] = declaringClass;
+        }
+        MethodKey<InvocationPlugin> methodInfo = plugins.put(plugin, isStatic, isOptional, declaringClass, name, argumentTypes);
+        assert Checker.check(this, methodInfo, plugin);
+    }
+
     /**
      * Registers an invocation plugin for a given method. There must be no plugin currently
      * registered for {@code method}.
@@ -213,12 +242,20 @@
      *            {@code declaringClass}
      */
     public void register(InvocationPlugin plugin, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
-        boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
-        if (!isStatic) {
-            argumentTypes[0] = declaringClass;
-        }
-        MethodKey<InvocationPlugin> methodInfo = plugins.put(plugin, isStatic, declaringClass, name, argumentTypes);
-        assert Checker.check(this, methodInfo, plugin);
+        register(plugin, false, declaringClass, name, argumentTypes);
+    }
+
+    /**
+     * Registers an invocation plugin for a given, optional method. There must be no plugin
+     * currently registered for {@code method}.
+     *
+     * @param argumentTypes the argument types of the method. Element 0 of this array must be the
+     *            {@link Class} value for {@link InvocationPlugin.Receiver} iff the method is
+     *            non-static. Upon returning, element 0 will have been rewritten to
+     *            {@code declaringClass}
+     */
+    public void registerOptional(InvocationPlugin plugin, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
+        register(plugin, true, declaringClass, name, argumentTypes);
     }
 
     /**
@@ -265,6 +302,7 @@
          * The set of all {@link InvocationPlugin#apply} method signatures.
          */
         static final Class<?>[][] SIGS;
+
         static {
             ArrayList<Class<?>[]> sigs = new ArrayList<>(MAX_ARITY);
             for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java	Fri Jun 26 20:35:08 2015 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java	Fri Jun 26 17:11:34 2015 -0700
@@ -37,6 +37,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.memory.address.*;
 import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.StandardGraphBuilderPlugins.*;
 
 public class AMD64GraphBuilderPlugins {
 
@@ -133,5 +134,11 @@
                 });
             }
         }
+
+        for (Kind kind : new Kind[]{Kind.Char, Kind.Short, Kind.Int, Kind.Long}) {
+            Class<?> javaClass = kind.toJavaClass();
+            r.registerOptional3("get" + kind.name() + "Unaligned", Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, false));
+            r.registerOptional4("put" + kind.name() + "Unaligned", Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, false));
+        }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Fri Jun 26 20:35:08 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Fri Jun 26 17:11:34 2015 -0700
@@ -555,7 +555,7 @@
         }
     }
 
-    static class UnsafePutPlugin implements InvocationPlugin {
+    public static class UnsafePutPlugin implements InvocationPlugin {
 
         private final Kind kind;
         private final boolean isVolatile;
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/MethodIdMap.java	Fri Jun 26 20:35:08 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/MethodIdMap.java	Fri Jun 26 17:11:34 2015 -0700
@@ -48,20 +48,28 @@
      */
     public static class MethodKey<T> {
         final boolean isStatic;
+
+        /**
+         * This method is optional. This is used for new API methods not present in previous JDK
+         * versions.
+         */
+        final boolean isOptional;
+
         final Class<?> declaringClass;
         final String name;
         final Class<?>[] argumentTypes;
         final T value;
         int id;
 
-        MethodKey(T data, boolean isStatic, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
+        MethodKey(T data, boolean isStatic, boolean isOptional, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
             assert isStatic || argumentTypes[0] == declaringClass;
             this.value = data;
             this.isStatic = isStatic;
+            this.isOptional = isOptional;
             this.declaringClass = declaringClass;
             this.name = name;
             this.argumentTypes = argumentTypes;
-            assert resolveJava() != null;
+            assert isOptional || resolveJava() != null;
         }
 
         @Override
@@ -86,7 +94,11 @@
         }
 
         private MethodIdHolder resolve(MetaAccessProvider metaAccess) {
-            return (MethodIdHolder) metaAccess.lookupJavaMethod(resolveJava());
+            Executable method = resolveJava();
+            if (method == null) {
+                return null;
+            }
+            return (MethodIdHolder) metaAccess.lookupJavaMethod(method);
         }
 
         private Executable resolveJava() {
@@ -101,6 +113,9 @@
                 assert Modifier.isStatic(res.getModifiers()) == isStatic;
                 return res;
             } catch (NoSuchMethodException | SecurityException e) {
+                if (isOptional) {
+                    return null;
+                }
                 throw new InternalError(e);
             }
         }
@@ -149,15 +164,16 @@
      *
      * @param value value to be associated with the specified method
      * @param isStatic specifies if the method is static
+     * @param isOptional specifies if the method is optional
      * @param declaringClass the class declaring the method
      * @param name the name of the method
      * @param argumentTypes the argument types of the method. Element 0 of this array must be
      *            {@code declaringClass} iff the method is non-static.
      * @return an object representing the method
      */
-    public MethodKey<V> put(V value, boolean isStatic, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
+    public MethodKey<V> put(V value, boolean isStatic, boolean isOptional, Class<?> declaringClass, String name, Class<?>... argumentTypes) {
         assert isStatic || argumentTypes[0] == declaringClass;
-        MethodKey<V> methodKey = new MethodKey<>(value, isStatic, declaringClass, name, argumentTypes);
+        MethodKey<V> methodKey = new MethodKey<>(value, isStatic, isOptional, declaringClass, name, argumentTypes);
         assert entries == null : "registration is closed";
         assert !registrations.contains(methodKey) : "a value is already registered for " + methodKey;
         registrations.add(methodKey);
@@ -199,21 +215,30 @@
                         int max = Integer.MIN_VALUE;
                         for (MethodKey<V> methodKey : registrations) {
                             MethodIdHolder m = methodKey.resolve(metaAccess);
-                            int id = idAllocator.assignId(m);
-                            if (id < minId) {
-                                minId = id;
+                            if (m == null) {
+                                assert methodKey.isOptional;
+                                methodKey.id = -1;
+                            } else {
+                                int id = idAllocator.assignId(m);
+                                if (id < minId) {
+                                    minId = id;
+                                }
+                                if (id > max) {
+                                    max = id;
+                                }
+                                methodKey.id = id;
                             }
-                            if (id > max) {
-                                max = id;
-                            }
-                            methodKey.id = id;
                         }
 
                         int length = (max - minId) + 1;
                         entries = allocateEntries(length);
-                        for (MethodKey<V> m : registrations) {
-                            int index = m.id - minId;
-                            entries[index] = m.value;
+                        for (MethodKey<V> methodKey : registrations) {
+                            if (methodKey.id == -1) {
+                                assert methodKey.isOptional;
+                            } else {
+                                int index = methodKey.id - minId;
+                                entries[index] = methodKey.value;
+                            }
                         }
                     }
                 }