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; |
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); |
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 |
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) { |