src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java
changeset 58877 aec7bf35d6f5
parent 58299 6df94ce3ab2f
child 59095 03fbcd06b4c0
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu Oct 31 14:23:06 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu Oct 31 16:54:16 2019 -0700
@@ -46,7 +46,6 @@
 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
-import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.common.SuppressFBWarnings;
 import org.graalvm.compiler.debug.Assertions;
@@ -55,6 +54,7 @@
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
+import org.graalvm.compiler.nodes.spi.Replacements;
 
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -175,21 +175,25 @@
     }
 
     /**
-     * Utility for {@linkplain InvocationPlugins#register(InvocationPlugin, Class, String, Class...)
-     * registration} of invocation plugins.
+     * Utility for {@linkplain InvocationPlugins#register registration} of invocation plugins.
      */
-    public static class Registration implements MethodSubstitutionRegistry {
+    public static class Registration {
 
         private final InvocationPlugins plugins;
+
         private final Type declaringType;
-        private final BytecodeProvider methodSubstitutionBytecodeProvider;
+        private final Replacements replacements;
+        private final BytecodeProvider bytecodeProvider;
         private boolean allowOverwrite;
 
-        @Override
         public Class<?> getReceiverType() {
             return Receiver.class;
         }
 
+        public Type getDeclaringType() {
+            return declaringType;
+        }
+
         /**
          * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
          * given class.
@@ -201,7 +205,8 @@
         public Registration(InvocationPlugins plugins, Type declaringType) {
             this.plugins = plugins;
             this.declaringType = declaringType;
-            this.methodSubstitutionBytecodeProvider = null;
+            this.replacements = null;
+            this.bytecodeProvider = null;
         }
 
         /**
@@ -211,13 +216,29 @@
          * @param plugins where to register the plugins
          * @param declaringType the class declaring the methods for which plugins will be registered
          *            via this object
-         * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for
-         *            method substitutions
+         * @param replacements the current Replacements provider
          */
-        public Registration(InvocationPlugins plugins, Type declaringType, BytecodeProvider methodSubstitutionBytecodeProvider) {
+        public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements) {
             this.plugins = plugins;
             this.declaringType = declaringType;
-            this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider;
+            this.replacements = replacements;
+            this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null;
+        }
+
+        /**
+         * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
+         * given class.
+         *
+         * @param plugins where to register the plugins
+         * @param declaringType the class declaring the methods for which plugins will be registered
+         *            via this object
+         * @param replacements the current Replacements provider
+         */
+        public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements, BytecodeProvider bytecodeProvider) {
+            this.plugins = plugins;
+            this.declaringType = declaringType;
+            this.replacements = replacements;
+            this.bytecodeProvider = bytecodeProvider;
         }
 
         /**
@@ -231,7 +252,8 @@
         public Registration(InvocationPlugins plugins, String declaringClassName) {
             this.plugins = plugins;
             this.declaringType = new OptionalLazySymbol(declaringClassName);
-            this.methodSubstitutionBytecodeProvider = null;
+            this.replacements = null;
+            this.bytecodeProvider = null;
         }
 
         /**
@@ -241,13 +263,13 @@
          * @param plugins where to register the plugins
          * @param declaringClassName the name of the class class declaring the methods for which
          *            plugins will be registered via this object
-         * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for
-         *            method substitutions
+         * @param replacements the current Replacements provider
          */
-        public Registration(InvocationPlugins plugins, String declaringClassName, BytecodeProvider methodSubstitutionBytecodeProvider) {
+        public Registration(InvocationPlugins plugins, String declaringClassName, Replacements replacements) {
             this.plugins = plugins;
             this.declaringType = new OptionalLazySymbol(declaringClassName);
-            this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider;
+            this.replacements = replacements;
+            this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null;
         }
 
         /**
@@ -339,6 +361,118 @@
         }
 
         /**
+         * Registers a plugin for a method with no arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional0(boolean isEnabled, String name, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 1 argument that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional1(boolean isEnabled, String name, Type arg, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 2 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional2(boolean isEnabled, String name, Type arg1, Type arg2, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 3 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional3(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 4 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional4(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 5 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional5(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 6 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional6(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6);
+            }
+        }
+
+        /**
+         * Registers a plugin for a method with 7 arguments that is conditionally enabled. This
+         * ensures that {@code Replacements} is aware of this plugin.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void registerConditional7(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) {
+            replacements.registerConditionalPlugin(plugin);
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+            }
+        }
+
+        /**
          * Registers a plugin for an optional method with no arguments.
          *
          * @param name the name of the method
@@ -398,7 +532,6 @@
          *            is non-static. Upon returning, element 0 will have been rewritten to
          *            {@code declaringClass}
          */
-        @Override
         public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, Type... argumentTypes) {
             registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes);
         }
