src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java
changeset 54084 84f10bbf993f
parent 52910 583fd71c47d6
child 54601 c40b2a190173
equal deleted inserted replaced
54083:d9bcf74fc56a 54084:84f10bbf993f
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.nodes.graphbuilderconf;
    25 package org.graalvm.compiler.nodes.graphbuilderconf;
    26 
    26 
    27 import static java.lang.String.format;
    27 import static java.lang.String.format;
       
    28 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
       
    29 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
    28 import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.LateClassPlugins.CLOSED_LATE_CLASS_PLUGIN;
    30 import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.LateClassPlugins.CLOSED_LATE_CLASS_PLUGIN;
    29 
    31 
    30 import java.lang.reflect.Constructor;
    32 import java.lang.reflect.Constructor;
    31 import java.lang.reflect.Method;
    33 import java.lang.reflect.Method;
    32 import java.lang.reflect.Modifier;
    34 import java.lang.reflect.Modifier;
   142         private final String name;
   144         private final String name;
   143         private Class<?> resolved;
   145         private Class<?> resolved;
   144 
   146 
   145         OptionalLazySymbol(String name) {
   147         OptionalLazySymbol(String name) {
   146             this.name = name;
   148             this.name = name;
       
   149             if (IS_BUILDING_NATIVE_IMAGE) {
       
   150                 resolve();
       
   151             }
   147         }
   152         }
   148 
   153 
   149         @Override
   154         @Override
   150         public String getTypeName() {
   155         public String getTypeName() {
   151             return name;
   156             return name;
   154         /**
   159         /**
   155          * Gets the resolved {@link Class} corresponding to this symbol or {@code null} if
   160          * Gets the resolved {@link Class} corresponding to this symbol or {@code null} if
   156          * resolution fails.
   161          * resolution fails.
   157          */
   162          */
   158         public Class<?> resolve() {
   163         public Class<?> resolve() {
   159             if (resolved == null) {
   164             if (!IS_IN_NATIVE_IMAGE && resolved == null) {
   160                 Class<?> resolvedOrNull = resolveClass(name, true);
   165                 Class<?> resolvedOrNull = resolveClass(name, true);
   161                 resolved = resolvedOrNull == null ? MASK_NULL : resolvedOrNull;
   166                 resolved = resolvedOrNull == null ? MASK_NULL : resolvedOrNull;
   162             }
   167             }
   163             return resolved == MASK_NULL ? null : resolved;
   168             return resolved == MASK_NULL ? null : resolved;
   164         }
   169         }
   211          */
   216          */
   212         public Registration(InvocationPlugins plugins, Type declaringType, BytecodeProvider methodSubstitutionBytecodeProvider) {
   217         public Registration(InvocationPlugins plugins, Type declaringType, BytecodeProvider methodSubstitutionBytecodeProvider) {
   213             this.plugins = plugins;
   218             this.plugins = plugins;
   214             this.declaringType = declaringType;
   219             this.declaringType = declaringType;
   215             this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider;
   220             this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider;
       
   221         }
       
   222 
       
   223         /**
       
   224          * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
       
   225          * given class.
       
   226          *
       
   227          * @param plugins where to register the plugins
       
   228          * @param declaringClassName the name of the class class declaring the methods for which
       
   229          *            plugins will be registered via this object
       
   230          */
       
   231         public Registration(InvocationPlugins plugins, String declaringClassName) {
       
   232             this.plugins = plugins;
       
   233             this.declaringType = new OptionalLazySymbol(declaringClassName);
       
   234             this.methodSubstitutionBytecodeProvider = null;
   216         }
   235         }
   217 
   236 
   218         /**
   237         /**
   219          * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
   238          * Creates an object for registering {@link InvocationPlugin}s for methods declared by a
   220          * given class.
   239          * given class.
   450 
   469 
   451             assert isStatic || argumentTypes[0] == declaringType;
   470             assert isStatic || argumentTypes[0] == declaringType;
   452             Binding binding = new Binding(plugin, isStatic, name, argumentTypes);
   471             Binding binding = new Binding(plugin, isStatic, name, argumentTypes);
   453             bindings.add(binding);
   472             bindings.add(binding);
   454 
   473 
   455             assert Checks.check(this.plugins, declaringType, binding);
   474             assert IS_IN_NATIVE_IMAGE || Checks.check(this.plugins, declaringType, binding);
   456             assert Checks.checkResolvable(false, declaringType, binding);
   475             assert IS_IN_NATIVE_IMAGE || Checks.checkResolvable(false, declaringType, binding);
   457         }
   476         }
   458 
   477 
   459         @Override
   478         @Override
   460         public void close() {
   479         public void close() {
   461             assert plugins != null : String.format("Late registrations of invocation plugins for %s is already closed", declaringType);
   480             assert plugins != null : String.format("Late registrations of invocation plugins for %s is already closed", declaringType);
   734         }
   753         }
   735         return null;
   754         return null;
   736     }
   755     }
   737 
   756 
   738     @SuppressWarnings("serial")
   757     @SuppressWarnings("serial")
   739     static class InvocationPlugRegistrationError extends GraalError {
   758     static class InvocationPluginRegistrationError extends GraalError {
   740         InvocationPlugRegistrationError(Throwable cause) {
   759         InvocationPluginRegistrationError(Throwable cause) {
   741             super(cause);
   760             super(cause);
   742         }
   761         }
   743     }
   762     }
   744 
   763 
   745     private void flushDeferrables() {
   764     private void flushDeferrables() {
   749                     try {
   768                     try {
   750                         for (Runnable deferrable : deferredRegistrations) {
   769                         for (Runnable deferrable : deferredRegistrations) {
   751                             deferrable.run();
   770                             deferrable.run();
   752                         }
   771                         }
   753                         deferredRegistrations = null;
   772                         deferredRegistrations = null;
   754                     } catch (InvocationPlugRegistrationError t) {
   773                     } catch (InvocationPluginRegistrationError t) {
   755                         throw t;
   774                         throw t;
   756                     } catch (Throwable t) {
   775                     } catch (Throwable t) {
   757                         /*
   776                         /*
   758                          * Something went wrong during registration but it's possible we'll end up
   777                          * Something went wrong during registration but it's possible we'll end up
   759                          * coming back into this code. nulling out deferredRegistrations would just
   778                          * coming back into this code. nulling out deferredRegistrations would just
   763                          */
   782                          */
   764                         deferredRegistrations.clear();
   783                         deferredRegistrations.clear();
   765                         Runnable rethrow = new Runnable() {
   784                         Runnable rethrow = new Runnable() {
   766                             @Override
   785                             @Override
   767                             public void run() {
   786                             public void run() {
   768                                 throw new InvocationPlugRegistrationError(t);
   787                                 throw new InvocationPluginRegistrationError(t);
   769                             }
   788                             }
   770                         };
   789                         };
   771                         deferredRegistrations.add(rethrow);
   790                         deferredRegistrations.add(rethrow);
   772                         rethrow.run();
   791                         rethrow.run();
   773                     }
   792                     }
   958         boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
   977         boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class;
   959         if (!isStatic) {
   978         if (!isStatic) {
   960             argumentTypes[0] = declaringClass;
   979             argumentTypes[0] = declaringClass;
   961         }
   980         }
   962         Binding binding = put(plugin, isStatic, allowOverwrite, declaringClass, name, argumentTypes);
   981         Binding binding = put(plugin, isStatic, allowOverwrite, declaringClass, name, argumentTypes);
   963         assert Checks.check(this, declaringClass, binding);
   982         assert IS_IN_NATIVE_IMAGE || Checks.check(this, declaringClass, binding);
   964         assert Checks.checkResolvable(isOptional, declaringClass, binding);
   983         assert IS_IN_NATIVE_IMAGE || Checks.checkResolvable(isOptional, declaringClass, binding);
   965     }
   984     }
   966 
   985 
   967     /**
   986     /**
   968      * Registers an invocation plugin for a given method. There must be no plugin currently
   987      * Registers an invocation plugin for a given method. There must be no plugin currently
   969      * registered for {@code method}.
   988      * registered for {@code method}.
  1002      */
  1021      */
  1003     public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
  1022     public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
  1004         if (parent != null) {
  1023         if (parent != null) {
  1005             InvocationPlugin plugin = parent.lookupInvocation(method);
  1024             InvocationPlugin plugin = parent.lookupInvocation(method);
  1006             if (plugin != null) {
  1025             if (plugin != null) {
       
  1026                 if (IS_IN_NATIVE_IMAGE && plugin instanceof MethodSubstitutionPlugin) {
       
  1027                     // Disable method substitutions until GR-13607
       
  1028                     return null;
       
  1029                 }
  1007                 return plugin;
  1030                 return plugin;
  1008             }
  1031             }
  1009         }
  1032         }
  1010         return get(method);
  1033         InvocationPlugin invocationPlugin = get(method);
       
  1034         if (IS_IN_NATIVE_IMAGE && invocationPlugin instanceof MethodSubstitutionPlugin) {
       
  1035             // Disable method substitutions until GR-13607
       
  1036             return null;
       
  1037         }
       
  1038         return invocationPlugin;
  1011     }
  1039     }
  1012 
  1040 
  1013     /**
  1041     /**
  1014      * Gets the set of registered invocation plugins.
  1042      * Gets the set of registered invocation plugins.
  1015      *
  1043      *
  1139          * The set of all {@link InvocationPlugin#apply} method signatures.
  1167          * The set of all {@link InvocationPlugin#apply} method signatures.
  1140          */
  1168          */
  1141         static final Class<?>[][] SIGS;
  1169         static final Class<?>[][] SIGS;
  1142 
  1170 
  1143         static {
  1171         static {
  1144             if (!Assertions.assertionsEnabled()) {
  1172             if (!Assertions.assertionsEnabled() && !IS_BUILDING_NATIVE_IMAGE) {
  1145                 throw new GraalError("%s must only be used in assertions", Checks.class.getName());
  1173                 throw new GraalError("%s must only be used in assertions", Checks.class.getName());
  1146             }
  1174             }
  1147             ArrayList<Class<?>[]> sigs = new ArrayList<>(MAX_ARITY);
  1175             ArrayList<Class<?>[]> sigs = new ArrayList<>(MAX_ARITY);
  1148             for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
  1176             if (!IS_IN_NATIVE_IMAGE) {
  1149                 if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) {
  1177                 for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
  1150                     Class<?>[] sig = method.getParameterTypes();
  1178                     if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) {
  1151                     assert sig[0] == GraphBuilderContext.class;
  1179                         Class<?>[] sig = method.getParameterTypes();
  1152                     assert sig[1] == ResolvedJavaMethod.class;
  1180                         assert sig[0] == GraphBuilderContext.class;
  1153                     assert sig[2] == InvocationPlugin.Receiver.class;
  1181                         assert sig[1] == ResolvedJavaMethod.class;
  1154                     assert Arrays.asList(sig).subList(3, sig.length).stream().allMatch(c -> c == ValueNode.class);
  1182                         assert sig[2] == InvocationPlugin.Receiver.class;
  1155                     while (sigs.size() < sig.length - 2) {
  1183                         assert Arrays.asList(sig).subList(3, sig.length).stream().allMatch(c -> c == ValueNode.class);
  1156                         sigs.add(null);
  1184                         while (sigs.size() < sig.length - 2) {
       
  1185                             sigs.add(null);
       
  1186                         }
       
  1187                         sigs.set(sig.length - 3, sig);
  1157                     }
  1188                     }
  1158                     sigs.set(sig.length - 3, sig);
  1189                 }
  1159                 }
  1190                 assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null),
  1160             }
  1191                                 ValueNode.class.getSimpleName());
  1161             assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null),
  1192             }
  1162                             ValueNode.class.getSimpleName());
       
  1163             SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
  1193             SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
  1164         }
  1194         }
  1165 
  1195 
  1166         static boolean containsBinding(InvocationPlugins p, Type declaringType, Binding key) {
  1196         static boolean containsBinding(InvocationPlugins p, Type declaringType, Binding key) {
  1167             String internalName = MetaUtil.toInternalName(declaringType.getTypeName());
  1197             String internalName = MetaUtil.toInternalName(declaringType.getTypeName());
  1273         if (type instanceof Class) {
  1303         if (type instanceof Class) {
  1274             return (Class<?>) type;
  1304             return (Class<?>) type;
  1275         }
  1305         }
  1276         if (type instanceof OptionalLazySymbol) {
  1306         if (type instanceof OptionalLazySymbol) {
  1277             return ((OptionalLazySymbol) type).resolve();
  1307             return ((OptionalLazySymbol) type).resolve();
       
  1308         }
       
  1309         if (IS_IN_NATIVE_IMAGE) {
       
  1310             throw new GraalError("Unresolved type in native image image:" + type.getTypeName());
  1278         }
  1311         }
  1279         return resolveClass(type.getTypeName(), optional);
  1312         return resolveClass(type.getTypeName(), optional);
  1280     }
  1313     }
  1281 
  1314 
  1282     private static List<String> toInternalTypeNames(Class<?>[] types) {
  1315     private static List<String> toInternalTypeNames(Class<?>[] types) {