From f35ce5a1bee6c3e3f89f630b0a3a9168f71b31e3 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 7 Jan 2025 11:10:03 -0800 Subject: [PATCH] Use plugin class name to filter fold plugin application --- .../processor/GeneratedFoldPlugin.java | 157 +++++++----------- .../GeneratedNodeIntrinsicPlugin.java | 22 ++- .../processor/GeneratedPlugin.java | 28 +--- .../processor/PluginGenerator.java | 3 - .../compiler/hotspot/libgraal/BuildTime.java | 9 +- .../compiler/nodes/PluginReplacementNode.java | 24 ++- .../PluginReplacementWithExceptionNode.java | 6 +- .../GeneratedFoldInvocationPlugin.java | 11 ++ .../GeneratedInvocationPlugin.java | 59 +++---- ...eneratedNodeIntrinsicInvocationPlugin.java | 12 +- .../hotspot/libgraal/LibGraalFeature.java | 5 - 11 files changed, 146 insertions(+), 190 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedFoldPlugin.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedFoldPlugin.java index 9da4a75d9ac1..994035452e16 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedFoldPlugin.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedFoldPlugin.java @@ -28,6 +28,7 @@ import static jdk.graal.compiler.replacements.processor.FoldHandler.INJECTED_PARAMETER_CLASS_NAME; import java.io.PrintWriter; +import java.io.StringWriter; import java.util.List; import java.util.Set; import java.util.TreeSet; @@ -66,138 +67,55 @@ public void extraImports(AbstractProcessor processor, Set imports) { imports.add("jdk.vm.ci.meta.JavaConstant"); imports.add("jdk.vm.ci.meta.JavaKind"); imports.add("jdk.graal.compiler.nodes.ConstantNode"); - imports.add("jdk.graal.compiler.core.common.type.Stamp"); } @Override protected void createExecute(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { - List params = intrinsicMethod.getParameters(); - out.printf(" if (b.shouldDeferPlugin(this)) {\n"); out.printf(" b.replacePlugin%s(this, targetMethod, args, %s.FUNCTION);\n", getReplacementFunctionSuffix(processor), getReplacementName()); out.printf(" return true;\n"); out.printf(" }\n"); - int argCount = 0; - Object receiver; - if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { - receiver = intrinsicMethod.getEnclosingElement(); - } else { - receiver = "arg0"; - TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); - constantArgument(processor, out, deps, argCount, type.asType(), argCount, false); - argCount++; - } - - int firstArg = argCount; - for (VariableElement param : params) { - if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { - constantArgument(processor, out, deps, argCount, param.asType(), argCount, false); - } else { + int argCount = intrinsicMethod.getModifiers().contains(Modifier.STATIC) ? 0 : 1; + for (VariableElement param : intrinsicMethod.getParameters()) { + if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) != null) { out.printf(" if (!checkInjectedArgument(b, args[%d], targetMethod)) {\n", argCount); out.printf(" return false;\n"); out.printf(" }\n"); - out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType())); } argCount++; } - Set suppressWarnings = new TreeSet<>(); - if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { - suppressWarnings.add("deprecation"); - } - if (hasRawtypeWarning(intrinsicMethod.getReturnType())) { - suppressWarnings.add("rawtypes"); - } - for (VariableElement param : params) { - if (hasUncheckedWarning(param.asType())) { - suppressWarnings.add("unchecked"); - } - } - if (suppressWarnings.size() > 0) { - out.printf(" @SuppressWarnings({"); - String sep = ""; - for (String suppressWarning : suppressWarnings) { - out.printf("%s\"%s\"", sep, suppressWarning); - sep = ", "; - } - out.printf("})\n"); - } + // Exercise the emission (but swallow generated output) to populate the deps + emitReplace(processor, new PrintWriter(new StringWriter()), deps); - out.printf(" %s result = %s.%s(", getErasedType(intrinsicMethod.getReturnType()), receiver, intrinsicMethod.getSimpleName()); - if (argCount > firstArg) { - out.printf("arg%d", firstArg); - for (int i = firstArg + 1; i < argCount; i++) { - out.printf(", arg%d", i); - } + // Build the list of extra arguments to be passed + StringBuilder extraArguments = new StringBuilder(); + for (InjectedDependencies.Dependency dep : deps) { + extraArguments.append(", ").append(dep.getName(processor, intrinsicMethod)); } - out.printf(");\n"); - - TypeMirror returnType = intrinsicMethod.getReturnType(); - switch (returnType.getKind()) { - case BOOLEAN: - out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); - break; - case BYTE: - case SHORT: - case CHAR: - case INT: - out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); - break; - case LONG: - out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); - break; - case FLOAT: - out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); - break; - case DOUBLE: - out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); - break; - case ARRAY: - case TYPEVAR: - case DECLARED: - if (returnType.equals(processor.getType("java.lang.String"))) { - out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(processor, WellKnownDependency.CONSTANT_REFLECTION)); - } else { - out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(processor, WellKnownDependency.SNIPPET_REFLECTION)); - } - break; - default: - throw new IllegalArgumentException(returnType.toString()); - } - - out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(processor, WellKnownDependency.META_ACCESS), - deps.use(processor, WellKnownDependency.STRUCTURED_GRAPH)); - out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); - out.printf(" return true;\n"); + out.printf(" return doExecute(b, args%s);\n", extraArguments); } - @Override - protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { - out.printf("\n"); - out.printf(" @Override\n"); - out.printf(" public boolean replace(GraphBuilderContext b, Replacements injection, Stamp stamp, NodeInputList args) {\n"); - + private void emitReplace(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { List params = intrinsicMethod.getParameters(); - - int argCount = 0; + final int firstArg = intrinsicMethod.getModifiers().contains(Modifier.STATIC) ? 0 : 1; Object receiver; - if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { + if (firstArg == 0) { receiver = intrinsicMethod.getEnclosingElement(); } else { receiver = "arg0"; TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); - constantArgument(processor, out, deps, argCount, type.asType(), argCount, true); - argCount++; + constantArgument(processor, out, deps, 0, type.asType(), 0, false); } - int firstArg = argCount; + int argCount = firstArg; for (VariableElement param : params) { if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { - constantArgument(processor, out, deps, argCount, param.asType(), argCount, true); + constantArgument(processor, out, deps, argCount, param.asType(), argCount, false); } else { - out.printf(" assert args.get(%d).isNullConstant() : \"Must be null constant \" + args.get(%d);\n", argCount, argCount); - out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.find(processor, (DeclaredType) param.asType()).getExpression(processor, intrinsicMethod)); + out.printf(" assert args[%d].isNullConstant() : \"Must be null constant \" + args[%d];\n", argCount, argCount); + out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType())); } argCount++; } @@ -270,6 +188,43 @@ protected void createHelpers(AbstractProcessor processor, PrintWriter out, Injec deps.use(processor, WellKnownDependency.STRUCTURED_GRAPH)); out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); out.printf(" return true;\n"); + } + + @Override + protected void createPrivateMembersAndConstructor(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, String constructorName) { + // Add declarations for the extra arguments + StringBuilder extraArguments = new StringBuilder(); + for (InjectedDependencies.Dependency dep : deps) { + extraArguments.append(", ").append(dep.getType()).append(" ").append(dep.getName(processor, intrinsicMethod)); + } + out.printf("\n"); + out.printf(" @SuppressWarnings(\"unused\")\n"); + out.printf(" static boolean doExecute(GraphBuilderContext b, ValueNode[] args%s) {\n", extraArguments); + emitReplace(processor, out, deps); + out.printf(" }\n"); + + // This must be done after the code emission above to ensure that deps includes all required + // dependencies. + super.createPrivateMembersAndConstructor(processor, out, deps, constructorName); + } + + @Override + protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + out.printf("\n"); + out.printf(" @Override\n"); + out.printf(" public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, ValueNode[] args) {\n"); + + // Create local declarations for all the injected arguments + for (InjectedDependencies.Dependency dep : deps) { + out.printf(" %s %s = %s;\n", dep.getType(), dep.getName(processor, intrinsicMethod), dep.getExpression(processor, intrinsicMethod)); + } + + // Build the list of extra arguments to be passed + StringBuilder extraArguments = new StringBuilder(); + for (InjectedDependencies.Dependency dep : deps) { + extraArguments.append(", ").append(dep.getName(processor, intrinsicMethod)); + } + out.printf(" return %s.doExecute(b, args%s);\n", getPluginName(), extraArguments); out.printf(" }\n"); } } diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java index 830c2729c09d..b2b12b920b95 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java @@ -62,9 +62,6 @@ protected String pluginSuperclass() { @Override public void extraImports(AbstractProcessor processor, Set imports) { imports.add("jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext"); - if (needsReplacement(processor)) { - imports.add("jdk.graal.compiler.core.common.type.Stamp"); - } } protected abstract List getParameters(); @@ -87,7 +84,7 @@ protected void createExecute(AbstractProcessor processor, PrintWriter out, Injec for (int i = 0; i < signature.length; i++, idx++) { if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(NodeIntrinsicHandler.CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { - String argName = constantArgument(processor, out, deps, idx, signature[i], i, false); + String argName = constantArgument(processor, out, deps, idx, signature[i], i, true); verifyConstantArgument(out, argName, signature[i]); } else { if (signature[i].equals(processor.getType(NodeIntrinsicHandler.VALUE_NODE_CLASS_NAME))) { @@ -199,7 +196,7 @@ protected void verifyConstantArgument(PrintWriter out, String argName, TypeMirro } @Override - protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) { + protected void createOtherClasses(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { if (needsReplacement(processor)) { if (isWithExceptionReplacement(processor)) { /* @@ -212,11 +209,10 @@ protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) out.printf("@ExcludeFromJacocoGeneratedReport(\"deferred plugin support that is only called in libgraal\")\n"); out.printf("final class %s implements PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction {\n", name); out.printf(" static PluginReplacementWithExceptionNode.ReplacementWithExceptionFunction FUNCTION = new %s();\n", name); - InjectedDependencies deps = new InjectedDependencies(false, intrinsicMethod); createHelpers(processor, out, deps); out.printf("}\n"); } else { - super.createOtherClasses(processor, out); + super.createOtherClasses(processor, out, deps); } } } @@ -241,13 +237,15 @@ protected boolean needsReplacement(AbstractProcessor processor) { } @Override - protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies originalDeps) { if (!needsReplacement(processor)) { return; } + // In this context all values must be retrieved from the injection argument + InjectedDependencies deps = new InjectedDependencies(false, intrinsicMethod); out.printf("\n"); out.printf(" @Override\n"); - out.printf(" public boolean replace(GraphBuilderContext b, Replacements injection, Stamp stamp, NodeInputList args) {\n"); + out.printf(" public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, ValueNode[] args) {\n"); List params = getParameters(); @@ -263,12 +261,12 @@ protected void createHelpers(AbstractProcessor processor, PrintWriter out, Injec for (int i = 0; i < signature.length; i++, idx++) { if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(NodeIntrinsicHandler.CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { - constantArgument(processor, out, deps, idx, signature[i], i, true); + constantArgument(processor, out, deps, idx, signature[i], i, false); } else { if (signature[i].equals(processor.getType(NodeIntrinsicHandler.VALUE_NODE_CLASS_NAME))) { - out.printf(" ValueNode arg%d = args.get(%d);\n", idx, i); + out.printf(" ValueNode arg%d = args[%d];\n", idx, i); } else { - out.printf(" %s arg%d = (%s) args.get(%d);\n", signature[i], idx, signature[i], i); + out.printf(" %s arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i); } } } diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedPlugin.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedPlugin.java index c21b28381794..aea8ffd96070 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedPlugin.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/GeneratedPlugin.java @@ -66,9 +66,7 @@ public void setPluginName(String pluginName) { this.pluginName = pluginName; } - protected String pluginSuperclass() { - return "GeneratedInvocationPlugin"; - } + protected abstract String pluginSuperclass(); public void generate(AbstractProcessor processor, PrintWriter out) { out.printf("// class: %s\n", intrinsicMethod.getEnclosingElement()); @@ -84,20 +82,15 @@ public void generate(AbstractProcessor processor, PrintWriter out) { InjectedDependencies deps = new InjectedDependencies(true, intrinsicMethod); createExecute(processor, out, deps); out.printf(" }\n"); - out.printf(" @Override\n"); - out.printf(" public Class getSource() {\n"); - out.printf(" return %s.class;\n", getAnnotationClass(processor).getQualifiedName().toString().replace('$', '.')); - out.printf(" }\n"); createPrivateMembersAndConstructor(processor, out, deps, pluginName); out.printf("}\n"); - createOtherClasses(processor, out); - + createOtherClasses(processor, out, deps); } - protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) { + protected void createOtherClasses(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { String name = getReplacementName(); out.printf("// class: %s\n", intrinsicMethod.getEnclosingElement()); out.printf("// method: %s\n", intrinsicMethod); @@ -105,7 +98,6 @@ protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) out.printf("@ExcludeFromJacocoGeneratedReport(\"deferred plugin support that is only called in libgraal\")\n"); out.printf("final class %s implements PluginReplacementNode.ReplacementFunction {\n", name); out.printf(" static PluginReplacementNode.ReplacementFunction FUNCTION = new %s();\n", name); - InjectedDependencies deps = new InjectedDependencies(false, intrinsicMethod); createHelpers(processor, out, deps); out.printf("}\n"); } @@ -187,13 +179,12 @@ static boolean hasUncheckedWarning(TypeMirror type) { } } - protected void createPrivateMembersAndConstructor(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, String constructorName) { + protected void createPrivateMembersAndConstructor(@SuppressWarnings("unused") AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, String constructorName) { if (!deps.isEmpty()) { out.printf("\n"); for (InjectedDependencies.Dependency dep : deps) { out.printf(" private final %s %s;\n", dep.getType(), dep.getName(processor, intrinsicMethod)); } - needInjectionProvider = true; } @@ -258,13 +249,8 @@ protected String constantArgument(AbstractProcessor processor, int argIdx, TypeMirror type, int nodeIdx, - boolean isReplacement) { - Function argFormatter; - if (isReplacement) { - argFormatter = (i) -> String.format("args.get(%d)", i); - } else { - argFormatter = (i) -> String.format("args[%d]", i); - } + boolean checkShouldDefer) { + Function argFormatter = (i) -> String.format("args[%d]", i); if (hasRawtypeWarning(type)) { out.printf(" @SuppressWarnings({\"rawtypes\"})\n"); } @@ -314,7 +300,7 @@ protected String constantArgument(AbstractProcessor processor, } } out.printf(" } else {\n"); - if (!isReplacement) { + if (checkShouldDefer) { out.printf(" if (b.shouldDeferPlugin(this)) {\n"); out.printf(" b.replacePlugin%s(this, targetMethod, args, %s.FUNCTION);\n", getReplacementFunctionSuffix(processor), getReplacementName()); out.printf(" return true;\n"); diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java index 063fee39413a..d1afb1d52e3c 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/replacements/processor/PluginGenerator.java @@ -163,7 +163,6 @@ protected static void createImports(PrintWriter out, AbstractProcessor processor HashSet extra = new HashSet<>(); extra.add("jdk.vm.ci.meta.ResolvedJavaMethod"); - extra.add("java.lang.annotation.Annotation"); extra.add("jdk.graal.compiler.nodes.ValueNode"); extra.add("jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext"); extra.add("jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin"); @@ -176,8 +175,6 @@ protected static void createImports(PrintWriter out, AbstractProcessor processor extra.add("jdk.graal.compiler.nodes.graphbuilderconf." + plugin.pluginSuperclass()); if (plugin.needsReplacement(processor)) { extra.add("jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport"); - extra.add("jdk.graal.compiler.graph.NodeInputList"); - extra.add("jdk.graal.compiler.nodes.spi.Replacements"); if (plugin.isWithExceptionReplacement(processor)) { extra.add("jdk.graal.compiler.nodes.PluginReplacementWithExceptionNode"); } else { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java index bad8cbed8d48..73a78c88da87 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/libgraal/BuildTime.java @@ -40,6 +40,8 @@ import java.util.function.Supplier; import org.graalvm.collections.EconomicMap; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; import jdk.graal.compiler.core.ArchitectureSpecific; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; @@ -50,7 +52,6 @@ import jdk.graal.compiler.hotspot.EncodedSnippets; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionsParser; @@ -59,8 +60,6 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.services.JVMCIServiceLocator; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; /** * This class is used at image build-time when a libgraal image gets built. Its static methods are @@ -149,7 +148,6 @@ private static void addProviders(Map, List> services, String arch, C public static void configureGraalForLibGraal(String arch, List> guestServiceClasses, Consumer> registerAsInHeap, - Consumer>> hostedGraalSetFoldNodePluginClasses, String nativeImageLocationQualifier, byte[] encodedGuestObjects) { GraalError.guarantee(VALID_LOADER_NAME.equals(LOADER.getName()), @@ -190,9 +188,6 @@ public static void configureGraalForLibGraal(String arch, List foreignCallSignatures = (List) libgraalObjects.get("foreignCallSignatures"); HotSpotForeignCallLinkage.Stubs.initStubs(foreignCallSignatures); - - hostedGraalSetFoldNodePluginClasses.accept(GeneratedInvocationPlugin.getFoldNodePluginClasses()); - } catch (ReflectiveOperationException e) { throw GraalError.shouldNotReachHere(e); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementNode.java index ce7bbf170484..20e491b36f88 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementNode.java @@ -33,9 +33,24 @@ import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodeinfo.Verbosity; +import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; +import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; import jdk.graal.compiler.nodes.spi.Replacements; +/** + * This node represents a {@link jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin + * plugin} which was deferred by + * {@link jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderTool#shouldDeferPlugin(GeneratedInvocationPlugin)} + * during graph encoding that must be replaced when the graph is decoded. This primarily exists to + * deal with graphs that have been encoded by {@link GraphEncoder} for cases where a + * {@link jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin} couldn't be applied at parse + * time. Usually {@link GraphDecoder} handles this by reapplying the plugins during decoding of the + * original {@link Invoke}. In the context of libgraal snippets that would create a lot of + * complexity because snippet methods aren't fully functional ResolvedJavaMethods. Using a + * placeholder instead avoids supporting the full GraphBuilder machinery in this admittedly weird + * case. + */ @NodeInfo(nameTemplate = "PluginReplacement/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) public final class PluginReplacementNode extends FixedWithNextNode implements PluginReplacementInterface { public static final NodeClass TYPE = NodeClass.create(PluginReplacementNode.class); @@ -53,11 +68,16 @@ public PluginReplacementNode(Stamp stamp, ValueNode[] args, ReplacementFunction @Override public boolean replace(GraphBuilderContext b, Replacements injection) { - return function.replace(b, injection, stamp, args); + return function.replace(b, injection, args.toArray(ValueNode.EMPTY_ARRAY)); } + /** + * This is the work of the original + * {@link jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin} decoupled from the + * plugin. + */ public interface ReplacementFunction { - boolean replace(GraphBuilderContext b, Replacements injection, Stamp stamp, NodeInputList args); + boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, ValueNode[] args); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementWithExceptionNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementWithExceptionNode.java index be00d675d320..fb1a7bddfb92 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementWithExceptionNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/PluginReplacementWithExceptionNode.java @@ -33,9 +33,11 @@ import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodeinfo.Verbosity; +import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; import jdk.graal.compiler.nodes.spi.Replacements; +/** See Javadoc in {@link PluginReplacementNode}. */ @NodeInfo(nameTemplate = "PluginReplacementWithException/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) public final class PluginReplacementWithExceptionNode extends WithExceptionNode implements PluginReplacementInterface { public static final NodeClass TYPE = NodeClass.create(PluginReplacementWithExceptionNode.class); @@ -53,11 +55,11 @@ public PluginReplacementWithExceptionNode(Stamp stamp, ValueNode[] args, Replace @Override public boolean replace(GraphBuilderContext b, Replacements injection) { - return function.replace(b, injection, stamp, args); + return function.replace(b, injection, args.toArray(ValueNode.EMPTY_ARRAY)); } public interface ReplacementWithExceptionFunction { - boolean replace(GraphBuilderContext b, Replacements injection, Stamp stamp, NodeInputList args); + boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, ValueNode[] args); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java index 91a67e34a5d2..f082dedc27d9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java @@ -24,11 +24,22 @@ */ package jdk.graal.compiler.nodes.graphbuilderconf; +import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import jdk.graal.compiler.api.replacements.Fold; + +/** + * A plugin generated from an {@link Fold @Fold} annotation. + */ public abstract class GeneratedFoldInvocationPlugin extends GeneratedInvocationPlugin { public GeneratedFoldInvocationPlugin(String name, Type... argumentTypes) { super(name, argumentTypes); } + + @Override + public final Class getSource() { + return Fold.class; + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java index ae32cd05c860..21f7eff4ea06 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java @@ -30,12 +30,10 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.List; import jdk.graal.compiler.api.replacements.Fold; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.Node.NodeIntrinsic; -import jdk.graal.compiler.nodes.PluginReplacementNode; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInlineOnlyInvocationPlugin; import jdk.vm.ci.meta.MetaAccessProvider; @@ -48,16 +46,6 @@ */ public abstract class GeneratedInvocationPlugin extends RequiredInlineOnlyInvocationPlugin { - private static List> foldNodePluginClasses = List.of(GeneratedFoldInvocationPlugin.class, PluginReplacementNode.ReplacementFunction.class); - - public static void setFoldNodePluginClasses(List> customFoldNodePluginClasses) { - foldNodePluginClasses = customFoldNodePluginClasses; - } - - public static List> getFoldNodePluginClasses() { - return foldNodePluginClasses; - } - private ResolvedJavaMethod executeMethod; public GeneratedInvocationPlugin(String name, Type... argumentTypes) { @@ -84,12 +72,13 @@ public String getSourceLocation() { } protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, ResolvedJavaMethod foldAnnotatedMethod) { - if (arg.isNullConstant()) { + if (inImageRuntimeCode()) { + // In native image runtime compilation, there is no later stage where execution of the + // plugin can be deferred. return true; } - if (inImageRuntimeCode()) { - // The reflection here is problematic for SVM. + if (arg.isNullConstant()) { return true; } @@ -98,41 +87,39 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re } if (inImageBuildtimeCode()) { - // The use of this plugin in the plugin itself shouldn't be folded since that defeats - // the purpose of the fold. - for (Class foldNodePluginClass : foldNodePluginClasses) { - ResolvedJavaType foldNodeClass = b.getMetaAccess().lookupJavaType(foldNodePluginClass); - if (foldNodeClass.isAssignableFrom(b.getMethod().getDeclaringClass())) { - return false; - } + // Calls to the @Fold method from the generated fold plugin shouldn't be folded. This is + // detected by comparing the class names of the current plugin and the method being + // parsed. These might be in different class loaders so the classes can't be compared + // directly. Class.getName() and ResolvedJavaType.getName() return different formats so + // get the ResolvedJavaType for this plugin. + ResolvedJavaType thisClass = b.getMetaAccess().lookupJavaType(getClass()); + if (thisClass.getName().equals(b.getMethod().getDeclaringClass().getName())) { + return false; } } - ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b); + ResolvedJavaMethod thisExecuteMethod = getExecuteMethod(b); if (b.getMethod().equals(thisExecuteMethod)) { return true; } throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg + " in " + b.getMethod().format("%H.%n(%p)")); } - private ResolvedJavaMethod getExecutedMethod(GraphBuilderContext b) { + private ResolvedJavaMethod getExecuteMethod(GraphBuilderContext b) { if (executeMethod == null) { - MetaAccessProvider metaAccess = b.getMetaAccess(); - ResolvedJavaMethod baseMethod = metaAccess.lookupJavaMethod(getExecuteMethod()); - ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass()); - executeMethod = thisClass.resolveConcreteMethod(baseMethod, thisClass); + try { + MetaAccessProvider metaAccess = b.getMetaAccess(); + Method result = GeneratedInvocationPlugin.class.getMethod("execute", GraphBuilderContext.class, ResolvedJavaMethod.class, Receiver.class, ValueNode[].class); + ResolvedJavaMethod baseMethod = metaAccess.lookupJavaMethod(result); + ResolvedJavaType thisClass = metaAccess.lookupJavaType(getClass()); + executeMethod = thisClass.resolveConcreteMethod(baseMethod, thisClass); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalError(e); + } } return executeMethod; } - private static Method getExecuteMethod() { - try { - return GeneratedInvocationPlugin.class.getMethod("execute", GraphBuilderContext.class, ResolvedJavaMethod.class, InvocationPlugin.Receiver.class, ValueNode[].class); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalError(e); - } - } - public final boolean isGeneratedFromFoldOrNodeIntrinsic() { return getSource().equals(Fold.class) || getSource().equals(NodeIntrinsic.class); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java index ab156e6b72a3..30701b89851f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java @@ -24,20 +24,30 @@ */ package jdk.graal.compiler.nodes.graphbuilderconf; +import java.lang.annotation.Annotation; import java.lang.reflect.Type; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; - +import jdk.graal.compiler.graph.Node; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +/** + * A plugin generated from an {@link jdk.graal.compiler.graph.Node.NodeIntrinsic @NodeIntrinsic} + * annotation. + */ public abstract class GeneratedNodeIntrinsicInvocationPlugin extends GeneratedInvocationPlugin { public GeneratedNodeIntrinsicInvocationPlugin(String name, Type... argumentTypes) { super(name, argumentTypes); } + @Override + public final Class getSource() { + return Node.NodeIntrinsic.class; + } + protected boolean verifyForeignCallDescriptor(GraphBuilderTool b, ResolvedJavaMethod targetMethod, ForeignCallDescriptor descriptor) { MetaAccessProvider metaAccess = b.getMetaAccess(); int parameters = 1; diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java index 6ddc9b091704..cbf743852801 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java @@ -72,7 +72,6 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.libgraal.BuildTime; import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase; -import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import jdk.graal.compiler.options.OptionDescriptor; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.serviceprovider.LibGraalService; @@ -402,8 +401,6 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { Consumer> registerAsInHeap = nodeClass -> impl.getMetaAccess().lookupJavaType(nodeClass) .registerAsInstantiated("All NodeClass classes are marked as instantiated eagerly."); - Consumer>> hostedGraalSetFoldNodePluginClasses = GeneratedInvocationPlugin::setFoldNodePluginClasses; - List> guestServiceClasses = new ArrayList<>(); List> serviceClasses = impl.getImageClassLoader().findAnnotatedClasses(LibGraalService.class, false); serviceClasses.stream().map(c -> loadClassOrFail(c.getName())).forEach(guestServiceClasses::add); @@ -417,7 +414,6 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { String.class, // arch List.class, // guestServiceClasses Consumer.class, // registerAsInHeap - Consumer.class, // hostedGraalSetFoldNodePluginClasses String.class, // nativeImageLocationQualifier byte[].class // encodedGuestObjects )); @@ -434,7 +430,6 @@ public void beforeAnalysis(BeforeAnalysisAccess baa) { configureGraalForLibGraal.invoke(arch, guestServiceClasses, registerAsInHeap, - hostedGraalSetFoldNodePluginClasses, nativeImageLocationQualifier, configResult.encodedConfig());