@@ -407,25 +540,63 @@
          * Registers a plugin that implements a method based on the bytecode of a substitute method.
          *
          * @param substituteDeclaringClass the class declaring the substitute method
-         * @param name the name of both the original method
+         * @param name the name of the original method
          * @param substituteName the name of the substitute 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}
          */
-        @Override
         public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) {
-            MethodSubstitutionPlugin plugin = createMethodSubstitution(substituteDeclaringClass, substituteName, argumentTypes);
-            plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes);
+            doMethodSubstitutionRegistration(false, true, substituteDeclaringClass, name, substituteName, argumentTypes);
+        }
+
+        /**
+         * Registers a plugin that implements a method based on the bytecode of a substitute method
+         * that is conditinally enabled. This ensures that {@code Replacements} is aware of this
+         * plugin.
+         *
+         * @param isEnabled whether the plugin is enabled in the current compiler
+         * @param substituteDeclaringClass the class declaring the substitute method
+         * @param name the name of both the original and substitute 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 registerConditionalMethodSubstitution(boolean isEnabled, Class<?> substituteDeclaringClass, String name, Type... argumentTypes) {
+            registerConditionalMethodSubstitution(isEnabled, substituteDeclaringClass, name, name, argumentTypes);
         }
 
-        public MethodSubstitutionPlugin createMethodSubstitution(Class<?> substituteDeclaringClass, String substituteName, Type... argumentTypes) {
-            assert methodSubstitutionBytecodeProvider != null : "Registration used for method substitutions requires a non-null methodSubstitutionBytecodeProvider";
-            MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(methodSubstitutionBytecodeProvider, substituteDeclaringClass, substituteName, argumentTypes);
-            return plugin;
+        /**
+         * Registers a plugin that implements a method based on the bytecode of a substitute method
+         * that is conditinally enabled. This ensures that {@code Replacements} is aware of this
+         * plugin.
+         *
+         * @param isEnabled whether the plugin is enabled in the current compiler
+         * @param substituteDeclaringClass the class declaring the substitute method
+         * @param name the name of the original method
+         * @param substituteName the name of the substitute 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 registerConditionalMethodSubstitution(boolean isEnabled, Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) {
+            doMethodSubstitutionRegistration(true, isEnabled, substituteDeclaringClass, name, substituteName, argumentTypes);
         }
 
+        private void doMethodSubstitutionRegistration(boolean isConditional, boolean isEnabled, Class<?> substituteDeclaringClass, String name, String substituteName, Type[] argumentTypes) {
+            MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(this, bytecodeProvider, name, substituteDeclaringClass, substituteName, argumentTypes);
+            replacements.registerMethodSubstitution(plugin);
+            if (isConditional) {
+                // Notify Replacements about the plugin even if it's not current enabled
+                replacements.registerConditionalPlugin(plugin);
+            }
+            if (isEnabled) {
+                plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes);
+            }
+        }
     }
 
     /**
@@ -519,13 +690,7 @@
             this.plugin = data;
             this.isStatic = isStatic;
             this.name = name;
-            StringBuilder buf = new StringBuilder();
-            buf.append('(');
-            for (int i = isStatic ? 0 : 1; i < argumentTypes.length; i++) {
-                buf.append(MetaUtil.toInternalName(argumentTypes[i].getTypeName()));
-            }
-            buf.append(')');
-            this.argumentsDescriptor = buf.toString();
+            this.argumentsDescriptor = toArgumentDescriptor(isStatic, argumentTypes);
             assert !name.equals("<init>") || !isStatic : this;
         }
 
@@ -546,6 +711,16 @@
         }
     }
 
+    static String toArgumentDescriptor(boolean isStatic, Type[] argumentTypes) {
+        StringBuilder buf = new StringBuilder();
+        buf.append('(');
+        for (int i = isStatic ? 0 : 1; i < argumentTypes.length; i++) {
+            buf.append(MetaUtil.toInternalName(argumentTypes[i].getTypeName()));
+        }
+        buf.append(')');
+        return buf.toString();
+    }
+
     /**
      * Plugin registrations for already resolved methods. If non-null, then {@link #registrations}
      * is null and no further registrations can be made.