From 01e0732c6e3b54003520ecb15b85dcef2e31da98 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 24 Jan 2022 22:18:31 -0800 Subject: [PATCH 01/18] Convert remaining MethodSubstitutions to snippets --- .../test/HotSpotCryptoSubstitutionTest.java | 82 +++++++++ .../compiler/hotspot/HotSpotBackend.java | 8 +- .../hotspot/HotSpotBackendFactory.java | 48 +++--- .../hotspot/HotSpotReplacementsImpl.java | 9 +- .../hotspot/SnippetResolvedJavaMethod.java | 2 +- .../hotspot/SymbolicSnippetEncoder.java | 115 ++++++------- .../meta/DefaultHotSpotLoweringProvider.java | 5 + .../meta/HotSpotGraphBuilderPlugins.java | 59 ++++++- .../hotspot/meta/HotSpotProviders.java | 40 ++--- ...titutions.java => BigIntegerSnippets.java} | 24 ++- ...titutions.java => DigestBaseSnippets.java} | 37 ++-- .../replacements/HotSpotReplacementsUtil.java | 12 +- .../graphbuilderconf/InvocationPlugin.java | 8 +- .../graphbuilderconf/InvocationPlugins.java | 15 +- .../aarch64/AArch64GraphBuilderPlugins.java | 48 +++++- .../amd64/AMD64GraphBuilderPlugins.java | 63 ++++++- .../amd64/AMD64StringSubstitutions.java | 101 ----------- .../DefaultJavaLoweringProvider.java | 6 + .../SnippetSubstitutionInvocationPlugin.java | 95 +++++++++++ .../replacements/SnippetSubstitutionNode.java | 117 +++++++++++++ .../SnippetSubstitutionStateSplitNode.java | 159 ++++++++++++++++++ .../replacements/SnippetTemplate.java | 19 ++- ...tutions.java => StringLatin1Snippets.java} | 19 ++- ...itutions.java => StringUTF16Snippets.java} | 24 ++- .../graal/meta/SubstrateReplacements.java | 44 +++-- 25 files changed, 860 insertions(+), 299 deletions(-) rename compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/{BigIntegerSubstitutions.java => BigIntegerSnippets.java} (70%) rename compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/{DigestBaseSubstitutions.java => DigestBaseSnippets.java} (76%) delete mode 100644 compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java create mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java create mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java create mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java rename compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/{StringLatin1Substitutions.java => StringLatin1Snippets.java} (89%) rename compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/{StringUTF16Substitutions.java => StringUTF16Snippets.java} (90%) diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java index 81a6caa7dd55..63d24642f43d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java @@ -24,22 +24,34 @@ */ package org.graalvm.compiler.hotspot.test; +import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS_MB; +import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS_MB; +import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS_MB; + import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.security.AlgorithmParameters; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.replacements.SnippetSubstitutionNode; import org.junit.Assert; import org.junit.Assume; +import org.junit.Before; import org.junit.Test; +import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Tests the intrinsification of certain crypto methods. @@ -172,4 +184,74 @@ public Result runEncryptDecrypt(SecretKey key, String algorithm) throws Exceptio return new Result(null, e); } } + + @Test + public void testDigestBaseSHA() throws Exception { + Assume.assumeTrue("SHA1 not supported", runtime().getVMConfig().useSHA1Intrinsics()); + testDigestBase("sun.security.provider.DigestBase", "implCompressMultiBlock", "SHA-1", SHA_IMPL_COMPRESS_MB); + } + + @Test + public void testDigestBaseSHA2() throws Exception { + Assume.assumeTrue("SHA256 not supported", runtime().getVMConfig().useSHA256Intrinsics()); + testDigestBase("sun.security.provider.DigestBase", "implCompressMultiBlock", "SHA-256", SHA2_IMPL_COMPRESS_MB); + } + + @Test + public void testDigestBaseSHA5() throws Exception { + Assume.assumeTrue("SHA512 not supported", runtime().getVMConfig().useSHA512Intrinsics()); + testDigestBase("sun.security.provider.DigestBase", "implCompressMultiBlock", "SHA-512", SHA5_IMPL_COMPRESS_MB); + } + + @Before + public void clearExceptionCall() { + expectedCall = null; + } + + HotSpotForeignCallDescriptor expectedCall; + + @Override + protected void checkLowTierGraph(StructuredGraph graph) { + if (expectedCall != null) { + for (ForeignCallNode node : graph.getNodes().filter(ForeignCallNode.class)) { + if (node.getDescriptor() == expectedCall) { + return; + } + } + assertTrue("expected call to " + expectedCall, false); + } + } + + private void testDigestBase(String className, String methodName, String algorithm, HotSpotForeignCallDescriptor call) throws Exception { + Class klass = Class.forName(className); + expectedCall = call; + MessageDigest digest = MessageDigest.getInstance(algorithm); + byte[] expected = digest.digest(input.clone()); + ResolvedJavaMethod method = getResolvedJavaMethod(klass, methodName); + + try { + testDigestBase(digest, expected, method); + } catch (BailoutException e) { + // The plugin may cause loading which invalidates assumptions in the graph so retry it + // once. This normally only occurs when running individual tests. + if (e.getMessage().contains("Code installation failed: dependencies failed")) { + testDigestBase(digest, expected, method); + } else { + throw e; + } + } + } + + private void testDigestBase(MessageDigest digest, byte[] expected, ResolvedJavaMethod method) { + StructuredGraph graph = parseForCompile(method); + assertTrue(graph.getNodes().filter(SnippetSubstitutionNode.class).isNotEmpty()); + InstalledCode intrinsic = getCode(method, graph, false, true, getInitialOptions()); + try { + Assert.assertNotNull("missing intrinsic", intrinsic); + byte[] actual = digest.digest(input.clone()); + assertDeepEquals(expected, actual); + } finally { + intrinsic.invalidate(); + } + } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 356d13f37d0f..3c62a8ed0d44 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -53,8 +53,8 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; -import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; -import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions; +import org.graalvm.compiler.hotspot.replacements.BigIntegerSnippets; +import org.graalvm.compiler.hotspot.replacements.DigestBaseSnippets; import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; @@ -170,7 +170,7 @@ public static class Options { NamedLocationIdentity.getArrayLocation(JavaKind.Byte), "cipherBlockChaining_decrypt_aescrypt", int.class, Word.class, Word.class, Pointer.class, Pointer.class, int.class); /** - * @see BigIntegerSubstitutions#multiplyToLen + * @see BigIntegerSnippets#implMultiplyToLen(int[], int, int[], int, int[]) */ public static final HotSpotForeignCallDescriptor MULTIPLY_TO_LEN = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int), "multiplyToLen", @@ -205,7 +205,7 @@ public static void multiplyToLenStub(Word xAddr, int xlen, Word yAddr, int ylen, Object.class); /** - * @see DigestBaseSubstitutions#implCompressMultiBlock0 + * @see DigestBaseSnippets#implCompressMultiBlock0 */ public static final HotSpotForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "shaImplCompressMB", int.class, Word.class, Object.class, int.class, int.class); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java index bc5b58a24af2..5c0fd2b74ba6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java @@ -120,79 +120,79 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti if (IS_BUILDING_NATIVE_IMAGE || IS_IN_NATIVE_IMAGE) { SnippetSignature.initPrimitiveKindCache(jvmci.getMetaAccess()); } - HotSpotProviders providers; - HotSpotRegistersProvider registers; HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache(); TargetDescription target = codeCache.getTarget(); - HotSpotHostForeignCallsProvider foreignCalls; - Value[] nativeABICallerSaveRegisters; MetaAccessProvider metaAccess = new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection(); ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess); - HotSpotLoweringProvider lowerer; - HotSpotStampProvider stampProvider; - HotSpotPlatformConfigurationProvider platformConfigurationProvider; - HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider; - HotSpotSnippetReflectionProvider snippetReflection; - LoopsDataProvider loopsDataProvider; - HotSpotReplacementsImpl replacements; - HotSpotSuitesProvider suites; - HotSpotWordTypes wordTypes; - GraphBuilderConfiguration.Plugins plugins; - BytecodeProvider bytecodeProvider; + HotSpotProviders providers; try (InitTimer t = timer("create providers")) { + HotSpotRegistersProvider registers; try (InitTimer rt = timer("create HotSpotRegisters provider")) { registers = createRegisters(); } + Value[] nativeABICallerSaveRegisters; try (InitTimer rt = timer("create NativeABICallerSaveRegisters")) { nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig()); } + HotSpotWordTypes wordTypes; try (InitTimer rt = timer("create WordTypes")) { wordTypes = createWordTypes(metaAccess, target); } + HotSpotHostForeignCallsProvider foreignCalls; try (InitTimer rt = timer("create ForeignCalls provider")) { foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters); } + HotSpotPlatformConfigurationProvider platformConfigurationProvider; try (InitTimer rt = timer("create platform configuration provider")) { platformConfigurationProvider = createConfigInfoProvider(config, metaAccess); } + HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider; try (InitTimer rt = timer("create MetaAccessExtensionProvider")) { metaAccessExtensionProvider = createMetaAccessExtensionProvider(); } + HotSpotStampProvider stampProvider; try (InitTimer rt = timer("create stamp provider")) { stampProvider = createStampProvider(); } + HotSpotLoweringProvider lowerer; try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target); } + LoopsDataProvider loopsDataProvider; try (InitTimer rt = timer("create loopsdata provider")) { loopsDataProvider = createLoopsDataProvider(); } - HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider, loopsDataProvider); - + HotSpotSnippetReflectionProvider snippetReflection; try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); } + BytecodeProvider bytecodeProvider; try (InitTimer rt = timer("create Bytecode provider")) { bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection); } + + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, null, registers, + snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config); + HotSpotReplacementsImpl replacements; try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(target, p, snippetReflection, bytecodeProvider); + replacements = createReplacements(target, providers, snippetReflection, bytecodeProvider); + providers = replacements.getProviders(); + replacements.maybeInitializeEncoder(options); } + GraphBuilderConfiguration.Plugins plugins; try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); + HotSpotSuitesProvider suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); + providers.setSuites(suites); } - providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, - snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config); - replacements.setProviders(providers); - replacements.maybeInitializeEncoder(options); + assert replacements == replacements.getProviders().getReplacements(); + assert providers.getGraphBuilderPlugins() == plugins; } try (InitTimer rt = timer("instantiate backend")) { return createBackend(config, graalRuntime, providers); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index b9a19ba66ca2..7f65c812b928 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -87,7 +87,7 @@ public void maybeInitializeEncoder(OptionValues options) { if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { synchronized (HotSpotReplacementsImpl.class) { if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this, options); + snippetEncoder = new SymbolicSnippetEncoder(this); } } } @@ -194,9 +194,10 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; if (!IS_IN_NATIVE_IMAGE) { assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); - assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)"); - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { - snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); + if (registeredSnippets.add(method)) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); + } } } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java index b5f6c7ad22c1..0cb8730df17d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java @@ -107,7 +107,7 @@ public boolean isVarArgs() { @Override public boolean isBridge() { - throw new UnsupportedOperationException(); + return false; } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 8382f00380dc..7066b7c51d09 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -24,12 +24,9 @@ */ package org.graalvm.compiler.hotspot; -import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import static org.graalvm.compiler.hotspot.EncodedSnippets.methodKey; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; import java.lang.reflect.Executable; import java.lang.reflect.Field; @@ -43,12 +40,12 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.BiFunction; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; @@ -149,12 +146,6 @@ */ public class SymbolicSnippetEncoder { - /** - * This is a customized HotSpotReplacementsImpl intended only for parsing snippets and method - * substitutions for graph encoding. - */ - private final HotSpotSnippetReplacementsImpl snippetReplacements; - /** * A mapping from the method substitution method to the original method name. The string key and * values are produced using {@link EncodedSnippets#methodKey(ResolvedJavaMethod)}. @@ -281,6 +272,8 @@ public String toString() { } } + private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); + /** * All the graphs parsed so far. */ @@ -292,8 +285,6 @@ public String toString() { private final EconomicSet conditionalPlugins = EconomicSet.create(); - private int preparedPlugins = 0; - /** * The invocation plugins which were delayed during graph preparation. */ @@ -319,7 +310,7 @@ public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod m } // Force inlining when parsing replacements - return createIntrinsicInlineInfo(method, snippetReplacements.getDefaultReplacementBytecodeProvider()); + return createIntrinsicInlineInfo(method, originalReplacements.getDefaultReplacementBytecodeProvider()); } @Override @@ -331,10 +322,16 @@ public void notifyAfterInline(ResolvedJavaMethod methodToInline) { /** * This plugin disables the snippet counter machinery. */ - private class SnippetCounterPlugin implements NodePlugin { + static final class SnippetCounterPlugin implements NodePlugin { String snippetCounterName = 'L' + SnippetCounter.class.getName().replace('.', '/') + ';'; String snippetIntegerHistogramName = 'L' + SnippetIntegerHistogram.class.getName().replace('.', '/') + ';'; + private final ReplacementsImpl snippetReplacements; + + private SnippetCounterPlugin(ReplacementsImpl snippetReplacements) { + this.snippetReplacements = snippetReplacements; + } + @Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { if (field.getName().equals("group") && field.getDeclaringClass().getName().equals(snippetCounterName)) { @@ -354,18 +351,8 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved } } - SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements, OptionValues options) { - assert IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options); + SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) { this.originalReplacements = replacements; - GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins(); - InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); - GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); - copy.clearInlineInvokePlugins(); - copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); - copy.appendNodePlugin(new SnippetCounterPlugin()); - HotSpotProviders providers = replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); - this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); - this.snippetReplacements.setGraphBuilderPlugins(copy); } synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { @@ -382,21 +369,8 @@ synchronized void checkRegistered(MethodSubstitutionPlugin plugin) { } } - /** - * Compiles the snippet and stores the graph. - */ - private synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, OptionValues options) { - ResolvedJavaMethod method = plugin.getSubstitute(snippetReplacements.getProviders().getMetaAccess()); - assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); - String originalMethodString = plugin.originalMethodAsString(); - StructuredGraph subst = buildGraph(method, original, originalMethodString, null, null, true, false, context, options); - MethodSubstitutionKey key = new MethodSubstitutionKey(method, original, context, plugin); - originalMethods.put(key.keyString(), originalMethodString); - preparedSnippetGraphs.put(key, subst); - } - private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, BitSet nonNullParameters, boolean requireInlining, - boolean trackNodeSourcePosition, IntrinsicContext.CompilationContext context, OptionValues options) { + boolean trackNodeSourcePosition, IntrinsicContext.CompilationContext context, OptionValues options, ReplacementsImpl snippetReplacements) { assert method.hasBytecodes() : "Snippet must not be abstract or native"; Object[] args = null; if (receiver != null) { @@ -420,7 +394,7 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod // Check if all methods which should be inlined are really inlined. for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { ResolvedJavaMethod callee = callTarget.targetMethod(); - if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original)) { + if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original) && !Objects.equals(callee, method)) { throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); } } @@ -466,14 +440,14 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod int startOffset = encoder.encode(graph); EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffset, encoder.getObjects(), encoder.getNodeClasses(), graph); - HotSpotProviders originalProvider = snippetReplacements.getProviders(); + HotSpotProviders originalProvider = originalReplacements.getProviders(); SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( originalProvider.getConstantReflection()); HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), - originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), + originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getStampProvider(), originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getLoopsDataProvider(), originalProvider.getConfig()); HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); @@ -512,17 +486,20 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod */ @SuppressWarnings("try") private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { - EconomicSet plugins = this.knownPlugins; - if (preparedPlugins != plugins.size()) { - for (MethodSubstitutionPlugin plugin : plugins) { - ResolvedJavaMethod original = plugin.getOriginalMethod(originalReplacements.getProviders().getMetaAccess()); - registerMethodSubstitution(plugin, original, INLINE_AFTER_PARSING, options); - if (!original.isNative()) { - registerMethodSubstitution(plugin, original, ROOT_COMPILATION_ENCODING, options); - } - lookupSnippetType(plugin.getDeclaringClass()); + GraphBuilderConfiguration.Plugins plugins = originalReplacements.getGraphBuilderPlugins(); + InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); + GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); + HotSpotProviders providers = originalReplacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(originalReplacements.getProviders().getConstantReflection())); + HotSpotSnippetReplacementsImpl snippetReplacements = new HotSpotSnippetReplacementsImpl(originalReplacements, providers.copyWith()); + snippetReplacements.setGraphBuilderPlugins(copy); + copy.clearInlineInvokePlugins(); + copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); + copy.appendNodePlugin(new SnippetCounterPlugin(snippetReplacements)); + + if (!pendingSnippetGraphs.isEmpty()) { + for (BiFunction function : pendingSnippetGraphs.getValues()) { + function.apply(options, snippetReplacements); } - preparedPlugins = plugins.size(); } EconomicMap graphs = this.preparedSnippetGraphs; if (encodedGraphs != graphs.size()) { @@ -541,19 +518,18 @@ private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { } - synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { + synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); SnippetKey key = new SnippetKey(method, original, receiver); findSnippetMethod(method); - if (!preparedSnippetGraphs.containsKey(key)) { + if (!pendingSnippetGraphs.containsKey(key)) { if (original != null) { originalMethods.put(key.keyString(), methodKey(original)); } SnippetParameterInfo info = new SnippetParameterInfo(method); - StructuredGraph snippet = buildGraph(method, original, null, receiver, SnippetParameterInfo.getNonNullParameters(info), true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options); - preparedSnippetGraphs.put(key, snippet); snippetParameterInfos.put(key.keyString(), info); + int i = 0; int offset = 0; if (!method.isStatic()) { @@ -577,6 +553,15 @@ synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } } } + pendingSnippetGraphs.put(key, new BiFunction() { + @Override + public Void apply(OptionValues cmopileOptions, HotSpotSnippetReplacementsImpl snippetReplacements) { + StructuredGraph snippet = buildGraph(method, original, null, receiver, SnippetParameterInfo.getNonNullParameters(info), true, trackNodeSourcePosition, INLINE_AFTER_PARSING, + cmopileOptions, snippetReplacements); + preparedSnippetGraphs.put(key, snippet); + return null; + } + }); } } @@ -783,8 +768,18 @@ SnippetReflectionProvider getSnippetReflection() { */ private Object filterSnippetObject(DebugContext debug, Object o) { checkIllegalSnippetObjects(o); + Object cached = cachedFilteredObjects.get(0); + if (cached != null) { + return cached; + } if (o instanceof HotSpotResolvedJavaMethod) { - return filterMethod(debug, (HotSpotResolvedJavaMethod) o); + HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) o; + if (isGraalClass(method.getDeclaringClass())) { + ResolvedJavaMethod snippetMethod = findSnippetMethod(method); + cachedFilteredObjects.put(method, snippetMethod); + return snippetMethod; + } + return filterMethod(debug, method); } else if (o instanceof HotSpotResolvedJavaField) { return filterField(debug, (HotSpotResolvedJavaField) o); } else if (o instanceof HotSpotResolvedJavaType) { @@ -813,6 +808,9 @@ private SymbolicResolvedJavaMethod filterMethod(DebugContext debug, ResolvedJava if (symbolic != null) { return symbolic; } + if (isGraalClass(method.getDeclaringClass())) { + throw new GraalError("Graal methods shouldn't leak into image: " + method); + } UnresolvedJavaType type = (UnresolvedJavaType) filterType(debug, method.getDeclaringClass()); String methodName = method.getName(); String signature = method.getSignature().toMethodDescriptor(); @@ -838,6 +836,9 @@ private JavaType filterType(DebugContext debug, ResolvedJavaType type) { if (unresolvedJavaType != null) { return unresolvedJavaType; } + if (isGraalClass(type)) { + throw new GraalError("Graal types shouldn't leak into image: " + type); + } unresolvedJavaType = UnresolvedJavaType.create(type.getName()); debug.log(DebugContext.VERBOSE_LEVEL, "filtered %s -> %s", type, unresolvedJavaType); cachedFilteredObjects.put(type, unresolvedJavaType); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 05570017057d..5f19f882f88c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -72,7 +72,9 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; import org.graalvm.compiler.hotspot.replacements.AssertionSnippets; +import org.graalvm.compiler.hotspot.replacements.BigIntegerSnippets; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; +import org.graalvm.compiler.hotspot.replacements.DigestBaseSnippets; import org.graalvm.compiler.hotspot.replacements.FastNotifyNode; import org.graalvm.compiler.hotspot.replacements.HotSpotAllocationSnippets; import org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets; @@ -303,6 +305,9 @@ public void initialize(OptionValues options, Iterable fact objectSnippets = new ObjectSnippets.Templates(options, providers); unsafeSnippets = new UnsafeSnippets.Templates(options, providers); + replacements.registerSnippetTemplateCache(new BigIntegerSnippets.Templates(options, providers)); + replacements.registerSnippetTemplateCache(new DigestBaseSnippets.Templates(options, providers)); + initializeExtensions(options, factories, providers, config); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 756e6fcc25c0..eff70853ccd6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -68,9 +68,9 @@ import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; import org.graalvm.compiler.hotspot.nodes.HotSpotLoadReservedReferenceNode; import org.graalvm.compiler.hotspot.nodes.HotSpotStoreReservedReferenceNode; -import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; +import org.graalvm.compiler.hotspot.replacements.BigIntegerSnippets; import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; -import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions; +import org.graalvm.compiler.hotspot.replacements.DigestBaseSnippets; import org.graalvm.compiler.hotspot.replacements.FastNotifyNode; import org.graalvm.compiler.hotspot.replacements.HotSpotIdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.HotSpotInvocationPluginHelper; @@ -127,6 +127,8 @@ import org.graalvm.compiler.replacements.MethodHandlePlugin; import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.replacements.SnippetSubstitutionInvocationPlugin; +import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; @@ -774,8 +776,23 @@ private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVM private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { Registration r = new Registration(plugins, BigInteger.class, replacements); - r.registerConditionalMethodSubstitution(config.useMultiplyToLenIntrinsic(), BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, - int.class, int[].class); + r.registerConditional(config.useMultiplyToLenIntrinsic(), new SnippetSubstitutionInvocationPlugin(true, "implMultiplyToLen", int[].class, int.class, int[].class, int.class, int[].class) { + BigIntegerSnippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().implMultiplyToLen; + } + + @Override + public BigIntegerSnippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(BigIntegerSnippets.Templates.class); + assert templates != null; + } + return templates; + } + }); r.registerConditional(config.useMulAddIntrinsic(), new InvocationPlugin("implMulAdd", int[].class, int[].class, int.class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode out, ValueNode in, ValueNode offset, ValueNode len, ValueNode k) { @@ -870,10 +887,36 @@ private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVM boolean useSha256 = config.useSHA256Intrinsics(); boolean useSha512 = config.useSHA512Intrinsics(); - if (isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && (useSha1 || useSha256 || useSha512)) { - Registration r = new Registration(plugins, "sun.security.provider.DigestBase", replacements); - r.registerMethodSubstitution(DigestBaseSubstitutions.class, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class); - } + boolean implCompressMultiBlock0Enabled = isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && (useSha1 || useSha256 || useSha512); + Registration r = new Registration(plugins, "sun.security.provider.DigestBase", replacements); + r.registerConditional(implCompressMultiBlock0Enabled, new SnippetSubstitutionInvocationPlugin(true, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class) { + DigestBaseSnippets.Templates templates; + + @Override + protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { + Object[] constantArguments = new Object[4]; + ResolvedJavaType declaringClass = targetMethod.getDeclaringClass(); + constantArguments[0] = declaringClass; + constantArguments[1] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA;"); + constantArguments[2] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA2;"); + constantArguments[3] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA5;"); + return constantArguments; + } + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().implCompressMultiBlock0; + } + + @Override + public DigestBaseSnippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(DigestBaseSnippets.Templates.class); + assert templates != null; + } + return templates; + } + }); Registration rSha1 = new Registration(plugins, "sun.security.provider.SHA", replacements); rSha1.registerConditional(config.useSHA1Intrinsics(), new SHAInvocationPlugin(HotSpotBackend.SHA_IMPL_COMPRESS)); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java index 87d6702bf16d..bb4c9507238c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java @@ -26,7 +26,6 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; @@ -39,7 +38,6 @@ import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.util.Providers; -import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -50,9 +48,8 @@ */ public class HotSpotProviders extends Providers { - private final SuitesProvider suites; + private SuitesProvider suites; private final HotSpotRegistersProvider registers; - private final Plugins graphBuilderPlugins; private final GraalHotSpotVMConfig config; public HotSpotProviders(MetaAccessProvider metaAccess, @@ -66,30 +63,18 @@ public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotRegistersProvider registers, SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, - Plugins graphBuilderPlugins, + StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider, GraalHotSpotVMConfig config) { - super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), platformConfigurationProvider, metaAccessExtensionProvider, + super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider); this.suites = suites; this.registers = registers; - this.graphBuilderPlugins = graphBuilderPlugins; this.config = config; } - public HotSpotProviders(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField, - ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider, - MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider) { - super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, null, null, - loopsDataProvider); - this.suites = null; - this.registers = null; - this.graphBuilderPlugins = null; - this.config = null; - } - @Override public HotSpotCodeCacheProvider getCodeCache() { return (HotSpotCodeCacheProvider) super.getCodeCache(); @@ -109,7 +94,7 @@ public HotSpotRegistersProvider getRegisters() { } public Plugins getGraphBuilderPlugins() { - return graphBuilderPlugins; + return replacements.getGraphBuilderPlugins(); } @Override @@ -129,7 +114,8 @@ public HotSpotPlatformConfigurationProvider getPlatformConfigurationProvider() { @Override public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), + getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), + getLoopsDataProvider(), config); } @@ -137,21 +123,27 @@ public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { public HotSpotProviders copyWith(ConstantFieldProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), + getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), + getLoopsDataProvider(), config); } @Override public HotSpotProviders copyWith(Replacements substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, - getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), + getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), + getMetaAccessExtensionProvider(), getLoopsDataProvider(), config); } - public HotSpotProviders copyWith(Plugins substitution) { + public HotSpotProviders copyWith() { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), - getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), + getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), + getLoopsDataProvider(), config); } + public void setSuites(HotSpotSuitesProvider suites) { + this.suites = suites; + } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSubstitutions.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSnippets.java similarity index 70% rename from compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSubstitutions.java rename to compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSnippets.java index f7a370073b76..b8b03a42fa30 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSubstitutions.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/BigIntegerSnippets.java @@ -26,20 +26,26 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayStart; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.HotSpotBackend; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.replacements.SnippetTemplate; +import org.graalvm.compiler.replacements.Snippets; -@ClassSubstitution(className = "java.math.BigInteger", optional = true) -public class BigIntegerSubstitutions { +public class BigIntegerSnippets implements Snippets { - @MethodSubstitution(isStatic = false) - static int[] multiplyToLen(@SuppressWarnings("unused") Object receiver, int[] x, int xlen, int[] y, int ylen, int[] zIn) { - return multiplyToLenStatic(x, xlen, y, ylen, zIn); + public static class Templates extends SnippetTemplate.AbstractTemplates { + + public Templates(OptionValues options, Providers providers) { + super(options, providers); + } + + public final SnippetTemplate.SnippetInfo implMultiplyToLen = snippet(BigIntegerSnippets.class, "implMultiplyToLen"); } - @MethodSubstitution(isStatic = true) - static int[] multiplyToLenStatic(int[] x, int xlen, int[] y, int ylen, int[] zIn) { + @Snippet + public static int[] implMultiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] zIn) { int[] zResult = zIn; int zLen; if (zResult == null || zResult.length < (xlen + ylen)) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSubstitutions.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java similarity index 76% rename from compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSubstitutions.java rename to compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java index 00799536d75e..4f71ccd72ae6 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSubstitutions.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java @@ -25,19 +25,21 @@ package org.graalvm.compiler.hotspot.replacements; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS; -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_INTRINSIC_CONTEXT; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.nodes.java.InstanceOfNode.doInstanceof; -import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.ReplacementsUtil; +import org.graalvm.compiler.replacements.SnippetTemplate; +import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.Word; import org.graalvm.word.LocationIdentity; import org.graalvm.word.WordFactory; @@ -45,15 +47,24 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; -@ClassSubstitution(className = "sun.security.provider.DigestBase", optional = true) -public class DigestBaseSubstitutions { +public class DigestBaseSnippets implements Snippets { - @MethodSubstitution(isStatic = false) - static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int limit) { - Object realReceiver = PiNode.piCastNonNull(receiver, HotSpotReplacementsUtil.methodHolderClass(INJECTED_INTRINSIC_CONTEXT)); - ResolvedJavaType sha1type = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "Lsun/security/provider/SHA;"); - ResolvedJavaType sha256type = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "Lsun/security/provider/SHA2;"); - ResolvedJavaType sha512type = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "Lsun/security/provider/SHA5;"); + public static class Templates extends SnippetTemplate.AbstractTemplates { + + public Templates(OptionValues options, Providers providers) { + super(options, providers); + } + + public final SnippetTemplate.SnippetInfo implCompressMultiBlock0 = snippet(DigestBaseSnippets.class, "implCompressMultiBlock0"); + } + + @Snippet(allowPartialIntrinsicArgumentMismatch = true) + static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int limit, + @Snippet.ConstantParameter ResolvedJavaType receiverType, + @Snippet.ConstantParameter ResolvedJavaType sha1type, + @Snippet.ConstantParameter ResolvedJavaType sha256type, + @Snippet.ConstantParameter ResolvedJavaType sha512type) { + Object realReceiver = PiNode.piCastNonNull(receiver, receiverType); Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Byte) + ofs)); if (useSHA1Intrinsics(INJECTED_VMCONFIG) && doInstanceof(sha1type, realReceiver)) { @@ -72,7 +83,9 @@ static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int lim Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int))); return HotSpotBackend.sha5ImplCompressMBStub(bufAddr, stateAddr, ofs, limit); } else { - return implCompressMultiBlock0(realReceiver, buf, ofs, limit); + // This will be replaced by an invoke of original method with the extra + // ConstantParameter arguments removed. + return implCompressMultiBlock0(receiver, buf, ofs, limit, receiverType, sha1type, sha256type, sha512type); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 9997127c8271..de71a4c6bf9a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -53,7 +53,6 @@ import org.graalvm.compiler.nodes.extended.LoadHubOrNullNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.memory.AddressableMemoryAccess; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -138,16 +137,9 @@ protected static ValueNode foldIndirection(ValueNode read, ValueNode object, Loc } } - @Fold - public static ResolvedJavaType methodHolderClass(@InjectedParameter IntrinsicContext context) { - return context.getOriginalMethod().getDeclaringClass(); - } - - @Fold - public static ResolvedJavaType getType(@Fold.InjectedParameter IntrinsicContext context, String typeName) { + public static ResolvedJavaType getType(ResolvedJavaType accessingClass, String typeName) { try { - UnresolvedJavaType unresolved = UnresolvedJavaType.create(typeName); - return unresolved.resolve(methodHolderClass(context)); + return UnresolvedJavaType.create(typeName).resolve(accessingClass); } catch (LinkageError e) { throw new GraalError(e); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java index 5d82901447a3..8cfa85abaea8 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugin.java @@ -429,7 +429,7 @@ public InlineOnlyInvocationPlugin(String name, Type... argumentTypes) { } @Override - public boolean inlineOnly() { + public final boolean inlineOnly() { return true; } } @@ -441,7 +441,7 @@ public OptionalInvocationPlugin(String name, Type... argumentTypes) { } @Override - public boolean isOptional() { + public final boolean isOptional() { return true; } } @@ -453,7 +453,7 @@ public RequiredInvocationPlugin(String name, Type... argumentTypes) { } @Override - public boolean canBeDisabled() { + public final boolean canBeDisabled() { return false; } } @@ -465,7 +465,7 @@ public RequiredInlineOnlyInvocationPlugin(String name, Type... argumentTypes) { } @Override - public boolean inlineOnly() { + public final boolean inlineOnly() { return true; } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java index 31ed63d0c51a..e0a8e3d2a80a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -440,6 +440,11 @@ public void close() { */ private volatile List deferredRegistrations; + /** + * Flag to avoid recursive deferred registration. + */ + private boolean processingDeferredRegistrations; + /** * Adds a {@link Runnable} for doing registration deferred until the first time * {@link #get(ResolvedJavaMethod)} or {@link #closeRegistration()} is called on this object. @@ -643,11 +648,15 @@ static class InvocationPluginRegistrationError extends GraalError { } } - private void flushDeferrables() { + public void flushDeferrables() { if (deferredRegistrations != null) { synchronized (this) { if (deferredRegistrations != null) { + if (processingDeferredRegistrations) { + throw new GraalError("recursively performing deferred registration"); + } try { + processingDeferredRegistrations = true; for (Runnable deferrable : deferredRegistrations) { deferrable.run(); } @@ -671,6 +680,8 @@ public void run() { }; deferredRegistrations.add(rethrow); rethrow.run(); + } finally { + processingDeferredRegistrations = false; } } } @@ -1113,7 +1124,7 @@ public static boolean check(InvocationPlugins plugins, Type declaringType, Invoc Class klass = plugin.getClass(); while (klass != InvocationPlugin.class) { for (Method m : klass.getDeclaredMethods()) { - if (m.getName().equals("defaultHandler")) { + if (m.getName().equals("defaultHandler") || m.getName().equals("execute")) { return true; } if (m.getName().equals("apply")) { diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index 83ba59dfea96..6bf37929165d 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -31,6 +31,8 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; +import java.lang.reflect.Type; + import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; @@ -57,9 +59,11 @@ import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.ArrayIndexOfNode; +import org.graalvm.compiler.replacements.SnippetSubstitutionInvocationPlugin; +import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.StringLatin1IndexOfCharPlugin; -import org.graalvm.compiler.replacements.StringLatin1Substitutions; -import org.graalvm.compiler.replacements.StringUTF16Substitutions; +import org.graalvm.compiler.replacements.StringLatin1Snippets; +import org.graalvm.compiler.replacements.StringUTF16Snippets; import org.graalvm.compiler.replacements.TargetGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; @@ -73,8 +77,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; -import java.lang.reflect.Type; - public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins { @Override public void register(Plugins plugins, Replacements replacements, Architecture arch, boolean registerForeignCallMath, OptionValues options) { @@ -287,7 +289,23 @@ private static void registerStringLatin1Plugins(InvocationPlugins plugins, Repla r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Byte, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Char, "compareToUTF16", byte[].class, byte[].class)); - r.registerMethodSubstitution(StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class); + r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { + StringLatin1Snippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().indexOf; + } + + @Override + public StringLatin1Snippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(StringLatin1Snippets.Templates.class); + assert templates != null; + } + return templates; + } + }); r.register(new StringLatin1IndexOfCharPlugin()); } @@ -296,7 +314,23 @@ private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replac r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Char, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Byte, true, "compareToLatin1", byte[].class, byte[].class)); - r.registerMethodSubstitution(StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class); + r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { + StringUTF16Snippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().indexOfUnsafe; + } + + @Override + public StringUTF16Snippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); + assert templates != null; + } + return templates; + } + }); r.register(new InvocationPlugin("indexOfCharUnsafe", byte[].class, int.class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value, ValueNode ch, ValueNode fromIndex, ValueNode max) { @@ -305,7 +339,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } }); - Registration r2 = new Registration(plugins, StringUTF16Substitutions.class, replacements); + Registration r2 = new Registration(plugins, StringUTF16Snippets.class, replacements); r2.register(new InvocationPlugin("getChar", byte[].class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { diff --git a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java index ee68940969b4..c64dd86580ef 100644 --- a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java @@ -61,10 +61,12 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.ArrayIndexOfNode; import org.graalvm.compiler.replacements.InvocationPluginHelper; +import org.graalvm.compiler.replacements.SnippetSubstitutionInvocationPlugin; +import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.StringLatin1IndexOfCharPlugin; -import org.graalvm.compiler.replacements.StringLatin1Substitutions; -import org.graalvm.compiler.replacements.StringUTF16Substitutions; +import org.graalvm.compiler.replacements.StringLatin1Snippets; +import org.graalvm.compiler.replacements.StringUTF16Snippets; import org.graalvm.compiler.replacements.TargetGraphBuilderPlugins; import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; @@ -360,11 +362,28 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.registerMethodSubstitution(StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class); + r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { + StringLatin1Snippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().indexOf; + } + + @Override + public StringLatin1Snippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(StringLatin1Snippets.Templates.class); + assert templates != null; + } + return templates; + } + }); r.register(new StringLatin1IndexOfCharPlugin()); } private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replacements replacements) { + Registration r = new Registration(plugins, "java.lang.StringUTF16", replacements); r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Char, "compareTo", byte[].class, byte[].class)); @@ -444,8 +463,40 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.registerMethodSubstitution(StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class); - r.registerMethodSubstitution(StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class); + r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { + StringUTF16Snippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().indexOfUnsafe; + } + + @Override + public StringUTF16Snippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); + assert templates != null; + } + return templates; + } + }); + r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class) { + StringUTF16Snippets.Templates templates; + + @Override + public SnippetTemplate.SnippetInfo getSnippet() { + return getTemplates().indexOfLatin1Unsafe; + } + + @Override + public StringUTF16Snippets.Templates getTemplates() { + if (templates == null) { + templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); + assert templates != null; + } + return templates; + } + }); r.register(new InvocationPlugin("indexOfCharUnsafe", byte[].class, int.class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value, ValueNode ch, ValueNode fromIndex, ValueNode max) { @@ -454,7 +505,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } }); - Registration r2 = new Registration(plugins, StringUTF16Substitutions.class, replacements); + Registration r2 = new Registration(plugins, StringUTF16Snippets.class, replacements); r2.register(new InvocationPlugin("getChar", byte[].class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { diff --git a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java deleted file mode 100644 index d810a12ffe05..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.amd64; - -import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; -import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; -import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; -import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayBaseOffset; -import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.replacements.ArrayIndexOf; -import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; - -// JaCoCo Exclude - -/** - * Substitutions for {@link java.lang.String} methods. - */ -@ClassSubstitution(String.class) -public class AMD64StringSubstitutions { - - /** Marker value for the {@link InjectedParameter} injected parameter. */ - static final MetaAccessProvider INJECTED = null; - - // Only exists in JDK <= 8 - @MethodSubstitution(isStatic = true, optional = true) - public static int indexOf(char[] source, int sourceOffset, int sourceCount, - @ConstantNodeParameter char[] target, int targetOffset, int targetCount, - int origFromIndex) { - int fromIndex = origFromIndex; - if (injectBranchProbability(UNLIKELY_PROBABILITY, fromIndex >= sourceCount)) { - return (targetCount == 0 ? sourceCount : -1); - } - if (injectBranchProbability(UNLIKELY_PROBABILITY, fromIndex < 0)) { - fromIndex = 0; - } - if (injectBranchProbability(UNLIKELY_PROBABILITY, targetCount == 0)) { - // The empty string is in every string. - return fromIndex; - } - - int totalOffset = sourceOffset + fromIndex; - if (injectBranchProbability(UNLIKELY_PROBABILITY, sourceCount - fromIndex < targetCount)) { - // The empty string contains nothing except the empty string. - return -1; - } - - if (injectBranchProbability(UNLIKELY_PROBABILITY, targetCount == 1)) { - return ArrayIndexOf.indexOfC1S2(source, sourceCount, totalOffset, target[targetOffset]); - } else { - int haystackLength = sourceCount - (targetCount - 2); - while (injectBranchProbability(LIKELY_PROBABILITY, totalOffset < haystackLength)) { - int indexOfResult = ArrayIndexOf.indexOfTwoConsecutiveCS2(source, haystackLength, totalOffset, target[targetOffset], target[targetOffset + 1]); - if (injectBranchProbability(UNLIKELY_PROBABILITY, indexOfResult < 0)) { - return -1; - } - totalOffset = indexOfResult; - if (injectBranchProbability(UNLIKELY_PROBABILITY, targetCount == 2)) { - return totalOffset; - } else { - long srcOffset = charArrayBaseOffset(INJECTED) + ((long) totalOffset * charArrayIndexScale(INJECTED)); - long tgtOffset = charArrayBaseOffset(INJECTED) + ((long) targetOffset * charArrayIndexScale(INJECTED)); - if (injectBranchProbability(UNLIKELY_PROBABILITY, ArrayRegionEqualsNode.regionEquals(source, srcOffset, target, tgtOffset, targetCount, JavaKind.Char))) { - return totalOffset; - } - } - totalOffset++; - } - return -1; - } - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index 00b82008355b..f4c28a05fc7c 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -188,6 +188,8 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider { private BoxingSnippets.Templates boxingSnippets; protected IdentityHashCodeSnippets.Templates identityHashCodeSnippets; protected IsArraySnippets.Templates isArraySnippets; + protected StringLatin1Snippets.Templates latin1Templates; + protected StringUTF16Snippets.Templates utf16templates; public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, PlatformConfigurationProvider platformConfig, MetaAccessExtensionProvider metaAccessExtensionProvider, @@ -203,6 +205,10 @@ public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsPr public void initialize(OptionValues options, SnippetCounter.Group.Factory factory, Providers providers) { replacements = providers.getReplacements(); boxingSnippets = new BoxingSnippets.Templates(options, factory, providers); + latin1Templates = new StringLatin1Snippets.Templates(options, providers); + providers.getReplacements().registerSnippetTemplateCache(latin1Templates); + utf16templates = new StringUTF16Snippets.Templates(options, providers); + providers.getReplacements().registerSnippetTemplateCache(utf16templates); providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, providers)); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java new file mode 100644 index 000000000000..9836146ad2ef --- /dev/null +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.graalvm.compiler.replacements; + +import java.lang.reflect.Type; + +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * A generic plugin used to implement substitution of methods by snippets. + */ +public abstract class SnippetSubstitutionInvocationPlugin extends InvocationPlugin.InlineOnlyInvocationPlugin { + + private final boolean hasSideEffect; + + public SnippetSubstitutionInvocationPlugin(boolean hasSideEffect, String name, Type... argumentTypes) { + super(name, argumentTypes); + this.hasSideEffect = hasSideEffect; + } + + public abstract SnippetTemplate.SnippetInfo getSnippet(); + + public abstract SnippetTemplate.AbstractTemplates getTemplates(); + + @Override + public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { + if (!b.isPluginEnabled(this)) { + return false; + } + if (receiver != null) { + // Perform the required null check + ValueNode r = receiver.get(); + assert args[0] == r; + } + Stamp stamp = b.getInvokeReturnStamp(b.getAssumptions()).getTrustedStamp(); + SnippetSubstitutionNode node; + SnippetTemplate.SnippetInfo snippet = getSnippet(); + SnippetTemplate.AbstractTemplates templates = getTemplates(); + if (hasSideEffect) { + SnippetSubstitutionStateSplitNode split = new SnippetSubstitutionStateSplitNode(templates, snippet, targetMethod, stamp, args); + split.setBci(b.bci()); + node = split; + } else { + node = new SnippetSubstitutionNode(templates, snippet, targetMethod, stamp, args); + } + node.setConstantArguments(getConstantArguments(targetMethod)); + JavaKind returnKind = targetMethod.getSignature().getReturnKind(); + if (returnKind != JavaKind.Void) { + b.addPush(returnKind, node); + } else { + b.add(node); + } + return true; + } + + /** + * Provide any extra arguments that should be passed to the {@link Snippet} as + * {@link ConstantParameter} arguments. + */ + @SuppressWarnings("unused") + protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { + return null; + } +} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java new file mode 100644 index 000000000000..1e03a4ff5506 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Lowerable; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.nodes.util.GraphUtil; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * A node that lowers a non-side effecting snippet. + */ +@NodeInfo(nameTemplate = "SnippetSubstitution#{p#snippet/s}", cycles = CYCLES_IGNORED, size = SIZE_IGNORED) +public class SnippetSubstitutionNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(SnippetSubstitutionNode.class); + + @Input protected NodeInputList arguments; + + protected Object[] constantArguments; + + protected final SnippetTemplate.SnippetInfo snippet; + protected final SnippetTemplate.AbstractTemplates templates; + protected final ResolvedJavaMethod targetMethod; + + public SnippetSubstitutionNode(SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, + Stamp stamp, ValueNode... arguments) { + this(TYPE, templates, snippet, targetMethod, stamp, arguments); + } + + protected SnippetSubstitutionNode(NodeClass c, SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, + Stamp stamp, ValueNode... arguments) { + super(c, stamp); + this.arguments = new NodeInputList<>(this, arguments); + this.snippet = snippet; + this.templates = templates; + this.targetMethod = targetMethod; + } + + public ValueNode getArgument(int i) { + return arguments.get(i); + } + + public int getArgumentCount() { + return arguments.size(); + } + + public void setConstantArguments(Object[] arguments) { + this.constantArguments = arguments; + } + + @Override + public void lower(LoweringTool tool) { + SnippetTemplate.Arguments args = new SnippetTemplate.Arguments(snippet, this.graph().getGuardsStage(), tool.getLoweringStage()); + int arg = 0; + for (; arg < arguments.size(); arg++) { + args.add(snippet.getParameterName(arg), arguments.get(arg)); + } + if (constantArguments != null) { + for (Object argument : constantArguments) { + args.addConst(snippet.getParameterName(arg), argument); + arg++; + } + } + SnippetTemplate template = templates.template(this, args); + UnmodifiableEconomicMap duplicates = template.instantiate(tool.getMetaAccess(), this, SnippetTemplate.DEFAULT_REPLACER, args, false); + fixupNodes(tool, template, duplicates); + GraphUtil.killCFG(this); + } + + /** + * Perform any fixup required after instantiating the snippet. + * + * @param tool + * @param template the template for the snippet + * @param duplicates the map returned from + * {@link SnippetTemplate.AbstractTemplates#instantiate(MetaAccessProvider, FixedNode, SnippetTemplate.UsageReplacer, SnippetTemplate.Arguments, boolean)} + */ + protected void fixupNodes(LoweringTool tool, SnippetTemplate template, UnmodifiableEconomicMap duplicates) { + } + +} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java new file mode 100644 index 000000000000..47911dae9ba4 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements; + +import static org.graalvm.compiler.nodeinfo.InputType.State; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + +import java.util.Arrays; + +import org.graalvm.collections.UnmodifiableEconomicMap; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CallTargetNode; +import org.graalvm.compiler.nodes.DeoptBciSupplier; +import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.StateSplit; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * A node that lowers a non-side effecting snippet. + */ +@NodeInfo(nameTemplate = "SnippetSubstitutionStateSplit#{p#snippet/s}", cycles = CYCLES_IGNORED, size = SIZE_IGNORED) +public class SnippetSubstitutionStateSplitNode extends SnippetSubstitutionNode implements StateSplit, DeoptBciSupplier, DeoptimizingNode.DeoptDuring { + public static final NodeClass TYPE = NodeClass.create(SnippetSubstitutionStateSplitNode.class); + + int bci; + @OptionalInput(InputType.State) FrameState stateAfter; + @OptionalInput(State) FrameState stateDuring; + + public SnippetSubstitutionStateSplitNode(SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, Stamp stamp, ValueNode... arguments) { + super(TYPE, templates, snippet, targetMethod, stamp, arguments); + } + + @Override + public FrameState stateAfter() { + return stateAfter; + } + + @Override + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + @Override + public boolean hasSideEffect() { + return true; + } + + @Override + public int bci() { + return bci; + } + + @Override + public void setBci(int bci) { + this.bci = bci; + } + + @Override + protected void fixupNodes(LoweringTool tool, SnippetTemplate template, UnmodifiableEconomicMap duplicates) { + super.fixupNodes(tool, template, duplicates); + if (!template.hasSideEffects()) { + throw new InternalError("snippet " + snippet + " has no side effects"); + } + for (Node originalNode : duplicates.getKeys()) { + if (originalNode instanceof InvokeNode) { + InvokeNode invoke = (InvokeNode) duplicates.get(originalNode); + + // Here we need to fix the bci of the invoke + if (invoke.bci() != bci()) { + invoke.setBci(bci()); + } + invoke.setStateDuring(null); + invoke.setStateAfter(null); + FrameState newStateAfter = stateAfter(); + JavaKind returnKind = invoke.getStackKind(); + if (returnKind != JavaKind.Void) { + // Replace the return value with the invoke itself + newStateAfter = newStateAfter.duplicateModified(returnKind, returnKind, invoke, null); + } + invoke.setStateAfter(newStateAfter); + + // Replace the call target that points at the original snippet with the actual + // target method. If any constants arguments were injected then strip those + // arguments off as well. + CallTargetNode targetNode = invoke.callTarget(); + ValueNode[] invokeArguments = targetNode.arguments().toArray(new ValueNode[0]); + if (constantArguments != null) { + invokeArguments = Arrays.copyOf(invokeArguments, invokeArguments.length - constantArguments.length); + } + MethodCallTargetNode target = graph().add(new MethodCallTargetNode(targetMethod.isStatic() ? CallTargetNode.InvokeKind.Static : CallTargetNode.InvokeKind.Virtual, + targetMethod, invokeArguments, targetNode.returnStamp(), null)); + targetNode.replaceAndDelete(target); + tool.getLowerer().lower(invoke, tool); + } else if (originalNode instanceof InvokeWithExceptionNode) { + throw new GraalError("unexpected invoke with exception %s in snippet", originalNode); + } + } + } + + @Override + public FrameState stateDuring() { + return stateDuring; + } + + @Override + public void setStateDuring(FrameState stateDuring) { + updateUsages(this.stateDuring, stateDuring); + this.stateDuring = stateDuring; + } + + @Override + public void computeStateDuring(FrameState currentStateAfter) { + FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, getStackKind()); + setStateDuring(newStateDuring); + } + + @Override + public boolean canDeoptimize() { + return true; + } +} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 2275d7658b3a..c0e8a686060f 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -92,6 +92,7 @@ import org.graalvm.compiler.nodes.DeoptBciSupplier; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.DeoptimizingNode.DeoptBefore; +import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; @@ -1633,6 +1634,10 @@ private EconomicMap bind(StructuredGraph replaceeGraph, MetaAccessPr return replacements; } + public boolean hasSideEffects() { + return !sideEffectNodes.isEmpty(); + } + /** * Converts a Java boxed value to a {@link JavaConstant} of the right kind. This adjusts for the * limitation that a {@link Local}'s kind is a {@linkplain JavaKind#getStackKind() stack kind} @@ -2431,8 +2436,18 @@ private void setReplaceeGraphStateAfter(Node nodeRequiringState, Node replacee, if (!(nodeRequiringState instanceof AbstractMergeNode || nodeRequiringState instanceof LoopExitNode)) { // merges and loop exit cannot have "this node" on stack if (valueInReplacement instanceof ValuePhiNode) { - Node sideEffectDup = duplicates.get(nodeRequiringState); - valueInReplacement = (ValueNode) sideEffectDup; + ValuePhiNode valuePhi = (ValuePhiNode) valueInReplacement; + FixedNode next = (FixedNode) nodeRequiringState; + while (next instanceof FixedWithNextNode) { + next = ((FixedWithNextNode) next).next(); + } + if (next instanceof EndNode) { + EndNode duplicateEnd = (EndNode) duplicates.get(next); + int endIndex = valuePhi.merge().forwardEndIndex(duplicateEnd); + if (endIndex != -1) { + valueInReplacement = valuePhi.valueAt(endIndex); + } + } } } propagateValInState(newState, replacee, valueInReplacement); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Substitutions.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java similarity index 89% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Substitutions.java rename to compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java index d2002bc4bdf3..e5ae07cefa82 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Substitutions.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java @@ -32,9 +32,10 @@ import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayIndexScale; -import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; import jdk.vm.ci.meta.JavaKind; @@ -43,8 +44,16 @@ /** * Substitutions for {@code java.lang.StringLatin1} methods. */ -@ClassSubstitution(className = "java.lang.StringLatin1", optional = true) -public class StringLatin1Substitutions { +public class StringLatin1Snippets implements Snippets { + + public static class Templates extends SnippetTemplate.AbstractTemplates { + + public Templates(OptionValues options, Providers providers) { + super(options, providers); + } + + public final SnippetTemplate.SnippetInfo indexOf = snippet(StringLatin1Snippets.class, "indexOf"); + } /** Marker value for the {@link InjectedParameter} injected parameter. */ public static final MetaAccessProvider INJECTED = null; @@ -53,7 +62,7 @@ private static long byteArrayOffset(long offset) { return byteArrayBaseOffset(INJECTED) + (offset * byteArrayIndexScale(INJECTED)); } - @MethodSubstitution + @Snippet public static int indexOf(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { ReplacementsUtil.dynamicAssert(fromIndex >= 0, "StringLatin1.indexOf invalid args: fromIndex negative"); ReplacementsUtil.dynamicAssert(targetCount > 0, "StringLatin1.indexOf invalid args: targetCount <= 0"); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Substitutions.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java similarity index 90% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Substitutions.java rename to compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java index 7ef2e76bd6c6..be37283ba4dc 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Substitutions.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java @@ -32,21 +32,31 @@ import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; -import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.nodes.extended.JavaReadNode; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; /** - * Substitutions for {@code java.lang.StringUTF16} methods. + * Snippets for for {@code java.lang.StringUTF16} methods. */ -@ClassSubstitution(className = "java.lang.StringUTF16", optional = true) -public class StringUTF16Substitutions { +public class StringUTF16Snippets implements Snippets { + public static class Templates extends SnippetTemplate.AbstractTemplates { + + public Templates(OptionValues options, Providers providers) { + super(options, providers); + } + + public final SnippetTemplate.SnippetInfo indexOfLatin1Unsafe = snippet(StringUTF16Snippets.class, "indexOfLatin1Unsafe"); + public final SnippetTemplate.SnippetInfo indexOfUnsafe = snippet(StringUTF16Snippets.class, "indexOfUnsafe"); + } + /** * Marker value for the {@link InjectedParameter} injected parameter. */ @@ -65,7 +75,7 @@ private static long byteArrayCharOffset(long offset) { */ private static native char getChar(byte[] value, int i); - @MethodSubstitution + @Snippet public static int indexOfUnsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { ReplacementsUtil.dynamicAssert(fromIndex >= 0, "StringUTF16.indexOfUnsafe invalid args: fromIndex negative"); ReplacementsUtil.dynamicAssert(targetCount > 0, "StringUTF16.indexOfUnsafe invalid args: targetCount <= 0"); @@ -96,7 +106,7 @@ public static int indexOfUnsafe(byte[] source, int sourceCount, byte[] target, i } } - @MethodSubstitution + @Snippet public static int indexOfLatin1Unsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { ReplacementsUtil.dynamicAssert(fromIndex >= 0, "StringUTF16.indexOfLatin1Unsafe invalid args: fromIndex negative"); ReplacementsUtil.dynamicAssert(targetCount > 0, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount <= 0"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index 71137a990f29..be3420d274b2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -108,11 +108,14 @@ public interface GraphMakerFactory { protected static class Builder { protected final GraphMakerFactory graphMakerFactory; protected final Map graphs; + protected Map deferred; + protected boolean processing; protected final Set delayedInvocationPluginMethods; protected Builder(GraphMakerFactory graphMakerFactory) { this.graphMakerFactory = graphMakerFactory; this.graphs = new HashMap<>(); + this.deferred = new HashMap<>(); this.delayedInvocationPluginMethods = new HashSet<>(); } } @@ -254,21 +257,30 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin assert DirectAnnotationAccess.isAnnotationPresent(method, Snippet.class) : "Snippet must be annotated with @" + Snippet.class.getSimpleName() + " " + method; assert method.hasBytecodes() : "Snippet must not be abstract or native"; assert builder.graphs.get(method) == null : "snippet registered twice: " + method.getName(); + assert builder.deferred.get(method) == null : "snippet registered twice: " + method.getName(); + + Runnable run = new Runnable() { + public void run() { + try (DebugContext debug = openSnippetDebugContext("Snippet_", method, options)) { + Object[] args = prepareConstantArguments(receiver); + StructuredGraph graph = makeGraph(debug, defaultBytecodeProvider, method, args, SnippetParameterInfo.getNonNullParameters(getSnippetParameterInfo(method)), null, + trackNodeSourcePosition, null); + + // Check if all methods which should be inlined are really inlined. + for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { + ResolvedJavaMethod callee = callTarget.targetMethod(); + if (!builder.delayedInvocationPluginMethods.contains(callee)) { + throw shouldNotReachHere("method " + callee.format("%h.%n") + " not inlined in snippet " + method.format("%h.%n") + " (maybe not final?)"); + } + } - try (DebugContext debug = openSnippetDebugContext("Snippet_", method, options)) { - Object[] args = prepareConstantArguments(receiver); - StructuredGraph graph = makeGraph(debug, defaultBytecodeProvider, method, args, SnippetParameterInfo.getNonNullParameters(getSnippetParameterInfo(method)), null, trackNodeSourcePosition, - null); - - // Check if all methods which should be inlined are really inlined. - for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { - ResolvedJavaMethod callee = callTarget.targetMethod(); - if (!builder.delayedInvocationPluginMethods.contains(callee)) { - throw shouldNotReachHere("method " + callee.format("%h.%n") + " not inlined in snippet " + method.format("%h.%n") + " (maybe not final?)"); + builder.graphs.put(method, graph); } } - - builder.graphs.put(method, graph); + }; + builder.deferred.put(method, run); + if (builder.processing) { + System.err.println(Thread.currentThread() + " " + method); } } @@ -280,6 +292,14 @@ public Set getDelayedInvocationPluginMethods() { @Platforms(Platform.HOSTED_ONLY.class) public void encodeSnippets() { GraphEncoder encoder = new GraphEncoder(ConfigurationValues.getTarget().arch); + Map deferred = builder.deferred; + builder.deferred = new HashMap<>(); + for (Runnable run : deferred.values()) { + run.run(); + } + for (Runnable run : builder.deferred.values()) { + run.run(); + } for (StructuredGraph graph : builder.graphs.values()) { encoder.prepare(graph); } From be40b80f62ec37420858e0bbfc7a7b7acfd5f01b Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 1 Feb 2022 12:33:27 -0800 Subject: [PATCH 02/18] Style fix --- .../oracle/svm/core/graal/meta/SubstrateReplacements.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index be3420d274b2..e08336713324 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -109,7 +109,6 @@ protected static class Builder { protected final GraphMakerFactory graphMakerFactory; protected final Map graphs; protected Map deferred; - protected boolean processing; protected final Set delayedInvocationPluginMethods; protected Builder(GraphMakerFactory graphMakerFactory) { @@ -260,6 +259,7 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin assert builder.deferred.get(method) == null : "snippet registered twice: " + method.getName(); Runnable run = new Runnable() { + @Override public void run() { try (DebugContext debug = openSnippetDebugContext("Snippet_", method, options)) { Object[] args = prepareConstantArguments(receiver); @@ -279,9 +279,6 @@ public void run() { } }; builder.deferred.put(method, run); - if (builder.processing) { - System.err.println(Thread.currentThread() + " " + method); - } } @Platforms(Platform.HOSTED_ONLY.class) From 362a6518813837713ab3c8fafed337c3cc81100b Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 1 Feb 2022 12:49:21 -0800 Subject: [PATCH 03/18] Cleanup deferring of snippet processing --- .../hotspot/SymbolicSnippetEncoder.java | 56 +++++++------------ .../graal/meta/SubstrateReplacements.java | 22 ++++---- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 7066b7c51d09..0b513ea59810 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -154,12 +154,6 @@ public class SymbolicSnippetEncoder { private final HotSpotReplacementsImpl originalReplacements; - /** - * The current count of graphs encoded. Used to detect when new graphs have been enqueued for - * encoding. - */ - private int encodedGraphs = 0; - abstract static class GraphKey { final ResolvedJavaMethod method; final ResolvedJavaMethod original; @@ -272,12 +266,7 @@ public String toString() { } } - private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); - - /** - * All the graphs parsed so far. - */ - private final EconomicMap preparedSnippetGraphs = EconomicMap.create(); + private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); private final EconomicMap snippetParameterInfos = EconomicMap.create(); @@ -482,10 +471,10 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod } /** - * If there are new graphs waiting to be encoded, reencode all the graphs and return the result. + * Encode all pending graphs and return the result. */ @SuppressWarnings("try") - private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { + private synchronized EncodedSnippets encodeSnippets(OptionValues options) { GraphBuilderConfiguration.Plugins plugins = originalReplacements.getGraphBuilderPlugins(); InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); @@ -496,26 +485,22 @@ private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); copy.appendNodePlugin(new SnippetCounterPlugin(snippetReplacements)); - if (!pendingSnippetGraphs.isEmpty()) { - for (BiFunction function : pendingSnippetGraphs.getValues()) { - function.apply(options, snippetReplacements); - } + EconomicMap preparedSnippetGraphs = EconomicMap.create(); + MapCursor> cursor = pendingSnippetGraphs.getEntries(); + while (cursor.advance()) { + GraphKey key = cursor.getKey(); + preparedSnippetGraphs.put(key, cursor.getValue().apply(options, snippetReplacements)); } - EconomicMap graphs = this.preparedSnippetGraphs; - if (encodedGraphs != graphs.size()) { - DebugContext debug = snippetReplacements.openSnippetDebugContext("SnippetEncoder", null, options); - try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { - encodedGraphs = graphs.size(); - for (StructuredGraph graph : graphs.getValues()) { - for (Node node : graph.getNodes()) { - node.setNodeSourcePosition(null); - } + + DebugContext debug = snippetReplacements.openSnippetDebugContext("SnippetEncoder", null, options); + try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { + for (StructuredGraph graph : preparedSnippetGraphs.getValues()) { + for (Node node : graph.getNodes()) { + node.setNodeSourcePosition(null); } - return encodeSnippets(debug); } + return encodeSnippets(debug, preparedSnippetGraphs); } - return null; - } synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { @@ -553,13 +538,12 @@ synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } } } - pendingSnippetGraphs.put(key, new BiFunction() { + pendingSnippetGraphs.put(key, new BiFunction<>() { @Override - public Void apply(OptionValues cmopileOptions, HotSpotSnippetReplacementsImpl snippetReplacements) { + public StructuredGraph apply(OptionValues cmopileOptions, HotSpotSnippetReplacementsImpl snippetReplacements) { StructuredGraph snippet = buildGraph(method, original, null, receiver, SnippetParameterInfo.getNonNullParameters(info), true, trackNodeSourcePosition, INLINE_AFTER_PARSING, cmopileOptions, snippetReplacements); - preparedSnippetGraphs.put(key, snippet); - return null; + return snippet; } }); } @@ -605,7 +589,7 @@ private boolean verifySingle(DebugContext debug, StructuredGraph graph) { } } - private synchronized EncodedSnippets encodeSnippets(DebugContext debug) { + private synchronized EncodedSnippets encodeSnippets(DebugContext debug, EconomicMap preparedSnippetGraphs) { GraphEncoder encoder = new GraphEncoder(HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch, debug); for (StructuredGraph graph : preparedSnippetGraphs.getValues()) { graph.resetDebug(debug); @@ -647,7 +631,7 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug) { */ @SuppressWarnings("try") public synchronized boolean encode(OptionValues options) { - EncodedSnippets encodedSnippets = maybeEncodeSnippets(options); + EncodedSnippets encodedSnippets = encodeSnippets(options); if (encodedSnippets != null) { HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); return true; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index e08336713324..dcaa06df89fe 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -28,10 +28,12 @@ import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Collection; +import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -108,13 +110,15 @@ public interface GraphMakerFactory { protected static class Builder { protected final GraphMakerFactory graphMakerFactory; protected final Map graphs; - protected Map deferred; + protected final Deque deferred; + protected final HashSet registered; protected final Set delayedInvocationPluginMethods; protected Builder(GraphMakerFactory graphMakerFactory) { this.graphMakerFactory = graphMakerFactory; this.graphs = new HashMap<>(); - this.deferred = new HashMap<>(); + this.deferred = new ArrayDeque<>(); + this.registered = new HashSet<>(); this.delayedInvocationPluginMethods = new HashSet<>(); } } @@ -256,8 +260,9 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin assert DirectAnnotationAccess.isAnnotationPresent(method, Snippet.class) : "Snippet must be annotated with @" + Snippet.class.getSimpleName() + " " + method; assert method.hasBytecodes() : "Snippet must not be abstract or native"; assert builder.graphs.get(method) == null : "snippet registered twice: " + method.getName(); - assert builder.deferred.get(method) == null : "snippet registered twice: " + method.getName(); + assert builder.registered.add(method) : "snippet registered twice: " + method.getName(); + // Defer the processing until encodeSnippets Runnable run = new Runnable() { @Override public void run() { @@ -278,7 +283,7 @@ public void run() { } } }; - builder.deferred.put(method, run); + builder.deferred.add(run); } @Platforms(Platform.HOSTED_ONLY.class) @@ -289,13 +294,8 @@ public Set getDelayedInvocationPluginMethods() { @Platforms(Platform.HOSTED_ONLY.class) public void encodeSnippets() { GraphEncoder encoder = new GraphEncoder(ConfigurationValues.getTarget().arch); - Map deferred = builder.deferred; - builder.deferred = new HashMap<>(); - for (Runnable run : deferred.values()) { - run.run(); - } - for (Runnable run : builder.deferred.values()) { - run.run(); + while (!builder.deferred.isEmpty()) { + builder.deferred.pop().run(); } for (StructuredGraph graph : builder.graphs.values()) { encoder.prepare(graph); From be3a43522f95abeec4cca0814c1af52205a4104d Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 4 Feb 2022 10:27:27 -0800 Subject: [PATCH 04/18] Generify SnippetSubstitutionInvocationPlugin --- .../meta/HotSpotGraphBuilderPlugins.java | 36 +++---------- .../aarch64/AArch64GraphBuilderPlugins.java | 36 +++---------- .../amd64/AMD64GraphBuilderPlugins.java | 53 +++++-------------- .../SnippetSubstitutionInvocationPlugin.java | 22 +++++--- 4 files changed, 43 insertions(+), 104 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index eff70853ccd6..ca33830352b2 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -776,21 +776,11 @@ private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVM private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { Registration r = new Registration(plugins, BigInteger.class, replacements); - r.registerConditional(config.useMultiplyToLenIntrinsic(), new SnippetSubstitutionInvocationPlugin(true, "implMultiplyToLen", int[].class, int.class, int[].class, int.class, int[].class) { - BigIntegerSnippets.Templates templates; - + r.registerConditional(config.useMultiplyToLenIntrinsic(), new SnippetSubstitutionInvocationPlugin<>(BigIntegerSnippets.Templates.class, true, + "implMultiplyToLen", int[].class, int.class, int[].class, int.class, int[].class) { @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().implMultiplyToLen; - } - - @Override - public BigIntegerSnippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(BigIntegerSnippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(BigIntegerSnippets.Templates templates) { + return templates.implMultiplyToLen; } }); r.registerConditional(config.useMulAddIntrinsic(), new InvocationPlugin("implMulAdd", int[].class, int[].class, int.class, int.class, int.class) { @@ -889,9 +879,8 @@ private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVM boolean implCompressMultiBlock0Enabled = isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && (useSha1 || useSha256 || useSha512); Registration r = new Registration(plugins, "sun.security.provider.DigestBase", replacements); - r.registerConditional(implCompressMultiBlock0Enabled, new SnippetSubstitutionInvocationPlugin(true, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class) { - DigestBaseSnippets.Templates templates; - + r.registerConditional(implCompressMultiBlock0Enabled, new SnippetSubstitutionInvocationPlugin<>(DigestBaseSnippets.Templates.class, true, + "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class) { @Override protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { Object[] constantArguments = new Object[4]; @@ -904,17 +893,8 @@ protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { } @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().implCompressMultiBlock0; - } - - @Override - public DigestBaseSnippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(DigestBaseSnippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(DigestBaseSnippets.Templates templates) { + return templates.implCompressMultiBlock0; } }); diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index 6bf37929165d..5ec9587804b1 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -289,21 +289,11 @@ private static void registerStringLatin1Plugins(InvocationPlugins plugins, Repla r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Byte, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Char, "compareToUTF16", byte[].class, byte[].class)); - r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { - StringLatin1Snippets.Templates templates; - + r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, false, + "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().indexOf; - } - - @Override - public StringLatin1Snippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(StringLatin1Snippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(StringLatin1Snippets.Templates templates) { + return templates.indexOf; } }); r.register(new StringLatin1IndexOfCharPlugin()); @@ -314,21 +304,11 @@ private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replac r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Char, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Byte, true, "compareToLatin1", byte[].class, byte[].class)); - r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { - StringUTF16Snippets.Templates templates; - + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().indexOfUnsafe; - } - - @Override - public StringUTF16Snippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { + return templates.indexOfUnsafe; } }); r.register(new InvocationPlugin("indexOfCharUnsafe", byte[].class, int.class, int.class, int.class) { diff --git a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java index c64dd86580ef..12b3e62ab2a9 100644 --- a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java @@ -362,21 +362,11 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { - StringLatin1Snippets.Templates templates; - + r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, false, + "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().indexOf; - } - - @Override - public StringLatin1Snippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(StringLatin1Snippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(StringLatin1Snippets.Templates templates) { + return templates.indexOf; } }); r.register(new StringLatin1IndexOfCharPlugin()); @@ -463,39 +453,20 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { - StringUTF16Snippets.Templates templates; - - @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().indexOfUnsafe; - } - + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override - public StringUTF16Snippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); - assert templates != null; - } - return templates; + public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { + return templates.indexOfUnsafe; } }); - r.register(new SnippetSubstitutionInvocationPlugin(false, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class) { - StringUTF16Snippets.Templates templates; - + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override - public SnippetTemplate.SnippetInfo getSnippet() { - return getTemplates().indexOfLatin1Unsafe; + public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { + return templates.indexOfLatin1Unsafe; } - @Override - public StringUTF16Snippets.Templates getTemplates() { - if (templates == null) { - templates = replacements.getSnippetTemplateCache(StringUTF16Snippets.Templates.class); - assert templates != null; - } - return templates; - } }); r.register(new InvocationPlugin("indexOfCharUnsafe", byte[].class, int.class, int.class, int.class) { @Override diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java index 9836146ad2ef..f4c63d0f58d1 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; @@ -40,18 +41,18 @@ /** * A generic plugin used to implement substitution of methods by snippets. */ -public abstract class SnippetSubstitutionInvocationPlugin extends InvocationPlugin.InlineOnlyInvocationPlugin { +public abstract class SnippetSubstitutionInvocationPlugin extends InvocationPlugin.InlineOnlyInvocationPlugin { private final boolean hasSideEffect; + private final Class templateClass; - public SnippetSubstitutionInvocationPlugin(boolean hasSideEffect, String name, Type... argumentTypes) { + public SnippetSubstitutionInvocationPlugin(Class templateClass, boolean hasSideEffect, String name, Type... argumentTypes) { super(name, argumentTypes); this.hasSideEffect = hasSideEffect; + this.templateClass = templateClass; } - public abstract SnippetTemplate.SnippetInfo getSnippet(); - - public abstract SnippetTemplate.AbstractTemplates getTemplates(); + public abstract SnippetTemplate.SnippetInfo getSnippet(T templates); @Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { @@ -63,10 +64,14 @@ public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, I ValueNode r = receiver.get(); assert args[0] == r; } + + // Build the appropriate node to represent snippet until it's lowered Stamp stamp = b.getInvokeReturnStamp(b.getAssumptions()).getTrustedStamp(); SnippetSubstitutionNode node; - SnippetTemplate.SnippetInfo snippet = getSnippet(); - SnippetTemplate.AbstractTemplates templates = getTemplates(); + + T templates = b.getReplacements().getSnippetTemplateCache(templateClass); + GraalError.guarantee(templates != null, "Missing templates for " + templateClass); + SnippetTemplate.SnippetInfo snippet = getSnippet(templates); if (hasSideEffect) { SnippetSubstitutionStateSplitNode split = new SnippetSubstitutionStateSplitNode(templates, snippet, targetMethod, stamp, args); split.setBci(b.bci()); @@ -74,7 +79,10 @@ public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, I } else { node = new SnippetSubstitutionNode(templates, snippet, targetMethod, stamp, args); } + + // Transfer any extra constant arguments required for the lowering node.setConstantArguments(getConstantArguments(targetMethod)); + JavaKind returnKind = targetMethod.getSignature().getReturnKind(); if (returnKind != JavaKind.Void) { b.addPush(returnKind, node); From 7b9eee06395180bb226acb649ddfc5d28b550088 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 7 Feb 2022 00:09:58 -0800 Subject: [PATCH 05/18] Use macro node for snippet substitutions --- .../hotspot/SnippetResolvedJavaMethod.java | 2 +- .../meta/HotSpotGraphBuilderPlugins.java | 4 +- .../replacements/DigestBaseSnippets.java | 7 +- .../aarch64/AArch64GraphBuilderPlugins.java | 4 +- .../amd64/AMD64GraphBuilderPlugins.java | 6 +- .../SnippetSubstitutionInvocationPlugin.java | 21 +-- .../replacements/SnippetSubstitutionNode.java | 61 ++----- .../SnippetSubstitutionStateSplitNode.java | 159 ------------------ .../FallbackInvokeWithExceptionNode.java | 6 + 9 files changed, 37 insertions(+), 233 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java index 0cb8730df17d..b5f6c7ad22c1 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SnippetResolvedJavaMethod.java @@ -107,7 +107,7 @@ public boolean isVarArgs() { @Override public boolean isBridge() { - return false; + throw new UnsupportedOperationException(); } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index ca33830352b2..022599b4d03c 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -776,7 +776,7 @@ private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVM private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, Replacements replacements) { Registration r = new Registration(plugins, BigInteger.class, replacements); - r.registerConditional(config.useMultiplyToLenIntrinsic(), new SnippetSubstitutionInvocationPlugin<>(BigIntegerSnippets.Templates.class, true, + r.registerConditional(config.useMultiplyToLenIntrinsic(), new SnippetSubstitutionInvocationPlugin<>(BigIntegerSnippets.Templates.class, "implMultiplyToLen", int[].class, int.class, int[].class, int.class, int[].class) { @Override public SnippetTemplate.SnippetInfo getSnippet(BigIntegerSnippets.Templates templates) { @@ -879,7 +879,7 @@ private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVM boolean implCompressMultiBlock0Enabled = isIntrinsicName(config, "sun/security/provider/DigestBase", "implCompressMultiBlock0") && (useSha1 || useSha256 || useSha512); Registration r = new Registration(plugins, "sun.security.provider.DigestBase", replacements); - r.registerConditional(implCompressMultiBlock0Enabled, new SnippetSubstitutionInvocationPlugin<>(DigestBaseSnippets.Templates.class, true, + r.registerConditional(implCompressMultiBlock0Enabled, new SnippetSubstitutionInvocationPlugin<>(DigestBaseSnippets.Templates.class, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class) { @Override protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java index 4f71ccd72ae6..acdff4818104 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSnippets.java @@ -40,6 +40,7 @@ import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.Snippets; +import org.graalvm.compiler.replacements.nodes.FallbackInvokeWithExceptionNode; import org.graalvm.compiler.word.Word; import org.graalvm.word.LocationIdentity; import org.graalvm.word.WordFactory; @@ -58,7 +59,7 @@ public Templates(OptionValues options, Providers providers) { public final SnippetTemplate.SnippetInfo implCompressMultiBlock0 = snippet(DigestBaseSnippets.class, "implCompressMultiBlock0"); } - @Snippet(allowPartialIntrinsicArgumentMismatch = true) + @Snippet static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int limit, @Snippet.ConstantParameter ResolvedJavaType receiverType, @Snippet.ConstantParameter ResolvedJavaType sha1type, @@ -83,9 +84,7 @@ static int implCompressMultiBlock0(Object receiver, byte[] buf, int ofs, int lim Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int))); return HotSpotBackend.sha5ImplCompressMBStub(bufAddr, stateAddr, ofs, limit); } else { - // This will be replaced by an invoke of original method with the extra - // ConstantParameter arguments removed. - return implCompressMultiBlock0(receiver, buf, ofs, limit, receiverType, sha1type, sha256type, sha512type); + return FallbackInvokeWithExceptionNode.fallbackFunctionCallInt(); } } diff --git a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index 5ec9587804b1..3d67599b3753 100644 --- a/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -289,7 +289,7 @@ private static void registerStringLatin1Plugins(InvocationPlugins plugins, Repla r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Byte, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Byte, JavaKind.Char, "compareToUTF16", byte[].class, byte[].class)); - r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, false, + r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public SnippetTemplate.SnippetInfo getSnippet(StringLatin1Snippets.Templates templates) { @@ -304,7 +304,7 @@ private static void registerStringUTF16Plugins(InvocationPlugins plugins, Replac r.setAllowOverwrite(true); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Char, "compareTo", byte[].class, byte[].class)); r.register(new ArrayCompareToPlugin(JavaKind.Char, JavaKind.Byte, true, "compareToLatin1", byte[].class, byte[].class)); - r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { diff --git a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java index 12b3e62ab2a9..b0948058bb5b 100644 --- a/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java @@ -362,7 +362,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, false, + r.register(new SnippetSubstitutionInvocationPlugin<>(StringLatin1Snippets.Templates.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public SnippetTemplate.SnippetInfo getSnippet(StringLatin1Snippets.Templates templates) { @@ -453,14 +453,14 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { return templates.indexOfUnsafe; } }); - r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, false, + r.register(new SnippetSubstitutionInvocationPlugin<>(StringUTF16Snippets.Templates.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public SnippetTemplate.SnippetInfo getSnippet(StringUTF16Snippets.Templates templates) { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java index f4c63d0f58d1..8ecedbb66cbd 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionInvocationPlugin.java @@ -29,11 +29,11 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.replacements.nodes.MacroNode; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -43,12 +43,10 @@ */ public abstract class SnippetSubstitutionInvocationPlugin extends InvocationPlugin.InlineOnlyInvocationPlugin { - private final boolean hasSideEffect; private final Class templateClass; - public SnippetSubstitutionInvocationPlugin(Class templateClass, boolean hasSideEffect, String name, Type... argumentTypes) { + public SnippetSubstitutionInvocationPlugin(Class templateClass, String name, Type... argumentTypes) { super(name, argumentTypes); - this.hasSideEffect = hasSideEffect; this.templateClass = templateClass; } @@ -65,20 +63,11 @@ public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, I assert args[0] == r; } - // Build the appropriate node to represent snippet until it's lowered - Stamp stamp = b.getInvokeReturnStamp(b.getAssumptions()).getTrustedStamp(); - SnippetSubstitutionNode node; - T templates = b.getReplacements().getSnippetTemplateCache(templateClass); - GraalError.guarantee(templates != null, "Missing templates for " + templateClass); + GraalError.guarantee(templates != null, "Missing templates for ", templateClass); SnippetTemplate.SnippetInfo snippet = getSnippet(templates); - if (hasSideEffect) { - SnippetSubstitutionStateSplitNode split = new SnippetSubstitutionStateSplitNode(templates, snippet, targetMethod, stamp, args); - split.setBci(b.bci()); - node = split; - } else { - node = new SnippetSubstitutionNode(templates, snippet, targetMethod, stamp, args); - } + MacroNode.MacroParams params = MacroNode.MacroParams.of(b, targetMethod, args); + SnippetSubstitutionNode node = new SnippetSubstitutionNode(templates, snippet, params); // Transfer any extra constant arguments required for the lowering node.setConstantArguments(getConstantArguments(targetMethod)); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java index 1e03a4ff5506..46fdfc06d87e 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionNode.java @@ -28,56 +28,31 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import org.graalvm.collections.UnmodifiableEconomicMap; -import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.util.GraphUtil; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.replacements.nodes.FallbackInvokeWithExceptionNode; +import org.graalvm.compiler.replacements.nodes.MacroNode; +import org.graalvm.compiler.replacements.nodes.MacroWithExceptionNode; /** * A node that lowers a non-side effecting snippet. */ @NodeInfo(nameTemplate = "SnippetSubstitution#{p#snippet/s}", cycles = CYCLES_IGNORED, size = SIZE_IGNORED) -public class SnippetSubstitutionNode extends FixedWithNextNode implements Lowerable { +public class SnippetSubstitutionNode extends MacroWithExceptionNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(SnippetSubstitutionNode.class); - @Input protected NodeInputList arguments; - protected Object[] constantArguments; protected final SnippetTemplate.SnippetInfo snippet; protected final SnippetTemplate.AbstractTemplates templates; - protected final ResolvedJavaMethod targetMethod; - - public SnippetSubstitutionNode(SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, - Stamp stamp, ValueNode... arguments) { - this(TYPE, templates, snippet, targetMethod, stamp, arguments); - } - protected SnippetSubstitutionNode(NodeClass c, SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, - Stamp stamp, ValueNode... arguments) { - super(c, stamp); - this.arguments = new NodeInputList<>(this, arguments); + public SnippetSubstitutionNode(T templates, SnippetTemplate.SnippetInfo snippet, MacroNode.MacroParams params) { + super(TYPE, params); this.snippet = snippet; this.templates = templates; - this.targetMethod = targetMethod; - } - - public ValueNode getArgument(int i) { - return arguments.get(i); - } - - public int getArgumentCount() { - return arguments.size(); } public void setConstantArguments(Object[] arguments) { @@ -98,20 +73,14 @@ public void lower(LoweringTool tool) { } } SnippetTemplate template = templates.template(this, args); - UnmodifiableEconomicMap duplicates = template.instantiate(tool.getMetaAccess(), this, SnippetTemplate.DEFAULT_REPLACER, args, false); - fixupNodes(tool, template, duplicates); - GraphUtil.killCFG(this); - } - - /** - * Perform any fixup required after instantiating the snippet. - * - * @param tool - * @param template the template for the snippet - * @param duplicates the map returned from - * {@link SnippetTemplate.AbstractTemplates#instantiate(MetaAccessProvider, FixedNode, SnippetTemplate.UsageReplacer, SnippetTemplate.Arguments, boolean)} - */ - protected void fixupNodes(LoweringTool tool, SnippetTemplate template, UnmodifiableEconomicMap duplicates) { + UnmodifiableEconomicMap duplicates = template.instantiate(tool.getMetaAccess(), this, SnippetTemplate.DEFAULT_REPLACER, args, true); + for (Node original : duplicates.getKeys()) { + if (original instanceof FallbackInvokeWithExceptionNode) { + Node replacement = duplicates.get(original); + if (replacement instanceof Lowerable) { + tool.getLowerer().lower(replacement, tool); + } + } + } } - } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java deleted file mode 100644 index 47911dae9ba4..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetSubstitutionStateSplitNode.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements; - -import static org.graalvm.compiler.nodeinfo.InputType.State; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; - -import java.util.Arrays; - -import org.graalvm.collections.UnmodifiableEconomicMap; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.CallTargetNode; -import org.graalvm.compiler.nodes.DeoptBciSupplier; -import org.graalvm.compiler.nodes.DeoptimizingNode; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.InvokeWithExceptionNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.java.MethodCallTargetNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * A node that lowers a non-side effecting snippet. - */ -@NodeInfo(nameTemplate = "SnippetSubstitutionStateSplit#{p#snippet/s}", cycles = CYCLES_IGNORED, size = SIZE_IGNORED) -public class SnippetSubstitutionStateSplitNode extends SnippetSubstitutionNode implements StateSplit, DeoptBciSupplier, DeoptimizingNode.DeoptDuring { - public static final NodeClass TYPE = NodeClass.create(SnippetSubstitutionStateSplitNode.class); - - int bci; - @OptionalInput(InputType.State) FrameState stateAfter; - @OptionalInput(State) FrameState stateDuring; - - public SnippetSubstitutionStateSplitNode(SnippetTemplate.AbstractTemplates templates, SnippetTemplate.SnippetInfo snippet, ResolvedJavaMethod targetMethod, Stamp stamp, ValueNode... arguments) { - super(TYPE, templates, snippet, targetMethod, stamp, arguments); - } - - @Override - public FrameState stateAfter() { - return stateAfter; - } - - @Override - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - @Override - public boolean hasSideEffect() { - return true; - } - - @Override - public int bci() { - return bci; - } - - @Override - public void setBci(int bci) { - this.bci = bci; - } - - @Override - protected void fixupNodes(LoweringTool tool, SnippetTemplate template, UnmodifiableEconomicMap duplicates) { - super.fixupNodes(tool, template, duplicates); - if (!template.hasSideEffects()) { - throw new InternalError("snippet " + snippet + " has no side effects"); - } - for (Node originalNode : duplicates.getKeys()) { - if (originalNode instanceof InvokeNode) { - InvokeNode invoke = (InvokeNode) duplicates.get(originalNode); - - // Here we need to fix the bci of the invoke - if (invoke.bci() != bci()) { - invoke.setBci(bci()); - } - invoke.setStateDuring(null); - invoke.setStateAfter(null); - FrameState newStateAfter = stateAfter(); - JavaKind returnKind = invoke.getStackKind(); - if (returnKind != JavaKind.Void) { - // Replace the return value with the invoke itself - newStateAfter = newStateAfter.duplicateModified(returnKind, returnKind, invoke, null); - } - invoke.setStateAfter(newStateAfter); - - // Replace the call target that points at the original snippet with the actual - // target method. If any constants arguments were injected then strip those - // arguments off as well. - CallTargetNode targetNode = invoke.callTarget(); - ValueNode[] invokeArguments = targetNode.arguments().toArray(new ValueNode[0]); - if (constantArguments != null) { - invokeArguments = Arrays.copyOf(invokeArguments, invokeArguments.length - constantArguments.length); - } - MethodCallTargetNode target = graph().add(new MethodCallTargetNode(targetMethod.isStatic() ? CallTargetNode.InvokeKind.Static : CallTargetNode.InvokeKind.Virtual, - targetMethod, invokeArguments, targetNode.returnStamp(), null)); - targetNode.replaceAndDelete(target); - tool.getLowerer().lower(invoke, tool); - } else if (originalNode instanceof InvokeWithExceptionNode) { - throw new GraalError("unexpected invoke with exception %s in snippet", originalNode); - } - } - } - - @Override - public FrameState stateDuring() { - return stateDuring; - } - - @Override - public void setStateDuring(FrameState stateDuring) { - updateUsages(this.stateDuring, stateDuring); - this.stateDuring = stateDuring; - } - - @Override - public void computeStateDuring(FrameState currentStateAfter) { - FrameState newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, getStackKind()); - setStateDuring(newStateDuring); - } - - @Override - public boolean canDeoptimize() { - return true; - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java index 690d1a107db8..12ace45b7ee2 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/FallbackInvokeWithExceptionNode.java @@ -80,4 +80,10 @@ public boolean updateInitialStamp(Stamp newStamp) { */ @NodeIntrinsic public static native Object fallbackFunctionCall(); + + /** + * @see FallbackInvokeWithExceptionNode + */ + @NodeIntrinsic + public static native int fallbackFunctionCallInt(); } From 510f75556c5b3ed37d35cf97d2457771df96abf7 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 7 Feb 2022 13:45:41 -0800 Subject: [PATCH 06/18] Properly conditionalize string substititution template registration --- .../replacements/DefaultJavaLoweringProvider.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java index f4c28a05fc7c..2d563fad53a9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java @@ -27,6 +27,7 @@ import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; import static jdk.vm.ci.meta.DeoptimizationReason.BoundsCheckException; import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import static org.graalvm.compiler.core.common.GraalOptions.EmitStringSubstitutions; import static org.graalvm.compiler.core.common.SpectrePHTMitigations.Options.SpectrePHTIndexMasking; import static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION; import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.branchlessMax; @@ -205,10 +206,12 @@ public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsPr public void initialize(OptionValues options, SnippetCounter.Group.Factory factory, Providers providers) { replacements = providers.getReplacements(); boxingSnippets = new BoxingSnippets.Templates(options, factory, providers); - latin1Templates = new StringLatin1Snippets.Templates(options, providers); - providers.getReplacements().registerSnippetTemplateCache(latin1Templates); - utf16templates = new StringUTF16Snippets.Templates(options, providers); - providers.getReplacements().registerSnippetTemplateCache(utf16templates); + if (EmitStringSubstitutions.getValue(options)) { + latin1Templates = new StringLatin1Snippets.Templates(options, providers); + providers.getReplacements().registerSnippetTemplateCache(latin1Templates); + utf16templates = new StringUTF16Snippets.Templates(options, providers); + providers.getReplacements().registerSnippetTemplateCache(utf16templates); + } providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, providers)); } From 8c838616983da5784adb7fbfc0423e29b902407c Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 9 Feb 2022 23:57:11 -0800 Subject: [PATCH 07/18] Remove MethodSubstitutions --- .../api/replacements/ClassSubstitution.java | 67 -- .../api/replacements/MethodSubstitution.java | 107 --- .../core/test/CheckGraalInvariants.java | 3 +- .../test/HotSpotMethodSubstitutionTest.java | 3 +- .../test/MethodSubstitutionEffectTest.java | 413 ----------- .../MethodSubstitutionForeignCallTest.java | 285 -------- .../hotspot/test/TestIntrinsicCompiles.java | 13 +- .../compiler/hotspot/EncodedSnippets.java | 38 +- .../hotspot/HotSpotReplacementsImpl.java | 75 -- .../hotspot/SymbolicSnippetEncoder.java | 87 +-- .../graalvm/compiler/java/BytecodeParser.java | 135 ---- .../compiler/java/BytecodeParserOptions.java | 5 +- .../compiler/nodes/StructuredGraph.java | 10 +- .../graphbuilderconf/GraphBuilderContext.java | 29 - .../graphbuilderconf/InlineInvokePlugin.java | 22 +- .../graphbuilderconf/IntrinsicContext.java | 3 - .../graphbuilderconf/InvocationPlugins.java | 90 +-- .../MethodSubstitutionPlugin.java | 266 ------- .../nodes/spi/DelegatingReplacements.java | 13 - .../compiler/nodes/spi/Replacements.java | 32 +- .../phases/common/inlining/InliningUtil.java | 13 +- .../processor/ClassSubstitutionHandler.java | 111 --- .../processor/MethodSubstitutionHandler.java | 274 -------- .../ReplacementsAnnotationProcessor.java | 2 - .../compiler/replacements/test/FoldTest.java | 110 --- .../test/MethodSubstitutionTest.java | 7 +- .../test/ReplacementsParseTest.java | 665 ------------------ .../test/RootMethodSubstitutionTest.java | 165 ----- .../test/StandardMethodSubstitutionsTest.java | 3 +- .../SubstitutionNodeSourcePositionTest.java | 52 -- .../replacements/test/SubstitutionsTest.java | 167 ----- .../test/classfile/RedefineIntrinsicTest.java | 264 ------- .../replacements/CachingPEGraphDecoder.java | 30 +- .../replacements/IntrinsicGraphBuilder.java | 16 +- .../compiler/replacements/PEGraphDecoder.java | 18 +- .../replacements/ReplacementsImpl.java | 108 +-- .../replacements/StringSubstitutions.java | 2 - .../replacements/nodes/MacroInvokable.java | 3 - .../pointsto/phases/InlineBeforeAnalysis.java | 4 +- .../graal/meta/SubstrateReplacements.java | 10 +- .../hotspot/libgraal/LibGraalFeature.java | 44 -- .../com/oracle/svm/graal/GraalSupport.java | 3 +- .../truffle/api/SubstratePEGraphDecoder.java | 8 +- 43 files changed, 73 insertions(+), 3702 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/ClassSubstitution.java delete mode 100644 compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionEffectTest.java delete mode 100644 compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionForeignCallTest.java delete mode 100644 compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java delete mode 100644 compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java diff --git a/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/ClassSubstitution.java b/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/ClassSubstitution.java deleted file mode 100644 index b638c80b2aef..000000000000 --- a/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/ClassSubstitution.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.replacements; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Denotes a class that substitutes methods of another specified class. The substitute methods are - * exactly those annotated by {@link MethodSubstitution}. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ClassSubstitution { - - /** - * Specifies the original class. - *

- * If the default value is specified for this element, then a non-default value must be given - * for the {@link #className()} element. - */ - Class value() default ClassSubstitution.class; - - /** - * Specifies the original class or classes if a single class is being used for multiple - * substitutions. - *

- * This method is provided for cases where the original class is not accessible (according to - * Java language access control rules). - *

- * If the default value is specified for this element, then a non-default value must be given - * for the {@link #value()} element. - */ - String[] className() default {}; - - /** - * Determines if the substitutions are for classes that may not be part of the runtime. - * Substitutions for such classes are omitted if the original classes cannot be found. If - * multiple classes are specified using {@link #className()} and {@link #optional()} is false, - * then at least one of the classes is required to be reachable. - */ - boolean optional() default false; -} diff --git a/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java b/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java deleted file mode 100644 index 5849de7b8c80..000000000000 --- a/compiler/src/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.replacements; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Array; - -import jdk.vm.ci.meta.Signature; - -/** - * Denotes a method whose body is used by a compiler as the substitute (or intrinsification) of - * another method. The exact mechanism used to do the substitution is compiler dependent but every - * compiler should require substitute methods to be annotated with {@link MethodSubstitution}. - * - * A compiler may support partial intrinsification where only a part of a method is implemented by - * the compiler. The unsupported path is expressed by a call to either the original or substitute - * method from within the substitute method. Such as call is a partial intrinsic exit. - * - * For example, here's a HotSpot specific intrinsic for {@link Array#newInstance(Class, int)} that - * only handles the case where the VM representation of the array class to be instantiated already - * exists: - * - *

- * @MethodSubstitution
- * public static Object newInstance(Class componentType, int length) {
- *     if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
- *         // Array class not yet created - exit the intrinsic and call the original method
- *         return newInstance(componentType, length);
- *     }
- *     return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
- * }
- * 
- * - * Here's the same intrinsification where the exit is expressed as a call to the original method: - * - *
- * @MethodSubstitution
- * public static Object newInstance(Class componentType, int length) {
- *     if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
- *         // Array class not yet created - exit the intrinsic and call the original method
- *         return java.lang.reflect.newInstance(componentType, length);
- *     }
- *     return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
- * }
- * 
- * - * A condition for a partial intrinsic exit is that it is uses the unmodified parameters of the - * substitute as arguments to the partial intrinsic exit call. There must also be no side effecting - * instruction between the start of the substitute method and the partial intrinsic exit. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface MethodSubstitution { - - /** - * Gets the name of the original method. - *

- * If the default value is specified for this element, then the name of the original method is - * same as the substitute method. - */ - String value() default ""; - - /** - * Determines if the original method is static. - */ - boolean isStatic() default true; - - /** - * Gets the {@linkplain Signature#toMethodDescriptor signature} of the original method. - *

- * If the default value is specified for this element, then the signature of the original method - * is the same as the substitute method. - */ - String signature() default ""; - - /** - * Determines if the substitution is for a method that may not be part of the runtime. For - * example, a method introduced in a later JDK version. Substitutions for such methods are - * omitted if the original method cannot be found. - */ - boolean optional() default false; -} diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index aecf973292e4..09d50ab816a1 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -50,7 +50,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; @@ -424,7 +423,7 @@ public static void runTest(InvariantsTool tool) { if (matches(filters, methodName)) { executor.execute(() -> { try (DebugContext debug = new Builder(options).build()) { - boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null; + boolean isSubstitution = method.getAnnotation(Snippet.class) != null; StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(isSubstitution).build(); try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { checkMethod(method); diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java index 3a95d717546e..08b16eee61ec 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java @@ -29,7 +29,6 @@ import java.lang.invoke.MethodType; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.nodes.IfNode; @@ -37,7 +36,7 @@ import org.junit.Test; /** - * Tests HotSpot specific {@link MethodSubstitution}s. + * Tests HotSpot specific substitutions. */ public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest { diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionEffectTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionEffectTest.java deleted file mode 100644 index 91b53fa27b17..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionEffectTest.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.test; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; - -import java.util.ArrayList; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.java.BytecodeParserOptions; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.replacements.ReplacementsImpl; -import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; -import org.graalvm.compiler.runtime.RuntimeProvider; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodSubstitutionEffectTest extends GraalCompilerTest { - public static int ValueFountain; - - static class Substitutee { - - public static int singleEffect(@SuppressWarnings("unused") int a) { - return 0; - } - - public static int sequentialEffectInvalid(@SuppressWarnings("unused") int a) { - return 0; - } - - public static void sequentialEffectInvalidVoid(@SuppressWarnings("unused") int a) { - } - - public static int splitEffect(@SuppressWarnings("unused") int a) { - return 0; - } - - public static void splitEffectVoid(@SuppressWarnings("unused") int a) { - } - - public static int multiSplitEffectNoMerge(@SuppressWarnings("unused") int a) { - return 0; - } - - public static int multiSplitEffectNoMergeInvalid(@SuppressWarnings("unused") int a) { - return 0; - } - - public static int splitEffectWrong(@SuppressWarnings("unused") int a) { - return 0; - } - - public static int splitParitalIntrinsicExit(@SuppressWarnings("unused") int a) { - return 0; - } - } - - @ClassSubstitution(Substitutee.class) - public static class Substitutor { - - @MethodSubstitution - public static int singleEffect(int a) { - return GraalDirectives.sideEffect(a); - } - - @MethodSubstitution - public static int sequentialEffectInvalid(int a) { - GraalDirectives.sideEffect(a); - return GraalDirectives.sideEffect(a); - } - - @MethodSubstitution - public static void sequentialEffectInvalidVoid(int a) { - GraalDirectives.sideEffect(a); - GraalDirectives.sideEffect(a); - } - - @MethodSubstitution - public static int splitEffect(int a) { - int i; - if (a > 0) { - GraalDirectives.sideEffect(a); - i = a; - } else { - GraalDirectives.sideEffect(42); - i = 42; - } - return i; - } - - @MethodSubstitution - public static void splitEffectVoid(int a) { - if (a > 0) { - GraalDirectives.sideEffect(a); - } else { - GraalDirectives.sideEffect(42); - } - } - - @MethodSubstitution - public static int multiSplitEffectNoMerge(int a) { - switch (a) { - case 1: - GraalDirectives.sideEffect(a); - return 3; - case 2: - GraalDirectives.sideEffect(a); - return 2; - case 3: - GraalDirectives.sideEffect(a); - return 1; - default: - GraalDirectives.sideEffect(a); - return 0; - } - } - - @MethodSubstitution - public static int multiSplitEffectNoMergeInvalid(int a) { - switch (a) { - case 1: - GraalDirectives.sideEffect(a); - return 3; - case 2: - GraalDirectives.sideEffect(a); - return 2; - case 3: - GraalDirectives.sideEffect(a); - return 1; - default: - GraalDirectives.sideEffect(a); - GraalDirectives.sideEffect(a); - return 0; - } - } - - @MethodSubstitution - public static int splitEffectWrong(int a) { - int i; - if (a > 0) { - GraalDirectives.sideEffect(a); - GraalDirectives.sideEffect(a); - i = a; - } else { - i = 42; - GraalDirectives.controlFlowAnchor(); - } - return i; - } - - @MethodSubstitution - public static int splitParitalIntrinsicExit(int a) { - int i; - if (a > 0) { - i = GraalDirectives.sideEffect(a); - } else { - i = splitParitalIntrinsicExit(a); - } - return i; - } - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, Substitutee.class, getReplacements(), bytecodeProvider); - r.registerMethodSubstitution(Substitutor.class, "singleEffect", int.class); - r.registerMethodSubstitution(Substitutor.class, "sequentialEffectInvalid", int.class); - r.registerMethodSubstitution(Substitutor.class, "sequentialEffectInvalidVoid", int.class); - r.registerMethodSubstitution(Substitutor.class, "splitEffect", int.class); - r.registerMethodSubstitution(Substitutor.class, "splitEffectVoid", int.class); - r.registerMethodSubstitution(Substitutor.class, "multiSplitEffectNoMerge", int.class); - r.registerMethodSubstitution(Substitutor.class, "multiSplitEffectNoMergeInvalid", int.class); - r.registerMethodSubstitution(Substitutor.class, "splitEffectWrong", int.class); - r.registerMethodSubstitution(Substitutor.class, "splitParitalIntrinsicExit", int.class); - super.registerInvocationPlugins(invocationPlugins); - } - - private ClassfileBytecodeProvider getSystemClassLoaderBytecodeProvider() { - ReplacementsImpl d = (ReplacementsImpl) getReplacements(); - MetaAccessProvider metaAccess = d.getProviders().getMetaAccess(); - ClassfileBytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader()); - return bytecodeProvider; - } - - static void snippet01() { - Substitutee.singleEffect(42); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet02() { - Substitutee.sequentialEffectInvalid(42); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet03() { - Substitutee.sequentialEffectInvalidVoid(42); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet04() { - Substitutee.splitEffect(ValueFountain); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet05() { - Substitutee.splitEffectVoid(ValueFountain); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet06() { - Substitutee.splitEffectWrong(ValueFountain); - if (ValueFountain == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet07() { - if (Substitutee.splitParitalIntrinsicExit(ValueFountain) == 42) { - GraalDirectives.deoptimize(); - } - } - - static void snippet08() { - Substitutee.multiSplitEffectNoMerge(ValueFountain); - } - - private DebugContext getDebugContext(ResolvedJavaMethod method) { - /* - * We do not want to inline partial intrinsic exits in this test to test the state of the - * self recursive call. - */ - OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false, - BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing, false); - return getDebugContext(options, null, method); - } - - StructuredGraph getGraph(ResolvedJavaMethod method, DebugContext debug) { - StructuredGraph g = parseEager(method, AllowAssumptions.NO, debug); - Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions()); - s.getHighTier().apply(g, getDefaultHighTierContext()); - s.getMidTier().apply(g, getDefaultMidTierContext()); - return g; - } - - StructuredGraph getGraph(String snippet) { - ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - return getGraph(method, getDebugContext(method)); - } - - @Test - public void test1() { - getGraph("snippet01"); - } - - @Test - @SuppressWarnings("try") - public void test2() { - ResolvedJavaMethod method = getResolvedJavaMethod("snippet02"); - try (AutoCloseable c = new TTY.Filter(); - DebugContext debug = getDebugContext(method); - DebugCloseable s = debug.disableIntercept()) { - getGraph(method, debug); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if (t.getCause() instanceof GraalError && t.getMessage().contains("unexpected node between return StateSplit and last instruction")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - @SuppressWarnings("try") - public void test3() { - ResolvedJavaMethod method = getResolvedJavaMethod("snippet03"); - try (AutoCloseable c = new TTY.Filter(); - DebugContext debug = getDebugContext(method); - DebugCloseable s = debug.disableIntercept()) { - getGraph(method, debug); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if (t.getCause() instanceof GraalError && t.getMessage().contains(" produced invalid framestate")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - public void test4() { - getGraph("snippet04"); - } - - @Test - public void test5() { - getGraph("snippet05"); - } - - @Test - @SuppressWarnings("try") - public void test6() { - ResolvedJavaMethod method = getResolvedJavaMethod("snippet06"); - try (AutoCloseable c = new TTY.Filter(); - DebugContext debug = getDebugContext(method); - DebugCloseable s = debug.disableIntercept()) { - getGraph(method, debug); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if (t.getCause() instanceof GraalError && t.getMessage().contains(" produced invalid framestate")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - public void test7() { - getGraph("snippet07"); - } - - @Test - public void test8() { - getGraph("snippet08"); - } - - @Test - @SuppressWarnings("try") - public void testRootCompiles() { - ArrayList intrinisicsWithoutErrors = new ArrayList<>(); - ArrayList intrinisicsErrors = new ArrayList<>(); - - intrinisicsWithoutErrors.add(getResolvedJavaMethod(Substitutee.class, "singleEffect")); - intrinisicsWithoutErrors.add(getResolvedJavaMethod(Substitutee.class, "splitEffect")); - intrinisicsWithoutErrors.add(getResolvedJavaMethod(Substitutee.class, "splitEffectVoid")); - intrinisicsWithoutErrors.add(getResolvedJavaMethod(Substitutee.class, "multiSplitEffectNoMerge")); - intrinisicsWithoutErrors.add(getResolvedJavaMethod(Substitutee.class, "splitParitalIntrinsicExit")); - - intrinisicsErrors.add(getResolvedJavaMethod(Substitutee.class, "sequentialEffectInvalid")); - intrinisicsErrors.add(getResolvedJavaMethod(Substitutee.class, "sequentialEffectInvalidVoid")); - intrinisicsErrors.add(getResolvedJavaMethod(Substitutee.class, "splitEffectWrong")); - intrinisicsErrors.add(getResolvedJavaMethod(Substitutee.class, "multiSplitEffectNoMergeInvalid")); - - for (ResolvedJavaMethod method : intrinisicsWithoutErrors) { - StructuredGraph graph = getProviders().getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, getDebugContext(method), AllowAssumptions.YES, null); - getCode(method, graph); - } - for (ResolvedJavaMethod method : intrinisicsErrors) { - try (AutoCloseable c = new TTY.Filter(); - DebugContext debug = getDebugContext(method); - DebugCloseable s = debug.disableIntercept()) { - StructuredGraph graph = getProviders().getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, debug, AllowAssumptions.YES, null); - getCode(method, graph); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if ((t.getCause() instanceof GraalError || t instanceof GraalError) && t.getMessage().contains("invalid state")) { - continue; - } - throw new AssertionError(t); - } - } - - } -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionForeignCallTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionForeignCallTest.java deleted file mode 100644 index 56e2e2a327cf..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MethodSubstitutionForeignCallTest.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.test; - -import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.replacements.ReplacementsImpl; -import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; -import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.word.LocationIdentity; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodSubstitutionForeignCallTest extends GraalCompilerTest { - public static final ForeignCallDescriptor TEST_CALL_DEOPT = new ForeignCallDescriptor("test", int.class, new Class[]{int.class}, false, new LocationIdentity[0], true, true); - public static final ForeignCallDescriptor TEST_CALL_REEXECUTABLE = new ForeignCallDescriptor("test", int.class, new Class[]{int.class}, true, new LocationIdentity[0], false, false); - public static final ForeignCallDescriptor TEST_CALL_NON_DEOPT = new ForeignCallDescriptor("test", int.class, new Class[]{int.class}, false, new LocationIdentity[0], false, false); - - public static class A { - static void invalidConsecutiveForeignCall1(@SuppressWarnings("unused") int phi) { - - } - - static void invalidConsecutiveForeignCall2(@SuppressWarnings("unused") int phi) { - - } - - static void validConsecutiveForeignCallReexecutable(@SuppressWarnings("unused") int phi) { - - } - - static void splitForeignCallInvalid(@SuppressWarnings("unused") int phi) { - - } - } - - @ClassSubstitution(A.class) - public static class ASubstitutions { - - /* - * Invalid: two consecutive states, deopt could float in between. - */ - @MethodSubstitution - static void invalidConsecutiveForeignCall1(int phi) { - testDeopt(phi); - // invalid two consecutive calls - testDeopt(phi); - } - - /* - * Invalid: two consecutive states, deopt could float in between. Same applies for - * non-deopting framestates if they are not re-executable. If they are, we are good. - */ - @MethodSubstitution - static void invalidConsecutiveForeignCall2(int phi) { - testNonDeopting(phi); - testNonDeopting(phi); - } - - /* - * Valid, the foreign calls are re-executable and non-deopting (thus completely side-effect - * free), they do not need a state. - */ - @MethodSubstitution - static void validConsecutiveForeignCallReexecutable(int phi) { - testPureReexectuable(phi); - testPureReexectuable(phi); - } - - /** - * Invalid: Splitting effect in a method substitution is allowed as long as it is just one - * effect per call. This is not the case here. - */ - @MethodSubstitution - static void splitForeignCallInvalid(int phi) { - if (SideEffect == 0) { - testDeopt(phi); - } else { - CurrentJavaThreadNode.get().writeByte(0, (byte) 0); - testDeopt(phi); - } - } - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - - invocationPlugins.register(MethodSubstitutionForeignCallTest.class, new InvocationPlugin("testDeopt", int.class) { - - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - - ForeignCallNode node = new ForeignCallNode(TEST_CALL_DEOPT, arg); - node.setBci(b.bci()); - b.addPush(JavaKind.Int, node); - return true; - } - }); - invocationPlugins.register(MethodSubstitutionForeignCallTest.class, new InvocationPlugin("testNonDeopting", int.class) { - - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - ForeignCallNode node = new ForeignCallNode(TEST_CALL_NON_DEOPT, arg); - node.setBci(b.bci()); - b.addPush(JavaKind.Int, node); - return true; - } - }); - invocationPlugins.register(MethodSubstitutionForeignCallTest.class, new InvocationPlugin("testPureReexectuable", int.class) { - - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - ForeignCallNode node = new ForeignCallNode(TEST_CALL_REEXECUTABLE, arg); - node.setBci(b.bci()); - b.addPush(JavaKind.Int, node); - return true; - } - }); - ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, A.class, getReplacements(), bytecodeProvider); - r.registerMethodSubstitution(ASubstitutions.class, "invalidConsecutiveForeignCall1", int.class); - r.registerMethodSubstitution(ASubstitutions.class, "invalidConsecutiveForeignCall2", int.class); - r.registerMethodSubstitution(ASubstitutions.class, "validConsecutiveForeignCallReexecutable", int.class); - r.registerMethodSubstitution(ASubstitutions.class, "splitForeignCallInvalid", int.class); - super.registerInvocationPlugins(invocationPlugins); - } - - private ClassfileBytecodeProvider getSystemClassLoaderBytecodeProvider() { - ReplacementsImpl d = (ReplacementsImpl) getReplacements(); - MetaAccessProvider metaAccess = d.getProviders().getMetaAccess(); - ClassfileBytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader()); - return bytecodeProvider; - } - - public static int SideEffect; - - public static int testDeopt(int value) { - SideEffect = value; - return value; - } - - public static int testNonDeopting(int value) { - return value; - } - - public static int testPureReexectuable(int value) { - return value; - } - - public static void testSnippetInvalidSequential() { - A.invalidConsecutiveForeignCall1(SideEffect); - if (SideEffect == 1) { - GraalDirectives.deoptimize(); - } - } - - public static void testNonDeoptingInvalid() { - A.invalidConsecutiveForeignCall2(SideEffect); - if (SideEffect == 1) { - GraalDirectives.deoptimize(); - } - } - - public static void testNonDeoptingSplit() { - A.splitForeignCallInvalid(SideEffect); - if (SideEffect == 1) { - GraalDirectives.deoptimize(); - } - } - - public static void testNonDeoptingReexectuable() { - A.validConsecutiveForeignCallReexecutable(SideEffect); - if (SideEffect == 1) { - GraalDirectives.deoptimize(); - } - } - - @Test - @SuppressWarnings("try") - public void test1() { - try (AutoCloseable c = new TTY.Filter()) { - OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false); - StructuredGraph g = parseEager(getResolvedJavaMethod("testSnippetInvalidSequential"), AllowAssumptions.NO, options); - Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions()); - s.getHighTier().apply(g, getDefaultHighTierContext()); - s.getMidTier().apply(g, getDefaultMidTierContext()); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if ((t.getCause() instanceof GraalError || t instanceof GraalError) && t.getMessage().contains("invalid framestate")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - @SuppressWarnings("try") - public void test2() { - try (AutoCloseable c = new TTY.Filter()) { - OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false); - StructuredGraph g = parseEager(getResolvedJavaMethod("testSnippetInvalidSequential"), AllowAssumptions.NO, options); - Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions()); - s.getHighTier().apply(g, getDefaultHighTierContext()); - s.getMidTier().apply(g, getDefaultMidTierContext()); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if ((t.getCause() instanceof GraalError || t instanceof GraalError) && t.getMessage().contains("invalid framestate")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - @SuppressWarnings("try") - public void test3() { - try (AutoCloseable c = new TTY.Filter()) { - OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false); - StructuredGraph g = parseEager(getResolvedJavaMethod("testNonDeoptingSplit"), AllowAssumptions.NO, options); - Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions()); - s.getHighTier().apply(g, getDefaultHighTierContext()); - s.getMidTier().apply(g, getDefaultMidTierContext()); - Assert.fail("Compilation should not reach this point, must throw an exception before"); - } catch (Throwable t) { - if ((t.getCause() instanceof GraalError || t instanceof GraalError) && t.getMessage().contains("invalid framestate")) { - return; - } - throw new AssertionError(t); - } - } - - @Test - public void test4() { - StructuredGraph g = parseEager(getResolvedJavaMethod("testNonDeoptingReexectuable"), AllowAssumptions.NO); - Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions()); - s.getHighTier().apply(g, getDefaultHighTierContext()); - s.getMidTier().apply(g, getDefaultMidTierContext()); - } - -} diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java index faba608b9cf9..06823b5ed537 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java @@ -39,7 +39,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import org.junit.Test; @@ -68,13 +67,11 @@ public void test() throws ClassNotFoundException { DebugContext debug = getDebugContext(options); for (VMIntrinsicMethod intrinsic : intrinsics) { InvocationPlugin plugin = CheckGraalIntrinsics.findPlugin(invocationPluginsMap, intrinsic); - if (plugin != null) { - if (plugin instanceof MethodSubstitutionPlugin) { - ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic); - if (!method.isNative()) { - StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, debug, AllowAssumptions.YES, null); - getCode(method, graph); - } + if (plugin != null && !plugin.inlineOnly()) { + ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic); + if (!method.isNative()) { + StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, debug, AllowAssumptions.YES, null); + getCode(method, graph); } } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java index ece27e9ce093..3dca6ebb3842 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java @@ -46,14 +46,12 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.nodes.Cancellable; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.EncodedGraph; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; @@ -185,37 +183,6 @@ public void visitImmutable(Consumer visitor) { visitor.accept(graphDatas); } - @SuppressWarnings("try") - StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, HotSpotReplacementsImpl replacements, IntrinsicContext.CompilationContext context, - StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { - IntrinsicContext.CompilationContext contextToUse = context; - if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) { - contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; - } - GraphData data = graphDatas.get(plugin.toString() + contextToUse); - if (data == null) { - throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + contextToUse); - } - - ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass()); - Providers providers = replacements.getProviders(); - EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, data.getStartOffset(null), snippetObjects, snippetNodeClasses, - methodKey(original), accessingClass, original.getDeclaringClass()); - - try (DebugContext debug = replacements.openDebugContext("LibGraal", original, options)) { - StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(original).setIsSubstitution(true).build(); - try (DebugContext.Scope scope = debug.scope("LibGraal.DecodeMethodSubstitution", result)) { - PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, original, contextToUse, encodedGraph, true); - graphDecoder.decode(original, result.isSubstitution(), encodedGraph.trackNodeSourcePosition()); - postDecode(debug, result, original); - assert result.verify(); - return result; - } catch (Throwable t) { - throw debug.handle(t); - } - } - } - /** * Generate a String name for a method including all type information. Used as a symbolic key * for lookup. @@ -366,7 +333,7 @@ private static void postDecode(DebugContext debug, StructuredGraph result, Resol static class SubstitutionGraphDecoder extends PEGraphDecoder { private final ResolvedJavaMethod method; private final EncodedGraph encodedGraph; - private IntrinsicContext intrinsic; + private final IntrinsicContext intrinsic; private final boolean mustSucceed; SubstitutionGraphDecoder(Providers providers, StructuredGraph result, HotSpotReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, @@ -377,12 +344,11 @@ static class SubstitutionGraphDecoder extends PEGraphDecoder { this.method = method; this.encodedGraph = encodedGraph; this.mustSucceed = mustSucceed; - intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false); + this.intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false); } @Override protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, - MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index 7f65c812b928..6ff30bb06ded 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -27,30 +27,23 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import java.util.BitSet; import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin; import org.graalvm.compiler.hotspot.word.HotSpotOperation; -import org.graalvm.compiler.nodes.Cancellable; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; @@ -103,15 +96,6 @@ public Class getIntrinsifyingPlugin(ResolvedJavaMe return super.getIntrinsifyingPlugin(method); } - @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { - if (!IS_IN_NATIVE_IMAGE) { - if (snippetEncoder != null) { - snippetEncoder.registerMethodSubstitution(plugin); - } - } - } - @Override public void registerConditionalPlugin(InvocationPlugin plugin) { if (!IS_IN_NATIVE_IMAGE) { @@ -121,55 +105,6 @@ public void registerConditionalPlugin(InvocationPlugin plugin) { } } - public void checkRegistered(MethodSubstitutionPlugin plugin) { - snippetEncoder.checkRegistered(plugin); - } - - @Override - public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, AllowAssumptions allowAssumptions, Cancellable cancellable) { - boolean useEncodedGraphs = UseEncodedGraphs.getValue(debug.getOptions()); - if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); - InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method, debug.getOptions()); - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin; - if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) { - replacements.maybeInitializeEncoder(debug.getOptions()); - replacements.registerMethodSubstitution(msp); - } - StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, allowAssumptions, cancellable, debug.getOptions()); - methodSubstitution.resetDebug(debug); - return methodSubstitution; - } - } - return super.getIntrinsicGraph(method, compilationId, debug, allowAssumptions, cancellable); - } - - @Override - public StructuredGraph getInlineSubstitution(ResolvedJavaMethod targetMethod, int invokeBci, Invoke.InlineControl inlineControl, boolean trackNodeSourcePosition, - NodeSourcePosition replaceePosition, AllowAssumptions allowAssumptions, OptionValues options) { - if (!inlineControl.allowSubstitution()) { - return null; - } - boolean useEncodedGraphs = UseEncodedGraphs.getValue(options); - if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) { - InvocationPlugin plugin = getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(targetMethod, options); - if (plugin instanceof MethodSubstitutionPlugin && (!plugin.inlineOnly() || invokeBci >= 0)) { - MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; - if (!IS_IN_NATIVE_IMAGE && useEncodedGraphs) { - maybeInitializeEncoder(options); - registerMethodSubstitution(msPlugin); - } - // This assumes the normal path creates the graph using - // GraphBuilderConfiguration.getSnippetDefault with omits exception edges - StructuredGraph subst = getMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, allowAssumptions, null, options); - return subst; - } - } - - return super.getInlineSubstitution(targetMethod, invokeBci, inlineControl, trackNodeSourcePosition, replaceePosition, allowAssumptions, options); - } - @Override public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { if (!IS_IN_NATIVE_IMAGE) { @@ -279,16 +214,6 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); } - @Override - public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, - StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { - if (IS_IN_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { - maybeEncodeSnippets(options); - return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, cancellable, options); - } - return null; - } - @SuppressWarnings("unchecked") @Override public T getInjectedArgument(Class capability) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 0b513ea59810..18178ad11af5 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.hotspot.EncodedSnippets.methodKey; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Executable; import java.lang.reflect.Field; @@ -92,7 +91,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -215,63 +213,10 @@ public String toString() { } } - static class MethodSubstitutionKey extends GraphKey { - final IntrinsicContext.CompilationContext context; - final MethodSubstitutionPlugin plugin; - - MethodSubstitutionKey(ResolvedJavaMethod method, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, MethodSubstitutionPlugin plugin) { - super(method, original); - this.context = context; - this.plugin = plugin; - assert method.isStatic() : "must be non-virtual"; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MethodSubstitutionKey that = (MethodSubstitutionKey) o; - return Objects.equals(original, that.original) && - context == that.context && - Objects.equals(plugin, that.plugin); - } - - @Override - public int hashCode() { - return Objects.hash(original, context, plugin); - } - - @Override - public String keyString() { - return plugin.toString() + context; - } - - @Override - public Class receiverClass() { - return null; - } - - @Override - public String toString() { - return "MethodSubstitutionKey{" + - "method=" + method + - ", original=" + original + - ", context=" + context + - ", plugin=" + plugin + - '}'; - } - } - private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); private final EconomicMap snippetParameterInfos = EconomicMap.create(); - private final EconomicSet knownPlugins = EconomicSet.create(); - private final EconomicSet conditionalPlugins = EconomicSet.create(); /** @@ -344,22 +289,12 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved this.originalReplacements = replacements; } - synchronized void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { - knownPlugins.add(plugin); - } - synchronized void registerConditionalPlugin(InvocationPlugin plugin) { conditionalPlugins.add(plugin); } - synchronized void checkRegistered(MethodSubstitutionPlugin plugin) { - if (!knownPlugins.contains(plugin)) { - throw new GraalError("missing plugin should have been registered during construction " + plugin + " " + knownPlugins); - } - } - - private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, BitSet nonNullParameters, boolean requireInlining, - boolean trackNodeSourcePosition, IntrinsicContext.CompilationContext context, OptionValues options, ReplacementsImpl snippetReplacements) { + private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, BitSet nonNullParameters, + boolean trackNodeSourcePosition, OptionValues options, ReplacementsImpl snippetReplacements) { assert method.hasBytecodes() : "Snippet must not be abstract or native"; Object[] args = null; if (receiver != null) { @@ -372,10 +307,7 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod // // -J-Dgraal.Dump=SymbolicSnippetEncoder_:2 -J-Dgraal.PrintGraph=File // -J-Dgraal.DebugStubsAndSnippets=true - IntrinsicContext.CompilationContext contextToUse = context; - if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) { - contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; - } + IntrinsicContext.CompilationContext contextToUse = IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; try (DebugContext debug = snippetReplacements.openDebugContext("LibGraalBuildGraph_", method, options)) { StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, nonNullParameters, original, trackNodeSourcePosition, null, contextToUse); @@ -383,11 +315,11 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod // Check if all methods which should be inlined are really inlined. for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { ResolvedJavaMethod callee = callTarget.targetMethod(); - if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original) && !Objects.equals(callee, method)) { + if (!delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original) && !Objects.equals(callee, method)) { throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); } } - assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, args, trackNodeSourcePosition, graph); + assert verifySnippetEncodeDecode(debug, method, original, args, trackNodeSourcePosition, graph); debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); assert graph.getAssumptions() == null : graph; return graph; @@ -420,7 +352,7 @@ private static void checkIllegalSnippetObjects(Object o) { } @SuppressWarnings("try") - private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object[] args, boolean trackNodeSourcePosition, + private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, boolean trackNodeSourcePosition, StructuredGraph graph) { // Verify the encoding and decoding process GraphEncoder encoder = new CheckingGraphEncoder(HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); @@ -448,7 +380,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod } StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, args, null, original, trackNodeSourcePosition, null); - SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), originalMethodString); + SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), null); StructuredGraph decodedSnippet = EncodedSnippets.decodeSnippetGraph(symbolicGraph, original != null ? original : method, original, originalReplacements, null, StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions(), false); String snippetString = getCanonicalGraphString(snippet, true, false); @@ -541,9 +473,8 @@ synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod pendingSnippetGraphs.put(key, new BiFunction<>() { @Override public StructuredGraph apply(OptionValues cmopileOptions, HotSpotSnippetReplacementsImpl snippetReplacements) { - StructuredGraph snippet = buildGraph(method, original, null, receiver, SnippetParameterInfo.getNonNullParameters(info), true, trackNodeSourcePosition, INLINE_AFTER_PARSING, + return buildGraph(method, original, receiver, SnippetParameterInfo.getNonNullParameters(info), trackNodeSourcePosition, cmopileOptions, snippetReplacements); - return snippet; } }); } @@ -1167,7 +1098,7 @@ private static synchronized SnippetResolvedJavaType createType(Class clazz) { return type; } - private class MetaAccessProviderDelegate implements MetaAccessProvider { + private static class MetaAccessProviderDelegate implements MetaAccessProvider { MetaAccessProvider delegate; MetaAccessProviderDelegate(MetaAccessProvider metaAccess) { diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index b96866c768e0..d7bf1a3faafd 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -271,7 +271,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; -import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; @@ -392,7 +391,6 @@ import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; -import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; @@ -2380,139 +2378,6 @@ private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targe return false; } - /** - * Inline a method substitution graph. This is necessary for libgraal as substitutions only - * exist as encoded graphs and can't be parsed directly into the caller. - */ - @Override - @SuppressWarnings("try") - public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] args) { - if (receiver != null) { - receiver.get(); - } - - WithExceptionNode withException = null; - boolean insertExceptionEdge = false; - FixedWithNextNode replacee = lastInstr; - try (DebugContext.Scope a = debug.scope("instantiate", substituteGraph)) { - // Inline the snippet nodes, replacing parameters with the given args in the process - StartNode entryPointNode = substituteGraph.start(); - FixedNode firstCFGNode = entryPointNode.next(); - StructuredGraph replaceeGraph = replacee.graph(); - Mark mark = replaceeGraph.getMark(); - try (InliningScope inlineScope = new IntrinsicScope(this, targetMethod, args)) { - - EconomicMap replacementsMap = EconomicMap.create(Equivalence.IDENTITY); - for (ParameterNode param : substituteGraph.getNodes(ParameterNode.TYPE)) { - replacementsMap.put(param, args[param.index()]); - } - replacementsMap.put(entryPointNode, AbstractBeginNode.prevBegin(replacee)); - - debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "Before inlining method substitution %s", substituteGraph.method()); - UnmodifiableEconomicMap duplicates = inlineMethodSubstitution(replaceeGraph, substituteGraph, replacementsMap); - - FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); - replacee.setNext(firstCFGNodeDuplicate); - debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining method substitution %s", substituteGraph.method()); - - // Handle partial intrinsic exits - for (Node node : graph.getNewNodes(mark)) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - if (invoke.bci() == BytecodeFrame.UNKNOWN_BCI) { - invoke.setBci(bci()); - } - } else if (node instanceof ForeignCall) { - ForeignCall call = (ForeignCall) node; - if (call.bci() == BytecodeFrame.UNKNOWN_BCI) { - call.setBci(bci()); - if (call.stateAfter() != null && call.stateAfter().bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { - call.setStateAfter(inlineScope.stateBefore); - } - } - } - - if (node instanceof WithExceptionNode) { - /** - * The graphs for MethodSubstitutions are produced assuming that exceptions - * must be dispatched. If the calling context doesn't want exception then - * convert back into a non throwing node - */ - assert withException == null : "at most one exception edge expected"; - withException = (WithExceptionNode) node; - BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); - if (intrinsicCallSiteParser != null && intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null) == ExceptionEdgeAction.OMIT) { - // Exception edge should be removed - withException.replaceWithNonThrowing(); - } else { - // Disconnnect exception edge - insertExceptionEdge = true; - withException.killExceptionEdge(); - } - } - } - - ArrayList calleeReturnDataList = new ArrayList<>(); - for (ReturnNode n : substituteGraph.getNodes(ReturnNode.TYPE)) { - ReturnNode returnNode = (ReturnNode) duplicates.get(n); - FixedWithNextNode predecessor = (FixedWithNextNode) returnNode.predecessor(); - calleeReturnDataList.add(new ReturnToCallerData(returnNode.result(), predecessor)); - predecessor.setNext(null); - returnNode.safeDelete(); - } - - // Merge multiple returns - processCalleeReturn(targetMethod, inlineScope, calleeReturnDataList); - - // Exiting this scope causes processing of the placeholder frame states. - } - - if (insertExceptionEdge) { - // Connect exception edge into main graph - AbstractBeginNode exceptionEdge = handleException(null, bci(), false); - withException.setExceptionEdge(exceptionEdge); - } - - debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); - return true; - } catch (Throwable t) { - throw debug.handle(t); - } - } - - private static UnmodifiableEconomicMap inlineMethodSubstitution(StructuredGraph replaceeGraph, StructuredGraph snippet, - EconomicMap replacementsMap) { - try (InliningLog.UpdateScope scope = replaceeGraph.getInliningLog().openUpdateScope((oldNode, newNode) -> { - InliningLog log = replaceeGraph.getInliningLog(); - if (oldNode == null) { - log.trackNewCallsite(newNode); - } - })) { - StartNode entryPointNode = snippet.start(); - ArrayList nodes = new ArrayList<>(snippet.getNodeCount()); - for (Node node : snippet.getNodes()) { - if (node != entryPointNode && node != entryPointNode.stateAfter()) { - nodes.add(node); - } - } - UnmodifiableEconomicMap duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacementsMap); - if (scope != null) { - replaceeGraph.getInliningLog().addLog(duplicates, snippet.getInliningLog()); - } - return duplicates; - } - } - - @Override - public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { - if (receiver != null) { - receiver.get(); - } - boolean res = inline(targetMethod, substitute, intrinsicBytecodeProvider, args); - assert res : "failed to inline " + substitute; - return res; - } - private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) { try (InliningLog.RootScope scope = graph.getInliningLog().openRootScope(method, targetMethod, bci())) { IntrinsicContext intrinsic = this.intrinsicContext; diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java index 33bea9b3f198..573d919f76ba 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java @@ -25,8 +25,8 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; /** * Options related to {@link BytecodeParser}. @@ -52,9 +52,6 @@ public class BytecodeParserOptions { "the intrinsic does not support.", type = OptionType.Expert) public static final OptionKey InlinePartialIntrinsicExitDuringParsing = new OptionKey<>(true); - @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) - public static final OptionKey InlineIntrinsicsDuringParsing = new OptionKey<>(true); - @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) public static final OptionKey TraceInlineDuringParsing = new OptionKey<>(false); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 035810f0f538..d81300092799 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -41,7 +41,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.collections.UnmodifiableEconomicMap; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.common.CancellationBailoutException; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -507,10 +506,9 @@ private StructuredGraph(String name, private static boolean checkIsSubstitutionInvariants(ResolvedJavaMethod method, boolean isSubstitution) { if (!IS_IN_NATIVE_IMAGE) { if (method != null) { - if (method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null) { + if (method.getAnnotation(Snippet.class) != null) { assert isSubstitution : "Graph for method " + method.format("%H.%n(%p)") + - " annotated by " + Snippet.class.getName() + " or " + - MethodSubstitution.class.getName() + + " annotated by " + Snippet.class.getName() + " must have its `isSubstitution` field set to true"; } } @@ -1040,8 +1038,8 @@ public boolean useProfilingInfo() { /** * Returns true if this graph is built without parsing the {@linkplain #method() root method} or - * if the root method is annotated by {@link Snippet} or {@link MethodSubstitution}. This is - * preferred over querying annotations directly as querying annotations can cause class loading. + * if the root method is annotated by {@link Snippet}. This is preferred over querying + * annotations directly as querying annotations can cause class loading. */ public boolean isSubstitution() { return isSubstitution; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java index c0c5ca233aab..b634313a62f0 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java @@ -29,7 +29,6 @@ import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull; import org.graalvm.compiler.bytecode.Bytecode; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -57,7 +56,6 @@ import org.graalvm.compiler.nodes.PluginReplacementWithExceptionNode; import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; @@ -165,33 +163,6 @@ default T addPush(JavaKind kind, T value) { void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType); - /** - * Intrinsifies an invocation of a given method by inlining the bytecodes of a given - * substitution method. - * - * @param bytecodeProvider used to get the bytecodes to parse for the substitution method - * @param targetMethod the method being intrinsified - * @param substitute the intrinsic implementation - * @param receiver the receiver, or null for static methods - * @param argsIncludingReceiver the arguments with which to inline the invocation - * - * @return whether the intrinsification was successful - */ - boolean intrinsify(BytecodeProvider bytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver); - - /** - * Intrinsifies an invocation of a given method by inlining the graph of a given substitution - * method. - * - * @param targetMethod the method being intrinsified - * @param substituteGraph the intrinsic implementation - * @param receiver the receiver, or null for static methods - * @param argsIncludingReceiver the arguments with which to inline the invocation - * - * @return whether the intrinsification was successful - */ - boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver); - /** * Creates a snap shot of the current frame state with the BCI of the instruction after the one * currently being parsed and assigns it to a given {@linkplain StateSplit#hasSideEffect() side diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java index 9caf93295dcc..12e126543414 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java @@ -62,28 +62,22 @@ final class InlineInfo { public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo(); private final ResolvedJavaMethod methodToInline; - private final MethodSubstitutionPlugin plugin; private final BytecodeProvider intrinsicBytecodeProvider; public static InlineInfo createStandardInlineInfo(ResolvedJavaMethod methodToInline) { - return new InlineInfo(methodToInline, null, null); + return new InlineInfo(methodToInline, null); } public static InlineInfo createIntrinsicInlineInfo(ResolvedJavaMethod methodToInline, BytecodeProvider intrinsicBytecodeProvider) { - return new InlineInfo(methodToInline, null, intrinsicBytecodeProvider); - } - - public static InlineInfo createMethodSubstitutionInlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin) { - return new InlineInfo(methodToInline, plugin, plugin.getBytecodeProvider()); + return new InlineInfo(methodToInline, intrinsicBytecodeProvider); } private InlineInfo() { - this(null, null, null); + this(null, null); } - private InlineInfo(ResolvedJavaMethod methodToInline, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider) { + private InlineInfo(ResolvedJavaMethod methodToInline, BytecodeProvider intrinsicBytecodeProvider) { this.methodToInline = methodToInline; - this.plugin = plugin; this.intrinsicBytecodeProvider = intrinsicBytecodeProvider; } @@ -109,14 +103,6 @@ public boolean allowsInlining() { public BytecodeProvider getIntrinsicBytecodeProvider() { return intrinsicBytecodeProvider; } - - public boolean isSubstitution() { - return plugin != null; - } - - public MethodSubstitutionPlugin getPlugin() { - return plugin; - } } /** diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java index b086b1a7f15a..163d873b587b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java @@ -28,12 +28,10 @@ import static jdk.vm.ci.code.BytecodeFrame.AFTER_EXCEPTION_BCI; import static jdk.vm.ci.code.BytecodeFrame.BEFORE_BCI; import static jdk.vm.ci.code.BytecodeFrame.INVALID_FRAMESTATE_BCI; -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -89,7 +87,6 @@ public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, this.compilationContext = compilationContext; this.allowPartialIntrinsicArgumentMismatch = allowPartialIntrinsicArgumentMismatch; assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)"); - assert IS_IN_NATIVE_IMAGE || !method.equals(intrinsic) || method.getAnnotation(MethodSubstitution.class) == null : "method and intrinsic must be different: " + method + " " + intrinsic; } /** diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java index e0a8e3d2a80a..46a053e53965 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java @@ -46,8 +46,6 @@ import org.graalvm.collections.Pair; import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.collections.UnmodifiableMapCursor; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.GraalError; @@ -197,7 +195,6 @@ public static class Registration { private final Type declaringType; private final Replacements replacements; - private final BytecodeProvider bytecodeProvider; private boolean allowOverwrite; public Class getReceiverType() { @@ -220,7 +217,6 @@ public Registration(InvocationPlugins plugins, Type declaringType) { this.plugins = plugins; this.declaringType = declaringType; this.replacements = null; - this.bytecodeProvider = null; } /** @@ -236,23 +232,6 @@ public Registration(InvocationPlugins plugins, Type declaringType, Replacements this.plugins = plugins; this.declaringType = declaringType; 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; } /** @@ -267,7 +246,6 @@ public Registration(InvocationPlugins plugins, String declaringClassName) { this.plugins = plugins; this.declaringType = new OptionalLazySymbol(declaringClassName); this.replacements = null; - this.bytecodeProvider = null; } /** @@ -283,7 +261,6 @@ public Registration(InvocationPlugins plugins, String declaringClassName, Replac this.plugins = plugins; this.declaringType = new OptionalLazySymbol(declaringClassName); this.replacements = replacements; - this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null; } /** @@ -314,65 +291,6 @@ public void registerConditional(boolean isEnabled, InvocationPlugin plugin) { plugins.register(declaringType, plugin, allowOverwrite); } } - - /** - * 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 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 registerMethodSubstitution(Class substituteDeclaringClass, String name, Type... argumentTypes) { - registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); - } - - /** - * 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 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 registerMethodSubstitution(Class substituteDeclaringClass, String name, String substituteName, Type... 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 conditionally 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(declaringType, plugin, allowOverwrite); - } - } } /** @@ -1111,12 +1029,6 @@ public static boolean check(InvocationPlugins plugins, Type declaringType, Invoc if (plugin instanceof ForeignCallPlugin || plugin instanceof GeneratedInvocationPlugin) { return true; } - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; - Method substitute = msplugin.getJavaSubstitute(); - assert substitute.getAnnotation(MethodSubstitution.class) != null : format("Substitute method must be annotated with @%s: %s", MethodSubstitution.class.getSimpleName(), substitute); - return true; - } int arguments = plugin.getArgumentsSize(); assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, plugin.getMethodNameWithArgumentsDescriptor()); @@ -1153,7 +1065,7 @@ static boolean checkResolvable(Type declaringType, InvocationPlugin plugin) { } } else { if (resolveMethod(declaringClass, plugin) == null && !plugin.isOptional()) { - throw new NoSuchMethodError(String.format("%s.%s%s", declaringClass.getName(), plugin.getMethodNameWithArgumentsDescriptor())); + throw new NoSuchMethodError(String.format("%s.%s", declaringClass.getName(), plugin.getMethodNameWithArgumentsDescriptor())); } } return true; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java deleted file mode 100644 index f652cb49fa69..000000000000 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.nodes.graphbuilderconf; - -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.resolveType; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Objects; -import java.util.stream.Collectors; - -import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a - * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be - * static even if the substituted method is not. - * - * While performing intrinsification with method substitutions is simpler than writing an - * {@link InvocationPlugin} that does manual graph weaving, it has a higher compile time cost than - * the latter; parsing bytecodes to create nodes is slower than simply creating nodes. As such, the - * recommended practice is to use {@link MethodSubstitutionPlugin} only for complex - * intrinsifications which is typically those using non-straight-line control flow. - */ -public final class MethodSubstitutionPlugin extends InvocationPlugin { - - private InvocationPlugins.Registration registration; - - private ResolvedJavaMethod cachedSubstitute; - - /** - * The class in which the substitute method is declared. - */ - private final Class declaringClass; - - /** - * The name of the substitute method. - */ - private final String substituteName; - - private final BytecodeProvider bytecodeProvider; - - /** - * Creates a method substitution plugin. - * - * @param bytecodeProvider used to get the bytecodes to parse for the substitute method - * @param originalName the name of the original method - * @param declaringClass the class in which the substitute method is declared - * @param substituteName the name of the substitute method - * @param parameters the parameter types of the substitute method. If the original method is not - * static, then {@code parameters[0]} must be the {@link Class} value denoting - * {@link InvocationPlugin.Receiver} - */ - public MethodSubstitutionPlugin(InvocationPlugins.Registration registration, BytecodeProvider bytecodeProvider, String originalName, Class declaringClass, String substituteName, - Type... parameters) { - super(originalName, parameters); - assert bytecodeProvider != null : "Requires a non-null methodSubstitutionBytecodeProvider"; - this.registration = registration; - this.bytecodeProvider = bytecodeProvider; - this.declaringClass = declaringClass; - this.substituteName = substituteName; - } - - /** - * Gets the substitute method, resolving it first if necessary. - */ - public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) { - if (cachedSubstitute == null) { - cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute()); - } - return cachedSubstitute; - } - - private String originalName() { - return name; - } - - private boolean originalIsStatic() { - return isStatic; - } - - /** - * Gets the object used to access the bytecodes of the substitute method. - */ - public BytecodeProvider getBytecodeProvider() { - return bytecodeProvider; - } - - /** - * Gets the class in which the substitute method is declared. - */ - public Class getDeclaringClass() { - return declaringClass; - } - - /** - * Gets the reflection API version of the substitution method. - */ - public Method getJavaSubstitute() throws GraalError { - Method substituteMethod = lookupSubstitute(); - int modifiers = substituteMethod.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new GraalError("Substitution method must not be abstract or native: " + substituteMethod); - } - if (!Modifier.isStatic(modifiers)) { - throw new GraalError("Substitution method must be static: " + substituteMethod); - } - return substituteMethod; - } - - /** - * Determines if a given method is the substitute method of this plugin. - */ - private boolean isSubstitute(Method m) { - if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(substituteName)) { - if (argumentTypes.length == m.getParameterCount()) { - Class[] mparams = m.getParameterTypes(); - int start = 0; - if (!originalIsStatic()) { - start = 1; - if (!mparams[0].isAssignableFrom(resolveType(argumentTypes[0], false))) { - return false; - } - } - for (int i = start; i < mparams.length; i++) { - if (mparams[i] != resolveType(argumentTypes[i], false)) { - return false; - } - } - return true; - } - } - return false; - } - - private Method lookupSubstitute(Method excluding) { - for (Method m : declaringClass.getDeclaredMethods()) { - if (!m.equals(excluding) && isSubstitute(m)) { - return m; - } - } - return null; - } - - /** - * Gets the substitute method of this plugin. - */ - private Method lookupSubstitute() { - Method m = lookupSubstitute(null); - if (m != null) { - assert lookupSubstitute(m) == null : String.format("multiple matches found for %s:%n%s%n%s", this, m, lookupSubstitute(m)); - return m; - } - throw new GraalError("No method found specified by %s", this); - } - - @Override - public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { - if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) { - StructuredGraph subst = b.getReplacements().getMethodSubstitution(this, - targetMethod, - INLINE_AFTER_PARSING, - StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()), - null /* cancellable */, - b.getOptions()); - if (subst == null) { - throw new GraalError("No graphs found for substitution %s", this); - } - return b.intrinsify(targetMethod, subst, receiver, argsIncludingReceiver); - } - ResolvedJavaMethod substitute = getSubstitute(b.getMetaAccess()); - return b.intrinsify(bytecodeProvider, targetMethod, substitute, receiver, argsIncludingReceiver); - } - - @Override - public String getSourceLocation() { - Class c = getClass(); - for (Method m : c.getDeclaredMethods()) { - if (m.getName().equals("execute")) { - return String.format("%s.%s()", m.getClass().getName(), m.getName()); - } - } - throw new GraalError("could not find method named \"execute\" in " + c.getName()); - } - - @Override - public String toString() { - return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), substituteName, - Arrays.asList(argumentTypes).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", "))); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MethodSubstitutionPlugin that = (MethodSubstitutionPlugin) o; - return originalIsStatic() == that.originalIsStatic() && - Objects.equals(declaringClass, that.declaringClass) && - Objects.equals(substituteName, that.substituteName) && - Objects.equals(originalName(), that.originalName()) && - Arrays.equals(argumentTypes, that.argumentTypes); - } - - @Override - public int hashCode() { - int result = Objects.hash(declaringClass, substituteName, originalName(), originalIsStatic()); - return result; - } - - public String originalMethodAsString() { - return String.format("%s.%s(%s)", declaringClass.getName(), substituteName, Arrays.asList(argumentTypes).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", "))); - } - - public ResolvedJavaMethod getOriginalMethod(MetaAccessProvider metaAccess) { - Class clazz = resolveType(registration.getDeclaringType(), false); - if (clazz == null) { - throw new GraalError("Can't find original class for " + this + " with class " + registration.getDeclaringType()); - } - ResolvedJavaType type = metaAccess.lookupJavaType(clazz); - for (ResolvedJavaMethod declared : type.getDeclaredMethods()) { - if (declared.getName().equals(originalName()) && declared.isStatic() == originalIsStatic() && - declared.getSignature().toMethodDescriptor().startsWith(argumentsDescriptor)) { - return declared; - } - } - throw new GraalError("Can't find original method for " + this + " with class " + registration.getDeclaringType()); - } -} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java index b70a931b3372..3aa77befcfe0 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java @@ -38,9 +38,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.JavaKind; @@ -112,17 +110,6 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); } - @Override - public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, - AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { - return delegate.getMethodSubstitution(plugin, original, context, allowAssumptions, cancellable, options); - } - - @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { - delegate.registerMethodSubstitution(plugin); - } - @Override public void registerConditionalPlugin(InvocationPlugin plugin) { delegate.registerConditionalPlugin(plugin); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java index d9b4b84ea0df..bfab9f0b1693 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java @@ -24,7 +24,8 @@ */ package org.graalvm.compiler.nodes.spi; -import org.graalvm.compiler.api.replacements.MethodSubstitution; +import java.util.BitSet; + import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetTemplateCache; import org.graalvm.compiler.bytecode.BytecodeProvider; @@ -38,16 +39,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; -import java.util.BitSet; - /** * Interface for managing replacements. */ @@ -75,9 +72,7 @@ public interface Replacements extends GeneratedPluginInjectionProvider { /** * Gets the snippet graph derived from a given method. * - * @param recursiveEntry if the snippet contains a call to this method, it's considered as - * recursive call and won't be processed for {@linkplain MethodSubstitution - * substitutions}. + * @param recursiveEntry XXX always null now?. * @param args arguments to the snippet if available, otherwise {@code null} * @param nonNullParameters * @param trackNodeSourcePosition @@ -110,27 +105,6 @@ default boolean isEncodingSnippets() { */ void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options); - /** - * Gets a graph that is a substitution for a given {@link MethodSubstitutionPlugin plugin} in - * the {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext - * context}. - * - * @param plugin the plugin being substituted - * @param original the method being substituted - * @param context the kind of inlining to be performed for the substitution - * @param allowAssumptions - * @param cancellable - * @param options - * @return the method substitution graph, if any, that is derived from {@code method} - */ - StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, - AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options); - - /** - * Registers a plugin as a substitution. - */ - void registerMethodSubstitution(MethodSubstitutionPlugin plugin); - /** * Marks a plugin as conditionally applied. In the contenxt of libgraal conditional plugins * can't be used in during graph encoding for snippets and method substitutions and this is used diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java index 30d702cc5b03..3a7f6c5f399e 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import java.util.ArrayDeque; @@ -40,7 +39,6 @@ import org.graalvm.collections.Equivalence; import org.graalvm.collections.UnmodifiableEconomicMap; import org.graalvm.collections.UnmodifiableMapCursor; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; @@ -878,16 +876,9 @@ static boolean checkInlineeFrameState(Invoke invoke, ResolvedJavaMethod inlinedM // Normal inlining expects all outermost inlinee frame states to // denote the inlinee method } else if (method.equals(invoke.callTarget().targetMethod())) { - // This occurs when an intrinsic calls back to the original - // method to handle a slow path. During parsing of such a - // partial intrinsic, these calls are given frame states - // that exclude the outer frame state denoting a position - // in the intrinsic code. - assert IS_IN_NATIVE_IMAGE || inlinedMethod.getAnnotation( - MethodSubstitution.class) != null : "expected an intrinsic when inlinee frame state matches method of call target but does not match the method of the inlinee graph: " + - frameState; + GraalError.shouldNotReachHere("method subsitutions are gone"); } else if (method.getName().equals(inlinedMethod.getName())) { - // This can happen for method substitutions. + GraalError.shouldNotReachHere("method subsitutions are gone"); } else { throw new AssertionError(String.format("inlinedMethod=%s frameState.method=%s frameState=%s invoke.method=%s", inlinedMethod, method, frameState, invoke.callTarget().targetMethod())); diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java deleted file mode 100644 index d7768742a265..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ClassSubstitutionHandler.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.processor; - -import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; -import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValueList; - -import java.util.List; - -import javax.annotation.processing.Messager; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.processor.AbstractProcessor; - -/** - * Handler for the {@value #CLASS_SUBSTITUTION_CLASS_NAME} annotation. - */ -public final class ClassSubstitutionHandler extends AnnotationHandler { - - static final String CLASS_SUBSTITUTION_CLASS_NAME = "org.graalvm.compiler.api.replacements.ClassSubstitution"; - - public ClassSubstitutionHandler(AbstractProcessor env) { - super(env, CLASS_SUBSTITUTION_CLASS_NAME); - } - - @Override - public void process(Element element, AnnotationMirror classSubstitution, PluginGenerator generator) { - if (!element.getKind().isClass()) { - assert false : "Element is guaranteed to be a class."; - return; - } - TypeElement type = (TypeElement) element; - - TypeElement substitutionType = resolveOriginalType(processor, type, classSubstitution); - if (substitutionType == null) { - return; - } - } - - static TypeElement resolveOriginalType(AbstractProcessor processor, Element sourceElement, AnnotationMirror classSubstition) { - TypeMirror type = getAnnotationValue(classSubstition, "value", TypeMirror.class); - List classNames = getAnnotationValueList(classSubstition, "className", String.class); - boolean optional = getAnnotationValue(classSubstition, "optional", Boolean.class); - - Messager messager = processor.env().getMessager(); - if (type.getKind() != TypeKind.DECLARED) { - messager.printMessage(Kind.ERROR, "The provided class must be a declared type.", sourceElement, classSubstition); - return null; - } - - if (!classSubstition.getAnnotationType().asElement().equals(((DeclaredType) type).asElement())) { - if (classNames.size() != 0) { - String msg = "The usage of value and className is exclusive."; - messager.printMessage(Kind.ERROR, msg, sourceElement, classSubstition); - messager.printMessage(Kind.ERROR, msg, sourceElement, classSubstition); - } - - return (TypeElement) ((DeclaredType) type).asElement(); - } - - if (classNames.size() != 0) { - TypeElement typeElement = null; - for (String className : classNames) { - typeElement = processor.getTypeElementOrNull(className); - if (typeElement != null) { - break; - } - } - if (typeElement == null && !optional) { - messager.printMessage(Kind.ERROR, String.format("None of the classes %s were found on the classpath.", classNames), sourceElement, classSubstition); - } - - return typeElement; - } - - if (!optional) { - messager.printMessage(Kind.ERROR, String.format("No value for 'value' or 'className' provided."), sourceElement, classSubstition); - } - - return null; - } - -} diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java deleted file mode 100644 index e2b39169c589..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/MethodSubstitutionHandler.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.processor; - -import static org.graalvm.compiler.processor.AbstractProcessor.getAnnotationValue; -import static org.graalvm.compiler.processor.AbstractProcessor.getSimpleName; -import static org.graalvm.compiler.replacements.processor.ClassSubstitutionHandler.CLASS_SUBSTITUTION_CLASS_NAME; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.annotation.processing.Messager; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; - -import org.graalvm.compiler.processor.AbstractProcessor; - -/** - * Handler for the {@value #METHOD_SUBSTITUTION_CLASS_NAME} annotation. - */ -public final class MethodSubstitutionHandler extends AnnotationHandler { - - private static final String METHOD_SUBSTITUTION_CLASS_NAME = "org.graalvm.compiler.api.replacements.MethodSubstitution"; - - private static final boolean DEBUG = false; - - private static final String ORIGINAL_METHOD_NAME = "value"; - private static final String ORIGINAL_IS_STATIC = "isStatic"; - private static final String ORIGINAL_SIGNATURE = "signature"; - - private static final String ORIGINAL_METHOD_NAME_DEFAULT = ""; - private static final String ORIGINAL_SIGNATURE_DEFAULT = ""; - - public MethodSubstitutionHandler(AbstractProcessor processor) { - super(processor, METHOD_SUBSTITUTION_CLASS_NAME); - } - - @SuppressWarnings("unused") - @Override - public void process(Element element, AnnotationMirror annotation, PluginGenerator generator) { - if (element.getKind() != ElementKind.METHOD) { - assert false : "Element is guaranteed to be a method."; - return; - } - ExecutableElement substitutionMethod = (ExecutableElement) element; - TypeElement substitutionType = findEnclosingClass(substitutionMethod); - assert substitutionType != null; - - Messager messager = processor.env().getMessager(); - AnnotationMirror substitutionClassAnnotation = processor.getAnnotation(substitutionType, processor.getType(CLASS_SUBSTITUTION_CLASS_NAME)); - if (substitutionClassAnnotation == null) { - messager.printMessage(Kind.ERROR, String.format("A @%s annotation is required on the enclosing class.", getSimpleName(CLASS_SUBSTITUTION_CLASS_NAME)), element, annotation); - return; - } - boolean optional = getAnnotationValue(substitutionClassAnnotation, "optional", Boolean.class); - if (optional) { - return; - } - - TypeElement originalType = ClassSubstitutionHandler.resolveOriginalType(processor, substitutionType, substitutionClassAnnotation); - if (originalType == null) { - messager.printMessage(Kind.ERROR, String.format("The @%s annotation is invalid on the enclosing class.", getSimpleName(CLASS_SUBSTITUTION_CLASS_NAME)), element, annotation); - return; - } - - if (!substitutionMethod.getModifiers().contains(Modifier.STATIC)) { - messager.printMessage(Kind.ERROR, String.format("A @%s method must be static.", getSimpleName(METHOD_SUBSTITUTION_CLASS_NAME)), element, annotation); - } - - if (substitutionMethod.getModifiers().contains(Modifier.ABSTRACT) || substitutionMethod.getModifiers().contains(Modifier.NATIVE)) { - messager.printMessage(Kind.ERROR, String.format("A @%s method must not be native or abstract.", getSimpleName(METHOD_SUBSTITUTION_CLASS_NAME)), element, annotation); - } - - String originalName = originalName(substitutionMethod, annotation); - boolean isStatic = getAnnotationValue(annotation, ORIGINAL_IS_STATIC, Boolean.class); - TypeMirror[] originalSignature = originalSignature(originalType, substitutionMethod, annotation, isStatic); - if (originalSignature == null) { - return; - } - ExecutableElement originalMethod = originalMethod(substitutionMethod, annotation, originalType, originalName, originalSignature, isStatic); - if (DEBUG && originalMethod != null) { - messager.printMessage(Kind.NOTE, String.format("Found original method %s in type %s.", originalMethod, findEnclosingClass(originalMethod))); - } - } - - private TypeMirror[] originalSignature(TypeElement originalType, ExecutableElement method, AnnotationMirror annotation, boolean isStatic) { - String signatureString = getAnnotationValue(annotation, ORIGINAL_SIGNATURE, String.class); - List parameters = new ArrayList<>(); - Messager messager = processor.env().getMessager(); - if (signatureString.equals(ORIGINAL_SIGNATURE_DEFAULT)) { - for (int i = 0; i < method.getParameters().size(); i++) { - parameters.add(method.getParameters().get(i).asType()); - } - if (!isStatic) { - if (parameters.isEmpty()) { - messager.printMessage(Kind.ERROR, "Method signature must be a static method with the 'this' object as its first parameter", method, annotation); - return null; - } else { - TypeMirror thisParam = parameters.remove(0); - if (!isSubtype(originalType.asType(), thisParam)) { - Name thisName = method.getParameters().get(0).getSimpleName(); - messager.printMessage(Kind.ERROR, String.format("The type of %s must assignable from %s", thisName, originalType), method, annotation); - } - } - } - parameters.add(0, method.getReturnType()); - } else { - try { - APHotSpotSignature signature = new APHotSpotSignature(signatureString); - parameters.add(signature.getReturnType(processor.env())); - for (int i = 0; i < signature.getParameterCount(false); i++) { - parameters.add(signature.getParameterType(processor.env(), i)); - } - } catch (Exception e) { - /* - * That's not good practice and should be changed after APHotSpotSignature has - * received a cleanup. - */ - messager.printMessage(Kind.ERROR, String.format("Parsing the signature failed: %s", e.getMessage() != null ? e.getMessage() : e.toString()), method, annotation); - return null; - } - } - return parameters.toArray(new TypeMirror[parameters.size()]); - } - - private static String originalName(ExecutableElement substituteMethod, AnnotationMirror substitution) { - String originalMethodName = getAnnotationValue(substitution, ORIGINAL_METHOD_NAME, String.class); - if (originalMethodName.equals(ORIGINAL_METHOD_NAME_DEFAULT)) { - originalMethodName = substituteMethod.getSimpleName().toString(); - } - return originalMethodName; - } - - private ExecutableElement originalMethod(ExecutableElement substitutionMethod, AnnotationMirror substitutionAnnotation, TypeElement originalType, String originalName, - TypeMirror[] originalSignature, boolean isStatic) { - TypeMirror signatureReturnType = originalSignature[0]; - TypeMirror[] signatureParameters = Arrays.copyOfRange(originalSignature, 1, originalSignature.length); - List searchElements; - if (originalName.equals("")) { - searchElements = ElementFilter.constructorsIn(originalType.getEnclosedElements()); - } else { - searchElements = ElementFilter.methodsIn(originalType.getEnclosedElements()); - } - - Messager messager = processor.env().getMessager(); - ExecutableElement originalMethod = null; - outer: for (ExecutableElement searchElement : searchElements) { - if (searchElement.getSimpleName().toString().equals(originalName) && searchElement.getParameters().size() == signatureParameters.length) { - for (int i = 0; i < signatureParameters.length; i++) { - VariableElement parameter = searchElement.getParameters().get(i); - if (!isTypeCompatible(parameter.asType(), signatureParameters[i])) { - continue outer; - } - } - originalMethod = searchElement; - break; - } - } - if (originalMethod == null) { - boolean optional = getAnnotationValue(substitutionAnnotation, "optional", Boolean.class); - if (!optional) { - messager.printMessage(Kind.ERROR, - String.format("Could not find the original method with name '%s' and parameters '%s'.", originalName, Arrays.toString(signatureParameters)), - substitutionMethod, substitutionAnnotation); - } - return null; - } - - if (originalMethod.getModifiers().contains(Modifier.STATIC) != isStatic) { - boolean optional = getAnnotationValue(substitutionAnnotation, "optional", Boolean.class); - if (!optional) { - messager.printMessage(Kind.ERROR, String.format("The %s element must be set to %s.", ORIGINAL_IS_STATIC, !isStatic), substitutionMethod, substitutionAnnotation); - } - return null; - } - - if (!isTypeCompatible(originalMethod.getReturnType(), signatureReturnType)) { - messager.printMessage( - Kind.ERROR, - String.format("The return type of the substitution method '%s' must match with the return type of the original method '%s'.", signatureReturnType, - originalMethod.getReturnType()), - substitutionMethod, substitutionAnnotation); - return null; - } - - return originalMethod; - } - - private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { - TypeMirror original = originalType; - TypeMirror substitution = substitutionType; - if (needsErasure(original)) { - original = processor.env().getTypeUtils().erasure(original); - } - if (needsErasure(substitution)) { - substitution = processor.env().getTypeUtils().erasure(substitution); - } - return processor.env().getTypeUtils().isSameType(original, substitution); - } - - /** - * Tests whether one type is a subtype of another. Any type is considered to be a subtype of - * itself. - * - * @param t1 the first type - * @param t2 the second type - * @return {@code true} if and only if the first type is a subtype of the second - */ - private boolean isSubtype(TypeMirror t1, TypeMirror t2) { - TypeMirror t1Erased = t1; - TypeMirror t2Erased = t2; - if (needsErasure(t1Erased)) { - t1Erased = processor.env().getTypeUtils().erasure(t1Erased); - } - if (needsErasure(t2Erased)) { - t2Erased = processor.env().getTypeUtils().erasure(t2Erased); - } - return processor.env().getTypeUtils().isSubtype(t1Erased, t2Erased); - } - - private static boolean needsErasure(TypeMirror typeMirror) { - return typeMirror.getKind() != TypeKind.NONE && typeMirror.getKind() != TypeKind.VOID && !typeMirror.getKind().isPrimitive() && typeMirror.getKind() != TypeKind.OTHER && - typeMirror.getKind() != TypeKind.NULL; - } - - private static TypeElement findEnclosingClass(Element element) { - if (element.getKind().isClass()) { - return (TypeElement) element; - } - - Element enclosing = element.getEnclosingElement(); - while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { - if (enclosing.getKind().isClass()) { - return (TypeElement) enclosing; - } - enclosing = enclosing.getEnclosingElement(); - } - return null; - } - -} diff --git a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java index 4d00040c49e4..f30b0c9b8102 100644 --- a/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java +++ b/compiler/src/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/ReplacementsAnnotationProcessor.java @@ -79,8 +79,6 @@ public boolean doProcess(Set annotations, RoundEnvironmen public List getHandlers() { if (handlers == null) { handlers = new ArrayList<>(); - handlers.add(new ClassSubstitutionHandler(this)); - handlers.add(new MethodSubstitutionHandler(this)); handlers.add(new NodeIntrinsicHandler(this)); handlers.add(new FoldHandler(this)); } diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java deleted file mode 100644 index 903b50c6f50e..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.nodes.ReturnNode; -import org.graalvm.compiler.nodes.StartNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; -import org.junit.Test; - -public class FoldTest extends ReplacementsTest { - - private static class TestMethod { - - public static int test() { - return 42; - } - } - - static class FoldUtils { - - private int number; - - FoldUtils(int number) { - this.number = number; - } - - @Fold - static int multiply(int a, int b) { - // we want to test whether @Fold works, so prevent automatic constant folding - return a * GraalDirectives.opaque(b); - } - - @Fold - int getNumber() { - // we want to test whether @Fold works, so prevent automatic constant folding - return GraalDirectives.opaque(number); - } - } - - @ClassSubstitution(TestMethod.class) - private static class TestMethodSubstitution { - - private static final FoldUtils utils = new FoldUtils(21); - - @MethodSubstitution - public static int test() { - return FoldUtils.multiply(utils.getNumber(), 2); - } - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - GeneratedPluginInjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null, getTarget()); - new PluginFactory_FoldTest().registerPlugins(invocationPlugins, injection); - BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestMethod.class, getReplacements(), replacementBytecodeProvider); - r.registerMethodSubstitution(TestMethodSubstitution.class, "test"); - super.registerInvocationPlugins(invocationPlugins); - } - - public static int callTest() { - return TestMethod.test(); - } - - @Override - protected void checkHighTierGraph(StructuredGraph graph) { - // check that folding happened correctly - StartNode start = graph.start(); - assert start.next() instanceof ReturnNode : "expected ReturnNode, got " + start.next(); - - ReturnNode ret = (ReturnNode) start.next(); - assert ret.result().isConstant() : "expected ConstantNode, got " + ret.result(); - } - - @Test - public void snippetTest() { - test("callTest"); - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java index 3a163b03b287..aa65211415ac 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java @@ -27,7 +27,6 @@ import java.lang.reflect.InvocationTargetException; import java.util.Arrays; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; @@ -46,9 +45,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that - * there are no remaining invocations in the graph. This is sufficient if the method that is being - * substituted is a native method. For Java methods, additional checks are necessary. + * Tests if method substitutions are inlined correctly. Most test cases only assert that there are + * no remaining invocations in the graph. This is sufficient if the method that is being substituted + * is a native method. For Java methods, additional checks are necessary. */ public abstract class MethodSubstitutionTest extends GraalCompilerTest { diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java deleted file mode 100644 index 43fe18a2cd73..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.test; - -import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; -import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing; - -import java.util.function.Function; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.GraalGraphError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.java.BytecodeParser.BytecodeParserError; -import org.graalvm.compiler.nodes.FrameState; -import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.StructuredGraph.Builder; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.OpaqueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.FloatingReadPhase; -import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; -import org.graalvm.compiler.phases.common.GuardLoweringPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.word.LocationIdentity; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Tests for expected behavior when parsing snippets and intrinsics. - */ -public class ReplacementsParseTest extends ReplacementsTest { - - private static final String IN_COMPILED_HANDLER_MARKER = "*** in compiled handler ***"; - - /** - * Marker value to indicate an exception handler was interpreted. We cannot use a complex string - * expression in this context without risking non-deterministic behavior dependent on whether - * String intrinsics are applied or whether String expression evaluation hit an uncommon trap - * when executed by C1 or C2 (and thus potentially altering the profile such that the exception - * handler is *not* compiled by Graal even when we want it to be). - */ - private static final String IN_INTERPRETED_HANDLER_MARKER = "*** in interpreted handler ***"; - - private InlineInvokePlugin.InlineInfo inlineInvokeDecision; - private String inlineInvokeMethodName = null; - - @SuppressWarnings("serial") - static class CustomError extends Error { - CustomError(String message) { - super(message); - } - } - - static final Object THROW_EXCEPTION_MARKER = new Object() { - @Override - public String toString() { - return "THROW_EXCEPTION_MARKER"; - } - }; - - static int copyFirstBody(byte[] left, byte[] right, boolean left2right) { - if (left2right) { - byte e = left[0]; - right[0] = e; - return e; - } else { - byte e = right[0]; - left[0] = e; - return e; - } - } - - static int copyFirstL2RBody(byte[] left, byte[] right) { - byte e = left[0]; - right[0] = e; - return e; - } - - static class TestObject { - static double next(double v) { - return Math.nextAfter(v, 1.0); - } - - static double next2(double v) { - return Math.nextAfter(v, 1.0); - } - - static double nextAfter(double x, double d) { - return Math.nextAfter(x, d); - } - - TestObject() { - this(null); - } - - TestObject(Object id) { - this.id = id; - } - - final Object id; - - String stringizeId() { - Object res = id; - if (res == THROW_EXCEPTION_MARKER) { - // Tests exception throwing from partial intrinsification - throw new CustomError("ex"); - } - return String.valueOf(res); - } - - static String stringize(Object obj) { - Object res = obj; - if (res == THROW_EXCEPTION_MARKER) { - // Tests exception throwing from partial intrinsification - throw new CustomError("ex"); - } - return String.valueOf(res); - } - - static String identity(String s) { - return s; - } - - /** - * @see TestObjectSubstitutions#copyFirst(byte[], byte[], boolean) - */ - static int copyFirst(byte[] left, byte[] right, boolean left2right) { - return copyFirstBody(left, right, left2right); - } - - /** - * @see TestObjectSubstitutions#copyFirstL2R(byte[], byte[]) - */ - static int copyFirstL2R(byte[] left, byte[] right) { - return copyFirstL2RBody(left, right); - } - - static int nonVoidIntrinsicWithCall(@SuppressWarnings("unused") int x, int y) { - return y; - } - - static int nonVoidIntrinsicWithOptimizedSplit(int x) { - return x; - } - - static int div(int x, int y) { - return x / y; - } - } - - static class TestForeignCallDescriptor extends ForeignCallDescriptor { - TestForeignCallDescriptor(boolean reexecutable, boolean canDeoptimize, boolean safepoint, String name, Class resultType, Class... argumentTypes) { - super(name, resultType, argumentTypes, reexecutable, new LocationIdentity[0], canDeoptimize, safepoint); - } - } - - @ClassSubstitution(TestObject.class) - static class TestObjectSubstitutions { - - @MethodSubstitution(isStatic = true) - static double nextAfter(double x, double d) { - double xx = (x == -0.0 ? 0.0 : x); - return Math.nextAfter(xx, d); - } - - /** - * Tests conditional intrinsification of a static method. - */ - @MethodSubstitution - static String stringize(Object obj) { - if (obj != null && obj.getClass() == String.class) { - return asNonNullString(obj); - } else { - // A recursive call denotes exiting/deoptimizing - // out of the partial intrinsification to the - // slow/uncommon case. - return stringize(obj); - } - } - - /** - * Tests conditional intrinsification of a non-static method. - */ - @MethodSubstitution(isStatic = false) - static String stringizeId(TestObject thisObj) { - if (thisObj.id != null && thisObj.id.getClass() == String.class) { - return asNonNullString(thisObj.id); - } else { - // A recursive call denotes exiting/deoptimizing - // out of the partial intrinsification to the - // slow/uncommon case. - return outOfLinePartialIntrinsification(thisObj); - } - } - - static String outOfLinePartialIntrinsification(TestObject thisObj) { - return stringizeId(thisObj); - } - - public static String asNonNullString(Object object) { - return asNonNullStringIntrinsic(object, String.class, true, true); - } - - @NodeIntrinsic(PiNode.class) - private static native String asNonNullStringIntrinsic(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); - - /** - * An valid intrinsic as the frame state associated with the merge should prevent the frame - * states associated with the array stores from being associated with subsequent - * deoptimizing nodes. - */ - @MethodSubstitution - static int copyFirst(byte[] left, byte[] right, boolean left2right) { - return copyFirstBody(left, right, left2right); - } - - /** - * An invalid intrinsic as the frame state associated with the array assignment can leak out - * to subsequent deoptimizing nodes. - */ - @MethodSubstitution - static int copyFirstL2R(byte[] left, byte[] right) { - return copyFirstL2RBody(left, right); - } - - /** - * Tests that non-capturing lambdas are folded away. - */ - @MethodSubstitution - static String identity(String value) { - return apply(s -> s, value); - } - - private static String apply(Function f, String value) { - return f.apply(value); - } - - @MethodSubstitution(isStatic = true) - static int nonVoidIntrinsicWithCall(int x, int y) { - nonVoidIntrinsicWithCallStub(x); - return y; - } - - @MethodSubstitution(isStatic = true) - static int nonVoidIntrinsicWithOptimizedSplit(int x) { - if (x == GraalDirectives.opaque(x)) { - nonVoidIntrinsicWithCallStub(x); - } - return x; - } - - @MethodSubstitution - static int div(int x, int y) { - assert y != 0; - return x / y; - } - - public static void nonVoidIntrinsicWithCallStub(int zLen) { - nonVoidIntrinsicWithCallStub(STUB_CALL, zLen); - } - - static final ForeignCallDescriptor STUB_CALL = new ForeignCallDescriptor("stubCall", void.class, new Class[]{int.class}, false, new LocationIdentity[0], false, false); - - @NodeIntrinsic(ForeignCallNode.class) - private static native void nonVoidIntrinsicWithCallStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, int zLen); - - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestObject.class, getReplacements(), replacementBytecodeProvider); - GeneratedPluginInjectionProvider injections = new DummyInjectionProvider(); - new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringizeId", Receiver.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirst", byte[].class, byte[].class, boolean.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirstL2R", byte[].class, byte[].class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithCall", int.class, int.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithOptimizedSplit", int.class); - r.registerMethodSubstitution(TestObjectSubstitutions.class, "div", int.class, int.class); - - if (replacementBytecodeProvider.supportsInvokedynamic()) { - r.registerMethodSubstitution(TestObjectSubstitutions.class, "identity", String.class); - } - super.registerInvocationPlugins(invocationPlugins); - } - - @BeforeClass - public static void warmupProfiles() { - for (int i = 0; i < 40000; i++) { - callCopyFirst(new byte[16], new byte[16], true); - callCopyFirstL2R(new byte[16], new byte[16]); - } - } - - /** - * Ensure that calling the original method from the substitution binds correctly. - */ - @Test - public void test1() { - test("test1Snippet", 1.0); - } - - public double test1Snippet(double d) { - return TestObject.next(d); - } - - /** - * Ensure that calling the substitution method binds to the original method properly. - */ - @Test - public void test2() { - test("test2Snippet", 1.0); - } - - public double test2Snippet(double d) { - return TestObject.next2(d); - } - - /** - * Ensure that substitution methods with assertions in them don't complain when the exception - * constructor is deleted. - */ - - @Test - public void testNextAfter() { - double[] inArray = new double[1024]; - double[] outArray = new double[1024]; - for (int i = 0; i < inArray.length; i++) { - inArray[i] = -0.0; - } - test("doNextAfter", inArray, outArray); - } - - public void doNextAfter(double[] outArray, double[] inArray) { - for (int i = 0; i < inArray.length; i++) { - double direction = (i & 1) == 0 ? Double.POSITIVE_INFINITY : -Double.NEGATIVE_INFINITY; - outArray[i] = TestObject.nextAfter(inArray[i], direction); - } - } - - private void testWithDifferentReturnValues(OptionValues options, String standardReturnValue, String compiledReturnValue, String name, Object... args) { - ResolvedJavaMethod method = getResolvedJavaMethod(name); - Object receiver = null; - - Result expect = executeExpected(method, receiver, args); - Assert.assertEquals(standardReturnValue, expect.returnValue); - expect = new Result(compiledReturnValue, null); - testAgainstExpected(options, method, expect, receiver, args); - } - - @Override - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { - return super.getCode(installedCodeOwner, graph, forceCompileOverride, installAsDefault, options); - } - - boolean forceCompileOverride; - - @Test - public void testCallStringize() { - test("callStringize", "a string"); - test("callStringize", Boolean.TRUE); - // Unset 'exception seen' bit if testCallStringizeWithoutInlinePartialIntrinsicExit - // is executed before this test - getResolvedJavaMethod("callStringize").reprofile(); - forceCompileOverride = true; - String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER; - String compiledReturnValue = IN_COMPILED_HANDLER_MARKER; - testWithDifferentReturnValues(getInitialOptions(), standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER); - } - - @Test - public void testCallStringizeWithoutInlinePartialIntrinsicExit() { - OptionValues options = new OptionValues(getInitialOptions(), InlinePartialIntrinsicExitDuringParsing, false); - test(options, "callStringize", "a string"); - test(options, "callStringize", Boolean.TRUE); - String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER; - String compiledReturnValue = IN_COMPILED_HANDLER_MARKER; - forceCompileOverride = true; - inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; - inlineInvokeMethodName = "stringize"; - try { - testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER); - } finally { - inlineInvokeDecision = null; - inlineInvokeMethodName = null; - } - } - - @Test - public void testCallStringizeId() { - test("callStringizeId", new TestObject("a string")); - test("callStringizeId", new TestObject(Boolean.TRUE)); - // Unset 'exception seen' bit if testCallStringizeIdWithoutInlinePartialIntrinsicExit - // is executed before this test - getResolvedJavaMethod("callStringize").reprofile(); - forceCompileOverride = true; - String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER; - String compiledReturnValue = IN_COMPILED_HANDLER_MARKER; - testWithDifferentReturnValues(getInitialOptions(), standardReturnValue, compiledReturnValue, "callStringizeId", new TestObject(THROW_EXCEPTION_MARKER)); - } - - @Test - public void testCallStringizeIdWithoutInlinePartialIntrinsicExit() { - OptionValues options = new OptionValues(getInitialOptions(), InlinePartialIntrinsicExitDuringParsing, false); - test(options, "callStringizeId", new TestObject("a string")); - test(options, "callStringizeId", new TestObject(Boolean.TRUE)); - TestObject exceptionTestObject = new TestObject(THROW_EXCEPTION_MARKER); - String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER; - String compiledReturnValue = IN_COMPILED_HANDLER_MARKER; - forceCompileOverride = true; - inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; - inlineInvokeMethodName = "stringizeId"; - try { - testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringizeId", exceptionTestObject); - } finally { - inlineInvokeDecision = null; - inlineInvokeMethodName = null; - } - } - - public static Object callStringize(Object obj) { - try { - return TestObject.stringize(obj); - } catch (CustomError e) { - if (GraalDirectives.inCompiledCode()) { - return IN_COMPILED_HANDLER_MARKER; - } - return IN_INTERPRETED_HANDLER_MARKER; - } - } - - public static Object callStringizeId(TestObject testObj) { - try { - return testObj.stringizeId(); - } catch (CustomError e) { - if (GraalDirectives.inCompiledCode()) { - return IN_COMPILED_HANDLER_MARKER; - } - return IN_INTERPRETED_HANDLER_MARKER; - } - } - - @Test - public void testRootCompileStringize() { - ResolvedJavaMethod method = getResolvedJavaMethod(TestObject.class, "stringize"); - test(method, null, "a string"); - test(method, null, Boolean.TRUE); - test(method, null, THROW_EXCEPTION_MARKER); - } - - @Test - public void testLambda() { - test("callLambda", (String) null); - test("callLambda", "a string"); - } - - public static String callLambda(String value) { - return TestObject.identity(value); - } - - public static int callCopyFirst(byte[] in, byte[] out, boolean left2right) { - int res = TestObject.copyFirst(in, out, left2right); - if (res == 17) { - // A node after the intrinsic that needs a frame state. - GraalDirectives.deoptimize(); - } - return res; - } - - public static int callCopyFirstWrapper(byte[] in, byte[] out, boolean left2right) { - return callCopyFirst(in, out, left2right); - } - - public static int callCopyFirstL2R(byte[] in, byte[] out) { - int res = TestObject.copyFirstL2R(in, out); - if (res == 17) { - // A node after the intrinsic that needs a frame state. - GraalDirectives.deoptimize(); - } - return res; - } - - @Test - public void testCallCopyFirst() { - byte[] in = {0, 1, 2, 3, 4}; - byte[] out = new byte[in.length]; - test("callCopyFirst", in, out, true); - test("callCopyFirst", in, out, false); - } - - @SuppressWarnings("try") - @Test - public void testCallCopyFirstL2R() { - byte[] in = {0, 1, 2, 3, 4}; - byte[] out = new byte[in.length]; - try { - test("callCopyFirstL2R", in, out); - } catch (GraalGraphError e) { - assertTrue(e.getMessage().startsWith("Invalid frame state")); - } - } - - @Override - protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - if (inlineInvokeMethodName == null || inlineInvokeMethodName.equals(method.getName())) { - return inlineInvokeDecision; - } - return null; - } - - @Test - public void testCallCopyFirstWithoutInlinePartialIntrinsicExit() { - OptionValues options = new OptionValues(getInitialOptions(), InlinePartialIntrinsicExitDuringParsing, false); - inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; - try { - byte[] in = {0, 1, 2, 3, 4}; - byte[] out = new byte[in.length]; - test(options, "callCopyFirstWrapper", in, out, true); - test(options, "callCopyFirstWrapper", in, out, false); - } finally { - inlineInvokeDecision = null; - } - } - - public static int nonVoidIntrinsicWithCall(int x, int y) { - if (TestObject.nonVoidIntrinsicWithCall(x, y) == x) { - GraalDirectives.deoptimize(); - } - return y; - } - - /** - * This tests the case where an intrinsic ends with a runtime call but returns some kind of - * value. This requires that a FrameState is available after the {@link ForeignCallNode} since - * the return value must be computed on return from the call. - */ - @Test - public void testNonVoidIntrinsicWithCall() { - testGraph("nonVoidIntrinsicWithCall"); - } - - public static int nonVoidIntrinsicWithOptimizedSplit(int x) { - if (TestObject.nonVoidIntrinsicWithOptimizedSplit(x) == x) { - GraalDirectives.deoptimize(); - } - return x; - } - - /** - * This is similar to {@link #testNonVoidIntrinsicWithCall()} but has a merge after the call - * which would normally capture the {@link FrameState} but in this case we force the merge to be - * optimized away. - */ - @Test - public void testNonVoidIntrinsicWithOptimizedSplit() { - testGraph("nonVoidIntrinsicWithOptimizedSplit"); - } - - public static int div(int x, int y) { - return TestObject.div(x, y); - } - - @Test - public void testAssertionInMethodSubstitution() { - try { - ResolvedJavaMethod method = getResolvedJavaMethod("div"); - // avoid dumping graphs and printing exception since and exception is expected - OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false); - parse(new Builder(options, getDebugContext(options, null, method), AllowAssumptions.YES).method(method).compilationId(getCompilationId(method)), getEagerGraphBuilderSuite()); - throw GraalError.shouldNotReachHere("BytecodeParser should have complained about using assertion in an intrinsic."); - } catch (BytecodeParserError e) { - // Expected behavior - } - } - - @SuppressWarnings("try") - private void testGraph(String name) { - StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES); - try (DebugContext.Scope s0 = graph.getDebug().scope(name, graph)) { - for (OpaqueNode node : graph.getNodes().filter(OpaqueNode.class)) { - node.remove(); - } - HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = createCanonicalizerPhase(); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new FloatingReadPhase().apply(graph); - canonicalizer.apply(graph, context); - new DeadCodeEliminationPhase().apply(graph); - new GuardLoweringPhase().apply(graph, getDefaultMidTierContext()); - new FrameStateAssignmentPhase().apply(graph); - } catch (Throwable e) { - throw graph.getDebug().handle(e); - } - } - - private class DummyInjectionProvider implements GeneratedPluginInjectionProvider { - @SuppressWarnings("unchecked") - @Override - public T getInjectedArgument(Class type) { - if (type == SnippetReflectionProvider.class) { - return (T) getSnippetReflection(); - } - throw new InternalError("missing injection " + type); - } - - @Override - public Stamp getInjectedStamp(Class type, boolean nonNull) { - JavaKind kind = JavaKind.fromJavaClass(type); - return StampFactory.forKind(kind); - } - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java deleted file mode 100644 index 9c2b37b346bc..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.test; - -import java.util.ArrayList; -import java.util.List; - -import org.graalvm.collections.MapCursor; -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.DebugContext.Builder; -import org.graalvm.compiler.nodes.Cancellable; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.compiler.runtime.RuntimeProvider; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * Exercise - * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext, AllowAssumptions, Cancellable)} - * with regular method substitutions and encoded graphs. - */ -@RunWith(Parameterized.class) -public class RootMethodSubstitutionTest extends GraalCompilerTest { - - private final ResolvedJavaMethod method; - private final InvocationPlugin plugin; - - public RootMethodSubstitutionTest(ResolvedJavaMethod method, InvocationPlugin plugin) { - this.method = method; - this.plugin = plugin; - } - - @Parameterized.Parameters(name = "{0}") - public static List data() { - ArrayList ret = new ArrayList<>(); - - Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); - Providers providers = backend.getProviders(); - - MapCursor> cursor = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().getInvocationPlugins(true).getEntries(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); - while (cursor.advance()) { - String className = cursor.getKey(); - ResolvedJavaType type = null; - try { - String typeName = className.substring(1, className.length() - 1).replace('/', '.'); - ClassLoader cl = ClassLoader.getSystemClassLoader(); - Class clazz = Class.forName(typeName, true, cl); - type = metaAccess.lookupJavaType(clazz); - } catch (ClassNotFoundException e) { - continue; - } - - for (InvocationPlugin plugin : cursor.getValue()) { - if (!plugin.inlineOnly()) { - ResolvedJavaMethod original = null; - original = findMethod(plugin, type.getDeclaredMethods()); - if (original == null) { - original = findMethod(plugin, type.getDeclaredConstructors()); - } - if (original == null) { - continue; - } - if (!original.isNative()) { - // Make sure the plugin we found hasn't been overridden. - InvocationPlugin originalPlugin = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(original, getInitialOptions()); - if (plugin == originalPlugin) { - ret.add(new Object[]{original, plugin}); - } - } - } - } - } - return ret; - } - - private static ResolvedJavaMethod findMethod(InvocationPlugin plugin, ResolvedJavaMethod[] methods) { - ResolvedJavaMethod original = null; - for (ResolvedJavaMethod declared : methods) { - if (plugin.match(declared)) { - original = declared; - break; - } - } - return original; - } - - private StructuredGraph getIntrinsicGraph(boolean useEncodedGraphs) { - OptionValues options = new OptionValues(getDebugContext().getOptions(), GraalOptions.UseEncodedGraphs, useEncodedGraphs); - DebugContext debugContext = new Builder(options, getDebugHandlersFactories()).description(getDebugContext().getDescription()).build(); - return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext, AllowAssumptions.YES, null); - } - - StructuredGraph expectedGraph; - StructuredGraph actualGraph; - - @Override - protected void checkHighTierGraph(StructuredGraph graph) { - // Capture the graphs after high tier - if (expectedGraph == null) { - expectedGraph = (StructuredGraph) graph.copy(graph.getDebug()); - } else { - assert actualGraph == null; - actualGraph = (StructuredGraph) graph.copy(graph.getDebug()); - } - super.checkHighTierGraph(graph); - } - - @Test - public void test() { - StructuredGraph regularGraph = getIntrinsicGraph(false); - if (regularGraph != null) { - getCode(method, regularGraph); - } - - if (plugin instanceof MethodSubstitutionPlugin) { - assertTrue(regularGraph != null, "MethodSubstitutionPlugin must produce a graph"); - StructuredGraph encodedGraph = getIntrinsicGraph(true); - assertTrue(encodedGraph != null, "must produce a graph"); - getCode(method, encodedGraph); - - // Compare the high tier graphs since the final graph might have scheduler - // differences because of different usage ordering. - assertEquals(expectedGraph, actualGraph, true, false); - } - } - -} diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java index b7feadc17628..5c38bb973633 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.java @@ -26,7 +26,6 @@ import java.util.HashMap; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -44,7 +43,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Tests the VM independent {@link MethodSubstitution}s. + * Tests the VM independent method substitutions. */ public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest { diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java index b025977db3bc..d8ff66f005a5 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java @@ -31,19 +31,13 @@ import java.util.List; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.SourceMapping; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.debug.BlackholeNode; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; @@ -60,52 +54,6 @@ */ public class SubstitutionNodeSourcePositionTest extends ReplacementsTest { - private static class TestMethod { - - public static int test(int i) { - return i; - } - } - - @ClassSubstitution(TestMethod.class) - public static class TestMethodSubstitution { - - @MethodSubstitution - public static int test(int i) { - blackhole(i); - return i; - } - - @Node.NodeIntrinsic(BlackholeNode.class) - private static native void blackhole(int i); - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - new PluginFactory_SubstitutionNodeSourcePositionTest().registerPlugins(invocationPlugins, null); - ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - InvocationPlugins.Registration r = new InvocationPlugins.Registration(invocationPlugins, TestMethod.class, getReplacements(), bytecodeProvider); - r.registerMethodSubstitution(TestMethodSubstitution.class, "test", int.class); - super.registerInvocationPlugins(invocationPlugins); - } - - public int methodSubstitution() { - return TestMethod.test(42); - } - - @Test - public void testMethodSubstitution() { - // @formatter:off - // Expect mappings of the form: - // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest$TestMethodSubstitution.blackhole(int) [bci: -1] - // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest$TestMethodSubstitution.test(SubstitutionNodeSourcePositionTest.java:71) [bci: 1] Substitution - // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest$TestMethod.test(int) [bci: -1] - // at org.graalvm.compiler.replacements.test.SubstitutionNodeSourcePositionTest.methodSubstitution(SubstitutionNodeSourcePositionTest.java:89) [bci: 2] - // @formatter:on - Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions())); - checkMappings("methodSubstitution", true, TestMethod.class, "test"); - } - public void snippetLowering(String[] array, String value) { array[0] = value; } diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java deleted file mode 100644 index 14a8aaf1e2a2..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.test; - -import static org.graalvm.compiler.nodeinfo.InputType.Guard; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; -import static org.hamcrest.CoreMatchers.instanceOf; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodeinfo.StructuralInput.Guard; -import org.graalvm.compiler.nodeinfo.StructuralInput.Memory; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ReturnNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; -import org.graalvm.word.LocationIdentity; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.meta.JavaKind; - -public class SubstitutionsTest extends ReplacementsTest { - - @NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_IGNORED, size = SIZE_IGNORED) - static class TestMemory extends FixedWithNextNode implements SingleMemoryKill { - private static final NodeClass TYPE = NodeClass.create(TestMemory.class); - - protected TestMemory() { - super(TYPE, StampFactory.forVoid()); - } - - @NodeIntrinsic - public static native Memory memory(); - - @Override - public LocationIdentity getKilledLocationIdentity() { - return LocationIdentity.any(); - } - } - - @NodeInfo(allowedUsageTypes = {Guard}, cycles = CYCLES_IGNORED, size = SIZE_IGNORED) - static class TestGuard extends FloatingNode implements GuardingNode { - private static final NodeClass TYPE = NodeClass.create(TestGuard.class); - - @Input(Memory) MemoryKill memory; - - protected TestGuard(ValueNode memory) { - super(TYPE, StampFactory.forVoid()); - this.memory = (MemoryKill) memory; - } - - @NodeIntrinsic - public static native Guard guard(Memory memory); - } - - @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) - static class TestValue extends FloatingNode { - private static final NodeClass TYPE = NodeClass.create(TestValue.class); - - @Input(Guard) GuardingNode guard; - - protected TestValue(ValueNode guard) { - super(TYPE, StampFactory.forKind(JavaKind.Int)); - this.guard = (GuardingNode) guard; - } - - @NodeIntrinsic - public static native int value(Guard guard); - } - - private static class TestMethod { - - public static int test() { - return 42; - } - } - - @ClassSubstitution(TestMethod.class) - private static class TestMethodSubstitution { - - @MethodSubstitution - public static int test() { - Memory memory = TestMemory.memory(); - Guard guard = TestGuard.guard(memory); - return TestValue.value(guard); - } - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - new PluginFactory_SubstitutionsTest().registerPlugins(invocationPlugins, null); - ClassfileBytecodeProvider bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, TestMethod.class, getReplacements(), bytecodeProvider); - r.registerMethodSubstitution(TestMethodSubstitution.class, "test"); - super.registerInvocationPlugins(invocationPlugins); - } - - public static int callTest() { - return TestMethod.test(); - } - - @Override - protected void checkHighTierGraph(StructuredGraph graph) { - // Check that the graph contains the expected test nodes. - NodeIterable retNodes = graph.getNodes().filter(ReturnNode.class); - Assert.assertTrue("expected exactly one ReturnNode", retNodes.count() == 1); - ReturnNode ret = retNodes.first(); - - Assert.assertThat(ret.result(), instanceOf(TestValue.class)); - TestValue value = (TestValue) ret.result(); - - Assert.assertThat(value.guard, instanceOf(TestGuard.class)); - TestGuard guard = (TestGuard) value.guard; - - Assert.assertThat(guard.memory, instanceOf(TestMemory.class)); - TestMemory memory = (TestMemory) guard.memory; - - // Remove the test nodes, replacing them by the constant 42. - // This implicitly makes sure that the rest of the graph is valid. - ret.replaceFirstInput(value, graph.unique(ConstantNode.forInt(42))); - value.safeDelete(); - guard.safeDelete(); - graph.removeFixed(memory); - } - - @Test - public void snippetTest() { - test("callTest"); - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java deleted file mode 100644 index 72305317cabb..000000000000 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.replacements.test.classfile; - -import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; -import static org.graalvm.compiler.test.SubprocessUtil.java; -import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; -import static org.junit.Assume.assumeTrue; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.lang.instrument.Instrumentation; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.ProtectionDomain; -import java.util.List; -import java.util.jar.Attributes; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; - -import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.replacements.test.ReplacementsTest; -import org.graalvm.compiler.test.SubprocessUtil; -import org.graalvm.compiler.test.SubprocessUtil.Subprocess; -import org.junit.Assert; -import org.junit.Test; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Tests that intrinsics (and snippets) are isolated from bytecode instrumentation. - */ -public class RedefineIntrinsicTest extends ReplacementsTest { - - public static class Original { - - // Intrinsified by Intrinsic.getValue - public static String getValue() { - return "original"; - } - } - - @ClassSubstitution(Original.class) - private static class Intrinsic { - - @MethodSubstitution - public static String getValue() { - return "intrinsic"; - } - } - - @Override - protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); - Registration r = new Registration(invocationPlugins, Original.class, getReplacements(), replacementBytecodeProvider); - r.registerMethodSubstitution(Intrinsic.class, "getValue"); - super.registerInvocationPlugins(invocationPlugins); - } - - public static String callOriginalGetValue() { - // This call will be intrinsified when compiled by Graal - return Original.getValue(); - } - - public static String callIntrinsicGetValue() { - // This call will *not* be intrinsified when compiled by Graal - return Intrinsic.getValue(); - } - - @Test - public void test() throws Throwable { - assumeManagementLibraryIsLoadable(); - try { - Class.forName("java.lang.instrument.Instrumentation"); - } catch (ClassNotFoundException ex) { - // skip this test if java.instrument JDK9 module is missing - return; - } - String recursionPropName = getClass().getName() + ".recursion"; - if (Boolean.getBoolean(recursionPropName)) { - testHelper(); - } else { - List vmArgs = withoutDebuggerArguments(getVMCommandLine()); - vmArgs.add("-D" + recursionPropName + "=true"); - vmArgs.add(SubprocessUtil.PACKAGE_OPENING_OPTIONS); - vmArgs.add("-Djdk.attach.allowAttachSelf=true"); - Subprocess proc = java(vmArgs, "com.oracle.mxtool.junit.MxJUnitWrapper", getClass().getName()); - if (proc.exitCode != 0) { - Assert.fail(String.format("non-zero exit code %d for command:%n%s", proc.exitCode, proc)); - } - } - } - - public void testHelper() throws Throwable { - - Object receiver = null; - Object[] args = {}; - - // Prior to redefinition, both Original and Intrinsic - // should behave as per their Java source code - Assert.assertEquals("original", Original.getValue()); - Assert.assertEquals("intrinsic", Intrinsic.getValue()); - - ResolvedJavaMethod callOriginalGetValue = getResolvedJavaMethod("callOriginalGetValue"); - ResolvedJavaMethod callIntrinsicGetValue = getResolvedJavaMethod("callIntrinsicGetValue"); - - // Expect intrinsification to change "original" to "intrinsic" - testAgainstExpected(callOriginalGetValue, new Result("intrinsic", null), receiver, args); - - // Expect no intrinsification - testAgainstExpected(callIntrinsicGetValue, new Result("intrinsic", null), receiver, args); - - // Apply redefinition of intrinsic bytecode - if (!redefineIntrinsic()) { - // running on JDK9 without agent - return; - } - - // Expect redefinition to have no effect - Assert.assertEquals("original", Original.getValue()); - - // Expect redefinition to change "intrinsic" to "redefined" - Assert.assertEquals("redefined", Intrinsic.getValue()); - - // Expect redefinition to have no effect on intrinsification (i.e., - // "original" is still changed to "intrinsic", not "redefined" - testAgainstExpected(callOriginalGetValue, new Result("intrinsic", null), receiver, args); - } - - /** - * Adds the class file bytes for a given class to a JAR stream. - */ - static void add(JarOutputStream jar, Class c) throws IOException { - String name = c.getName(); - String classAsPath = name.replace('.', '/') + ".class"; - jar.putNextEntry(new JarEntry(classAsPath)); - - InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath); - - int nRead; - byte[] buf = new byte[1024]; - while ((nRead = stream.read(buf, 0, buf.length)) != -1) { - jar.write(buf, 0, nRead); - } - - jar.closeEntry(); - } - - static boolean redefineIntrinsic() throws Exception { - Manifest manifest = new Manifest(); - manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); - Attributes mainAttrs = manifest.getMainAttributes(); - mainAttrs.putValue("Agent-Class", RedefinerAgent.class.getName()); - mainAttrs.putValue("Can-Redefine-Classes", "true"); - mainAttrs.putValue("Can-Retransform-Classes", "true"); - - Path jar = Files.createTempFile("myagent", ".jar"); - try { - JarOutputStream jarStream = new JarOutputStream(new FileOutputStream(jar.toFile()), manifest); - add(jarStream, RedefinerAgent.class); - add(jarStream, Redefiner.class); - jarStream.close(); - - return loadAgent(jar); - } finally { - Files.deleteIfExists(jar); - } - } - - @SuppressWarnings({"deprecation", "unused"}) - public static boolean loadAgent(Path agent) throws Exception { - String vmName = ManagementFactory.getRuntimeMXBean().getName(); - int p = vmName.indexOf('@'); - assumeTrue("VM name not in @ format: " + vmName, p != -1); - String pid = vmName.substring(0, p); - Class c; - try { - // I don't know what changed to make this necessary... - c = Class.forName("com.sun.tools.attach.VirtualMachine", true, RedefineIntrinsicTest.class.getClassLoader()); - } catch (ClassNotFoundException ex) { - try { - Class.forName("javax.naming.Reference"); - } catch (ClassNotFoundException coreNamingMissing) { - // if core JDK classes aren't found, we are probably running in a - // JDK9 java.base environment and then missing class is OK - return false; - } - throw ex; - } - Method attach = c.getDeclaredMethod("attach", String.class); - Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class); - Method detach = c.getDeclaredMethod("detach"); - Object vm = attach.invoke(null, pid); - loadAgent.invoke(vm, agent.toString(), ""); - detach.invoke(vm); - return true; - } - - public static class RedefinerAgent { - - public static void agentmain(@SuppressWarnings("unused") String args, Instrumentation inst) throws Exception { - if (inst.isRedefineClassesSupported() && inst.isRetransformClassesSupported()) { - inst.addTransformer(new Redefiner(), true); - Class[] allClasses = inst.getAllLoadedClasses(); - for (int i = 0; i < allClasses.length; i++) { - Class c = allClasses[i]; - if (c == Intrinsic.class) { - inst.retransformClasses(new Class[]{c}); - } - } - } - } - } - - /** - * This transformer replaces the first instance of the constant "intrinsic" in the class file - * for {@link Intrinsic} with "redefined". - */ - static class Redefiner implements ClassFileTransformer { - - @Override - public byte[] transform(ClassLoader cl, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - if (Intrinsic.class.equals(classBeingRedefined)) { - String cf = new String(classfileBuffer); - int i = cf.indexOf("intrinsic"); - Assert.assertTrue("cannot find \"intrinsic\" constant in " + Intrinsic.class.getSimpleName() + "'s class file", i > 0); - System.arraycopy("redefined".getBytes(), 0, classfileBuffer, i, "redefined".length()); - } - return classfileBuffer; - } - } -} diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java index 073aefb149a8..de06ed310c1a 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java @@ -26,12 +26,14 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; + +import java.util.concurrent.ConcurrentHashMap; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.SourceLanguagePositionProvider; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -45,7 +47,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.spi.CoreProviders; @@ -57,8 +58,6 @@ import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.ResolvedJavaMethod; -import java.util.concurrent.ConcurrentHashMap; - /** * A graph decoder that provides all necessary encoded graphs on-the-fly (by parsing the methods and * encoding the graphs). @@ -96,14 +95,12 @@ protected GraphBuilderPhase.Instance createGraphBuilderPhaseInstance(IntrinsicCo } @SuppressWarnings("try") - private EncodedGraph createGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { + private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { StructuredGraph graphToEncode; if (isSubstitution && (UseEncodedGraphs.getValue(options) || IS_IN_NATIVE_IMAGE)) { - // These must go through Replacements to find the graph to use. - graphToEncode = providers.getReplacements().getMethodSubstitution(plugin, method, INLINE_AFTER_PARSING, allowAssumptions, - null, options); + throw GraalError.shouldNotReachHere("dead path"); } else { - graphToEncode = buildGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution); + graphToEncode = buildGraph(method, intrinsicBytecodeProvider, isSubstitution); } /* @@ -123,20 +120,21 @@ private EncodedGraph createGraph(ResolvedJavaMethod method, MethodSubstitutionPl } @SuppressWarnings("try") - private StructuredGraph buildGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { + private StructuredGraph buildGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { StructuredGraph graphToEncode;// @formatter:off graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions). useProfilingInfo(false). trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()). - method(plugin != null ? plugin.getSubstitute(providers.getMetaAccess()) : method). + method(method). setIsSubstitution(isSubstitution). cancellable(graph.getCancellable()). build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("buildGraph", graphToEncode); DebugCloseable a = BuildGraphTimer.start(debug)) { - IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null - ? new IntrinsicContext(method, plugin.getSubstitute(providers.getMetaAccess()), intrinsicBytecodeProvider, INLINE_AFTER_PARSING) - : null; + if (intrinsicBytecodeProvider != null) { + throw GraalError.shouldNotReachHere("isn't this dead?"); + } + IntrinsicContext initialIntrinsicContext = null; GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext); graphBuilderPhaseInstance.apply(graphToEncode); CanonicalizerPhase.create().apply(graphToEncode, providers); @@ -150,11 +148,11 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, MethodSubstitution } @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition) { EncodedGraph result = graphCache.get(method); if (result == null && method.hasBytecodes()) { - result = createGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution); + result = createGraph(method, intrinsicBytecodeProvider, isSubstitution); } return result; } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java index 29a57b850099..8f4143e212b8 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java @@ -27,7 +27,6 @@ import static jdk.vm.ci.code.BytecodeFrame.AFTER_BCI; import org.graalvm.compiler.bytecode.Bytecode; -import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; @@ -61,7 +60,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.CoreProvidersDelegate; @@ -89,7 +87,6 @@ public class IntrinsicGraphBuilder extends CoreProvidersDelegate implements Grap protected FixedWithNextNode lastInstr; protected ValueNode[] arguments; protected ValueNode returnValue; - private boolean parsingIntrinsic; private FrameState createStateAfterStartOfReplacementGraph(ResolvedJavaMethod original, GraphBuilderConfiguration graphBuilderConfig) { FrameStateBuilder startFrameState = new FrameStateBuilder(this, code, graph, graphBuilderConfig.retainLocalVariables()); @@ -317,7 +314,7 @@ public int getDepth() { @Override public boolean parsingIntrinsic() { - return parsingIntrinsic; + return false; } @Override @@ -337,7 +334,6 @@ public ValueNode get(boolean performNullCheck) { @SuppressWarnings("try") public final StructuredGraph buildGraph(InvocationPlugin plugin) { - parsingIntrinsic = plugin instanceof MethodSubstitutionPlugin; // The caller is expected to have filtered out decorator plugins since they cannot be // processed without special handling. assert !plugin.isDecorator() : plugin; @@ -374,16 +370,6 @@ public boolean canMergeIntrinsicReturns() { return true; } - @Override - public boolean intrinsify(BytecodeProvider bytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { - return false; - } - - @Override - public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, Receiver receiver, ValueNode[] argsIncludingReceiver) { - return false; - } - @Override public boolean isParsingInvocationPlugin() { return true; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index c5a943680bbd..9707a0206cdb 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -107,7 +107,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; @@ -422,16 +421,6 @@ public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) throw unimplemented(); } - @Override - public boolean intrinsify(BytecodeProvider bytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { - return false; - } - - @Override - public boolean intrinsify(ResolvedJavaMethod targetMethod, StructuredGraph substituteGraph, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { - return false; - } - @Override public void setStateAfter(StateSplit stateSplit) { throw unimplemented(); @@ -816,7 +805,7 @@ protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, @SuppressWarnings("try") public void decode(ResolvedJavaMethod method, boolean isSubstitution, boolean trackNodeSourcePosition) { try (DebugContext.Scope scope = debug.scope("PEGraphDecode", graph)) { - EncodedGraph encodedGraph = lookupEncodedGraph(method, null, null, isSubstitution, trackNodeSourcePosition); + EncodedGraph encodedGraph = lookupEncodedGraph(method, null, isSubstitution, trackNodeSourcePosition); recordGraphElements(encodedGraph); PEMethodScope methodScope = createMethodScope(graph, null, null, encodedGraph, method, null, 0, null); decode(createInitialLoopScope(methodScope, null)); @@ -1152,7 +1141,7 @@ protected LoopScope doInline(PEMethodScope methodScope, LoopScope loopScope, Inv return null; } ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline(); - EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getPlugin(), inlineInfo.getIntrinsicBytecodeProvider(), inlineInfo.isSubstitution(), graph.trackNodeSourcePosition()); + EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getIntrinsicBytecodeProvider(), false, graph.trackNodeSourcePosition()); if (graphToInline == null) { return null; } @@ -1426,8 +1415,7 @@ private static void deleteInvoke(Invoke invoke) { } } - protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, - boolean trackNodeSourcePosition); + protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition); @SuppressWarnings("try") @Override diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java index dbfc7ef3c8be..cc96e83decc9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java @@ -28,12 +28,8 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache; import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; -import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; -import static org.graalvm.compiler.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; -import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createMethodSubstitutionInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; import java.util.BitSet; @@ -44,7 +40,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.replacements.SnippetTemplateCache; @@ -85,7 +80,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; @@ -204,14 +198,6 @@ public Class getIntrinsifyingPlugin(ResolvedJavaMe */ @Override public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method, b.getOptions()); - if (msPlugin != null) { - if (b.parsingIntrinsic() || InlineDuringParsing.getValue(b.getOptions()) || InlineIntrinsicsDuringParsing.getValue(b.getOptions())) { - // Forced inlining of intrinsics - return createMethodSubstitutionInlineInfo(method, msPlugin); - } - return null; - } if (b.parsingIntrinsic()) { assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; @@ -331,18 +317,6 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin // No initialization needed as snippet graphs are created on demand in getSnippet } - @Override - public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, - AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { - // Method substitutions are parsed by the BytecodeParser. - return null; - } - - @Override - public void registerMethodSubstitution(MethodSubstitutionPlugin plugin) { - // No initialization needed as method substitutions are parsed by the BytecodeParser. - } - @Override public void registerConditionalPlugin(InvocationPlugin plugin) { } @@ -358,15 +332,6 @@ public BytecodeProvider getDefaultReplacementBytecodeProvider() { return defaultBytecodeProvider; } - protected MethodSubstitutionPlugin getMethodSubstitution(ResolvedJavaMethod method, OptionValues options) { - InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method, options); - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; - return msPlugin; - } - return null; - } - @Override public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invokeBci, Invoke.InlineControl inlineControl, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, AllowAssumptions allowAssumptions, OptionValues options) { @@ -377,29 +342,9 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo StructuredGraph result; InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method, options); if (plugin != null) { - MetaAccessProvider metaAccess = providers.getMetaAccess(); - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; - ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess); - StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null; - if (graph == null || graph.trackNodeSourcePosition() != trackNodeSourcePosition) { - try (DebugContext debug = openSnippetDebugContext("Substitution_", method, options)) { - graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, null, method, trackNodeSourcePosition, replaceePosition, INLINE_AFTER_PARSING); - if (!UseSnippetGraphCache.getValue(options)) { - return graph; - } - graph.freeze(); - graphs.putIfAbsent(substitute, graph); - graph = graphs.get(substitute); - } - } - assert graph.isFrozen(); - result = graph; - } else { - Bytecode code = new ResolvedJavaMethodBytecode(method); - try (DebugContext debug = openSnippetDebugContext("Substitution_", method, options)) { - result = new IntrinsicGraphBuilder(options, debug, providers, code, invokeBci, allowAssumptions).buildGraph(plugin); - } + Bytecode code = new ResolvedJavaMethodBytecode(method); + try (DebugContext debug = openSnippetDebugContext("Substitution_", method, options)) { + result = new IntrinsicGraphBuilder(options, debug, providers, code, invokeBci, allowAssumptions).buildGraph(plugin); } } else { result = null; @@ -413,36 +358,11 @@ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationI InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method, debug.getOptions()); if (plugin != null && !plugin.inlineOnly()) { assert !plugin.isDecorator() : "lookupInvocation shouldn't return decorator plugins"; - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin; - ResolvedJavaMethod substMethod = msPlugin.getSubstitute(providers.getMetaAccess()); - assert !substMethod.equals(method); - BytecodeProvider bytecodeProvider = msPlugin.getBytecodeProvider(); - // @formatter:off - StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug, allowAssumptions). - method(substMethod). - compilationId(compilationId). - recordInlinedMethods(bytecodeProvider.shouldRecordMethodDependencies()). - setIsSubstitution(true). - build(); - // @formatter:on - try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) { - Plugins plugins = new Plugins(getGraphBuilderPlugins()); - GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, bytecodeProvider, ROOT_COMPILATION); - new GraphBuilderPhase.Instance(providers, config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); - assert !graph.isFrozen(); - return graph; - } catch (Throwable e) { - debug.handle(e); - } - } else { - Bytecode code = new ResolvedJavaMethodBytecode(method); - OptionValues options = debug.getOptions(); - Plugins plugins = new Plugins(getGraphBuilderPlugins()); - GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - return new IntrinsicGraphBuilder(options, debug, providers, code, -1, StructuredGraph.AllowAssumptions.YES, config).buildGraph(plugin); - } + Bytecode code = new ResolvedJavaMethodBytecode(method); + OptionValues options = debug.getOptions(); + Plugins plugins = new Plugins(getGraphBuilderPlugins()); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); + return new IntrinsicGraphBuilder(options, debug, providers, code, -1, StructuredGraph.AllowAssumptions.YES, config).buildGraph(plugin); } return null; } @@ -454,8 +374,7 @@ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationI * @param method the snippet or method substitution for which a graph will be created * @param args * @param nonNullParameters - * @param original the original method if {@code method} is a {@linkplain MethodSubstitution - * substitution} otherwise null + * @param original XXX always null? * @param trackNodeSourcePosition record source information * @param context * {@link org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext @@ -475,8 +394,7 @@ public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodePr * @param method the snippet or method substitution for which a graph will be created * @param args * @param nonNullParameters - * @param original the original method if {@code method} is a {@linkplain MethodSubstitution - * substitution} otherwise null + * @param original XXX always null? * @param trackNodeSourcePosition record source information */ public final StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, BitSet nonNullParameters, ResolvedJavaMethod original, @@ -652,19 +570,17 @@ protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider IntrinsicContext initialIntrinsicContext = null; Snippet snippetAnnotation = null; - MethodSubstitution methodAnnotation = null; if (!IS_IN_NATIVE_IMAGE) { snippetAnnotation = method.getAnnotation(Snippet.class); - methodAnnotation = method.getAnnotation(MethodSubstitution.class); } - if (methodAnnotation == null && snippetAnnotation == null) { + if (snippetAnnotation == null) { // Post-parse inlined intrinsic initialIntrinsicContext = new EncodedIntrinsicContext(substitutedMethod, method, bytecodeProvider, context, false); } else { // Snippet ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method; initialIntrinsicContext = new EncodedIntrinsicContext(original, method, bytecodeProvider, context, - snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true); + snippetAnnotation.allowPartialIntrinsicArgumentMismatch()); } createGraphBuilder(replacements.providers, config, OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java index 5bdfa07f2d53..9c7acd60b5e5 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java @@ -24,7 +24,6 @@ */ package org.graalvm.compiler.replacements; -import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.java.LoadFieldNode; @@ -33,7 +32,6 @@ /** * Substitutions for {@link java.lang.String} methods. */ -@ClassSubstitution(String.class) public class StringSubstitutions { /** diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java index 8a84ca1a5086..b6b9bc88644f 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroInvokable.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.code.BytecodeFrame.isPlaceholderBci; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeInputList; @@ -57,8 +56,6 @@ *
    *
  • If {@link #getLoweredSnippetGraph(LoweringTool)} returns a non-null result, this graph is * used as a replacement.
  • - *
  • If a {@link MethodSubstitution} for the target method is found, this substitution is used as - * a replacement.
  • *
  • Otherwise, the macro node is replaced with an {@link InvokeNode}.
  • *
*/ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java index 3c88b3baec60..f7bb3137ac5e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysis.java @@ -45,7 +45,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; @@ -176,8 +175,7 @@ protected PEMethodScope createMethodScope(StructuredGraph targetGraph, PEMethodS } @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, - boolean trackNodeSourcePosition) { + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition) { AnalysisMethod aMethod = (AnalysisMethod) method; return aMethod.ensureGraphParsed(bb).getEncodedGraph(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index dcaa06df89fe..4f0c4f3c9d4e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -68,7 +68,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; @@ -228,8 +227,7 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod private IntrinsicContext intrinsic = new IntrinsicContext(method, null, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING, false); @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, - boolean isSubstitution, boolean track) { + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean track) { if (lookupMethod.equals(method)) { assert !track || encodedGraph.trackNodeSourcePosition(); return encodedGraph; @@ -344,12 +342,6 @@ protected void copyFrom(SubstrateReplacements copyFrom, Function } } - @Override - protected MethodSubstitutionPlugin getMethodSubstitution(ResolvedJavaMethod method, OptionValues options) { - // This override keeps graphBuilderPlugins from being reached during image generation. - return null; - } - @Override public boolean hasSubstitution(ResolvedJavaMethod method, OptionValues options) { // This override keeps graphBuilderPlugins from being reached during image generation. 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 4d6e519450a0..4ee075cccf37 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 @@ -54,11 +54,8 @@ import com.oracle.svm.core.heap.Heap; import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.MapCursor; import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.GraalServiceThread; -import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -74,9 +71,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionDescriptor; @@ -92,11 +86,9 @@ import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup; import org.graalvm.compiler.truffle.common.TruffleCompilerRuntime; import org.graalvm.compiler.truffle.compiler.PartialEvaluatorConfiguration; -import org.graalvm.compiler.truffle.compiler.TruffleCompilerBase; import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentationFactory; import org.graalvm.compiler.truffle.compiler.substitutions.GraphBuilderInvocationPluginProvider; import org.graalvm.compiler.truffle.compiler.substitutions.GraphDecoderInvocationPluginProvider; -import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.jniutils.JNI; import org.graalvm.jniutils.JNIExceptionWrapper; import org.graalvm.jniutils.JNIMethodScope; @@ -423,33 +415,10 @@ public void registerLowerings(RuntimeConfiguration runtimeConfig, OptionValues o hotSpotSubstrateReplacements = getReplacements(); } - private void registerMethodSubstitutions(DebugContext debug, InvocationPlugins invocationPlugins, MetaAccessProvider metaAccess) { - MapCursor> cursor = invocationPlugins.getInvocationPlugins(true).getEntries(); - while (cursor.advance()) { - String className = cursor.getKey(); - for (InvocationPlugin plugin : cursor.getValue()) { - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin methodSubstitutionPlugin = (MethodSubstitutionPlugin) plugin; - - ResolvedJavaMethod original = methodSubstitutionPlugin.getOriginalMethod(metaAccess); - if (original != null) { - ResolvedJavaMethod method = methodSubstitutionPlugin.getSubstitute(metaAccess); - debug.log("Method substitution %s %s", method, original); - - hotSpotSubstrateReplacements.checkRegistered(methodSubstitutionPlugin); - } else { - throw new GraalError("Can't find original method for " + methodSubstitutionPlugin.getMethodNameWithArgumentsDescriptor() + " with class " + className); - } - } - } - } - } - @SuppressWarnings({"try", "unchecked"}) @Override public void beforeAnalysis(BeforeAnalysisAccess access) { FeatureImpl.BeforeAnalysisAccessImpl impl = (FeatureImpl.BeforeAnalysisAccessImpl) access; - DebugContext debug = impl.getBigBang().getDebug(); // Services that will not be loaded if native-image is run // with -XX:-UseJVMCICompiler. @@ -461,19 +430,6 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { GraalServices.load(HotSpotMBeanOperationProvider.class); GraalServices.load(DisassemblerProvider.class); - try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { - InvocationPlugins compilerPlugins = hotSpotSubstrateReplacements.getGraphBuilderPlugins().getInvocationPlugins(); - MetaAccessProvider metaAccess = hotSpotSubstrateReplacements.getProviders().getMetaAccess(); - registerMethodSubstitutions(debug, compilerPlugins, metaAccess); - - // Also register Truffle plugins - TruffleCompilerBase truffleCompiler = (TruffleCompilerBase) GraalTruffleRuntime.getRuntime().newTruffleCompiler(); - InvocationPlugins trufflePlugins = truffleCompiler.getPartialEvaluator().getConfigPrototype().getPlugins().getInvocationPlugins(); - registerMethodSubstitutions(debug, trufflePlugins, metaAccess); - } catch (Throwable t) { - throw debug.handle(t); - } - // Filter out any cached services which are for a different architecture try { HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java index 8cd88dd12733..ea0bd96cc171 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java @@ -38,7 +38,6 @@ import java.util.function.Function; import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -324,7 +323,7 @@ public static StructuredGraph decodeGraph(DebugContext debug, String name, Compi return null; } - boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null; + boolean isSubstitution = method.getAnnotation(Snippet.class) != null; StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug).name(name).method(method).compilationId(compilationId).setIsSubstitution(isSubstitution).build(); GraphDecoder decoder = new GraphDecoder(ConfigurationValues.getTarget().arch, graph); decoder.decode(encodedGraph); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstratePEGraphDecoder.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstratePEGraphDecoder.java index 9ce0924f5f81..f4e27b527d78 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstratePEGraphDecoder.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstratePEGraphDecoder.java @@ -26,6 +26,8 @@ import static com.oracle.svm.core.util.VMError.shouldNotReachHere; +import java.util.concurrent.ConcurrentHashMap; + import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.graph.SourceLanguagePositionProvider; @@ -34,7 +36,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.spi.CoreProviders; @@ -46,8 +47,6 @@ import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.ResolvedJavaMethod; -import java.util.concurrent.ConcurrentHashMap; - public class SubstratePEGraphDecoder extends PEGraphDecoder { private final EconomicMap graphCache = EconomicMap.create(); @@ -61,8 +60,7 @@ public SubstratePEGraphDecoder(Architecture architecture, StructuredGraph graph, } @Override - protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, MethodSubstitutionPlugin plugin, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, - boolean trackNodeSourcePosition) { + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution, boolean trackNodeSourcePosition) { /* * The EncodedGraph instance also serves as a cache for some information during decoding, * e.g., the start offsets of encoded nodes. So it is beneficial to have a cache of the From 226e758494c2966edb1f7b094ad5992773f30742 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 00:26:37 -0800 Subject: [PATCH 08/18] Simplify array allocation --- .../meta/HotSpotGraphBuilderPlugins.java | 12 +- .../replacements/EncodedSymbolConstant.java | 118 ------------------ 2 files changed, 6 insertions(+), 124 deletions(-) delete mode 100644 compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 022599b4d03c..f8a6350da26a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -883,13 +883,13 @@ private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVM "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class) { @Override protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { - Object[] constantArguments = new Object[4]; ResolvedJavaType declaringClass = targetMethod.getDeclaringClass(); - constantArguments[0] = declaringClass; - constantArguments[1] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA;"); - constantArguments[2] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA2;"); - constantArguments[3] = HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA5;"); - return constantArguments; + return new Object[]{ + declaringClass, + HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA;"), + HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA2;"), + HotSpotReplacementsUtil.getType(declaringClass, "Lsun/security/provider/SHA5;") + }; } @Override diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java deleted file mode 100644 index 9cfd8bb7442f..000000000000 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.replacements; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.nio.ByteBuffer; - -import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.type.DataPointerConstant; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; - -/** - * Represents an encoded representation of a constant. - */ -public final class EncodedSymbolConstant extends DataPointerConstant { - private final Constant constant; - private byte[] bytes; - - public EncodedSymbolConstant(Constant constant) { - super(1); - this.constant = constant; - } - - @Override - public int getSerializedSize() { - return getEncodedConstant().length; - } - - @Override - public void serialize(ByteBuffer buffer) { - buffer.put(getEncodedConstant()); - } - - /** - * Converts a string to a byte array with modified UTF-8 encoding. The first two bytes of the - * byte array store the length of the string in bytes. - * - * @param s a java.lang.String in UTF-16 - */ - private static byte[] toUTF8String(String s) { - try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) { - DataOutputStream stream = new DataOutputStream(bytes); - stream.writeUTF(s); - return bytes.toByteArray(); - } catch (Exception e) { - throw new PermanentBailoutException(e, "String conversion failed: %s", s); - } - } - - private static byte[] encodeConstant(Constant constant) { - assert constant != null; - if (constant instanceof HotSpotObjectConstant) { - return toUTF8String(((HotSpotObjectConstant) constant).asObject(String.class)); - } else if (constant instanceof HotSpotMetaspaceConstant) { - HotSpotMetaspaceConstant metaspaceConstant = ((HotSpotMetaspaceConstant) constant); - HotSpotResolvedObjectType klass = metaspaceConstant.asResolvedJavaType(); - if (klass != null) { - return toUTF8String(klass.getName()); - } - HotSpotResolvedJavaMethod method = metaspaceConstant.asResolvedJavaMethod(); - if (method != null) { - byte[] methodName = toUTF8String(method.getName()); - byte[] signature = toUTF8String(method.getSignature().toMethodDescriptor()); - byte[] result = new byte[methodName.length + signature.length]; - int resultPos = 0; - System.arraycopy(methodName, 0, result, resultPos, methodName.length); - resultPos += methodName.length; - System.arraycopy(signature, 0, result, resultPos, signature.length); - resultPos += signature.length; - assert resultPos == result.length; - return result; - } - - } - throw new PermanentBailoutException("Encoding of constant %s failed", constant); - } - - public byte[] getEncodedConstant() { - if (bytes == null) { - bytes = encodeConstant(constant); - } - return bytes; - } - - @Override - public String toValueString() { - return "encoded symbol\"" + constant.toValueString() + "\""; - } - -} From 9f2b8c8612618fe2dabe84ad053b9795232d0fe1 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 10:22:52 -0800 Subject: [PATCH 09/18] Rename and simplify StringSubstitutions --- .../test/StringSubstitutionsTest.java | 3 +-- .../StandardGraphBuilderPlugins.java | 22 +------------------ ...tions.java => StringHelperIntrinsics.java} | 19 ++-------------- .../replacements/StringLatin1Snippets.java | 2 +- .../replacements/StringUTF16Snippets.java | 2 +- 5 files changed, 6 insertions(+), 42 deletions(-) rename compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/{StringSubstitutions.java => StringHelperIntrinsics.java} (72%) diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java index 88954ad74d83..b2f5296ec082 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java @@ -26,7 +26,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.replacements.StringSubstitutions; import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; import org.junit.Test; @@ -34,7 +33,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Tests {@link StringSubstitutions}. + * Tests String intrinsics. */ public class StringSubstitutionsTest extends MethodSubstitutionTest { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java index 2cb18ef3f774..d96dcdcd4972 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java @@ -137,7 +137,6 @@ import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; -import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode; import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode; @@ -291,26 +290,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } }); - Registration sr = new Registration(plugins, StringSubstitutions.class); - sr.register(new InlineOnlyInvocationPlugin("getValue", String.class) { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD); - ValueNode object = b.nullCheckedValue(value); - b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), - b.getOptions(), b.getAssumptions(), object, field, false, false)); - return true; - } - }); - sr.register(new InlineOnlyInvocationPlugin("getCoder", String.class) { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_CODER_FIELD); - b.addPush(JavaKind.Int, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), - b.getOptions(), b.getAssumptions(), value, field, false, false)); - return true; - } - }); + Registration sr = new Registration(plugins, StringHelperIntrinsics.class); sr.register(new InlineOnlyInvocationPlugin("getByte", byte[].class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java similarity index 72% rename from compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java rename to compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java index 9c7acd60b5e5..e98e92490ef4 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringSubstitutions.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java @@ -24,26 +24,11 @@ */ package org.graalvm.compiler.replacements; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; -import org.graalvm.compiler.nodes.java.LoadFieldNode; - // JaCoCo Exclude /** - * Substitutions for {@link java.lang.String} methods. + * Intrinsics for use by {@link StringUTF16Snippets} and {@link StringLatin1Snippets}. */ -public class StringSubstitutions { - - /** - * Will be intrinsified with an {@link InvocationPlugin} to a {@link LoadFieldNode}. - */ - public static native byte[] getValue(String s); - +public class StringHelperIntrinsics { public static native byte getByte(byte[] value, int i); - - public static native int getCoder(String s); - - public static boolean isCompactString(String s) { - return getCoder(s) == 0; - } } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java index e5ae07cefa82..c4cf12bac48a 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringLatin1Snippets.java @@ -28,9 +28,9 @@ import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; -import static org.graalvm.compiler.replacements.StringSubstitutions.getByte; import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayIndexScale; +import static org.graalvm.compiler.replacements.StringHelperIntrinsics.getByte; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java index be37283ba4dc..9ff88034982e 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Snippets.java @@ -28,9 +28,9 @@ import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; -import static org.graalvm.compiler.replacements.StringSubstitutions.getByte; import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; +import static org.graalvm.compiler.replacements.StringHelperIntrinsics.getByte; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; From e4b3ad5891ebc49351949dc166507fd17eefcd71 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 10:43:20 -0800 Subject: [PATCH 10/18] Remove UseEncodedGraphs and simplify/sanity check snippet type registration --- .../compiler/core/common/GraalOptions.java | 3 -- .../compiler/hotspot/EncodedSnippets.java | 10 +++-- .../hotspot/HotSpotBackendFactory.java | 2 +- .../hotspot/HotSpotReplacementsImpl.java | 42 +++++++++++++------ .../hotspot/SymbolicSnippetEncoder.java | 23 ++-------- .../meta/HotSpotHostForeignCallsProvider.java | 5 +++ .../hotspot/word/HotSpotWordTypes.java | 8 +++- .../SubstitutionNodeSourcePositionTest.java | 3 -- .../replacements/CachingPEGraphDecoder.java | 3 +- 9 files changed, 53 insertions(+), 46 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 5c0af4300437..88a9396d7940 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -266,9 +266,6 @@ public final class GraalOptions { @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.", type = OptionType.Expert) public static final OptionKey UseGraalStubs = new OptionKey<>(true); - @Option(help = "Encode and decode snippets and substitutions before parsing to test libgraal code path. This option is ignored in the context of libgraal.") - public static final OptionKey UseEncodedGraphs = new OptionKey<>(false); - @Option(help = "If applicable, use bulk zeroing instructions when the zeroing size in bytes exceeds this threshold.", type = OptionType.Expert) public static final OptionKey MinimalBulkZeroingSize = new OptionKey<>(2048); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java index 3dca6ebb3842..e6d1a2a28b5e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java @@ -26,7 +26,7 @@ import static jdk.vm.ci.runtime.JVMCI.getRuntime; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; +import static org.graalvm.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.util.Map; @@ -174,7 +174,11 @@ public NodeClass[] getSnippetNodeClasses() { } ResolvedJavaType lookupSnippetType(Class clazz) { - return snippetTypes.get(clazz); + SnippetResolvedJavaType type = snippetTypes.get(clazz); + if (type == null && isGraalClass(clazz)) { + throw new GraalError("Missing graal class " + clazz); + } + return type; } public void visitImmutable(Consumer visitor) { @@ -282,7 +286,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.snippetReflection; - if (IS_IN_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + if (IS_IN_NATIVE_IMAGE) { snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); } parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java index 5c0fd2b74ba6..8c4ddc97cd3d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java @@ -179,7 +179,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, snippetReflection, bytecodeProvider); providers = replacements.getProviders(); - replacements.maybeInitializeEncoder(options); + replacements.maybeInitializeEncoder(); } GraphBuilderConfiguration.Plugins plugins; try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index 6ff30bb06ded..f39a3ed84d73 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -26,7 +26,6 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import java.util.BitSet; @@ -52,7 +51,9 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Filters certain method substitutions based on whether there is underlying hardware support for @@ -73,16 +74,13 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } - public void maybeInitializeEncoder(OptionValues options) { + public void maybeInitializeEncoder() { if (IS_IN_NATIVE_IMAGE) { return; } - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { - synchronized (HotSpotReplacementsImpl.class) { - if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this); - } - } + if (IS_BUILDING_NATIVE_IMAGE) { + assert snippetEncoder == null; + snippetEncoder = new SymbolicSnippetEncoder(this); } } @@ -130,7 +128,7 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin if (!IS_IN_NATIVE_IMAGE) { assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { - if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + if (IS_BUILDING_NATIVE_IMAGE) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); } } @@ -196,7 +194,7 @@ public boolean encode(OptionValues options) { @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (IS_IN_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { + if (IS_IN_NATIVE_IMAGE) { maybeEncodeSnippets(options); // Snippets graphs can contain foreign object references and @@ -224,16 +222,34 @@ public T getInjectedArgument(Class capability) { } public ResolvedJavaMethod findSnippetMethod(ResolvedJavaMethod thisMethod) { - if (!IS_IN_NATIVE_IMAGE && snippetEncoder != null) { + if (IS_BUILDING_NATIVE_IMAGE && !IS_IN_NATIVE_IMAGE) { + if (snippetEncoder == null) { + throw new GraalError("findSnippetMethod called before initialization of Replacements"); + } return snippetEncoder.findSnippetMethod(thisMethod); } return null; } public static MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { - if (!IS_IN_NATIVE_IMAGE && snippetEncoder != null) { - return snippetEncoder.noticeTypes(metaAccess); + if (IS_BUILDING_NATIVE_IMAGE && !IS_IN_NATIVE_IMAGE) { + return SymbolicSnippetEncoder.noticeTypes(metaAccess); } return metaAccess; } + + static boolean isGraalClass(ResolvedJavaType type) { + return isGraalClass(MetaUtil.internalNameToJava(type.getName(), true, true)); + } + + static boolean isGraalClass(Class clazz) { + return isGraalClass(clazz.getName()); + } + + static boolean isGraalClass(String className) { + return className.contains("jdk.vm.ci") || + className.contains("org.graalvm.") || + className.contains("com.oracle.graal") || + className.contains("com.oracle.truffle"); + } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 18178ad11af5..810228d614af 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.EncodedSnippets.methodKey; +import static org.graalvm.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import java.lang.reflect.Executable; @@ -125,7 +126,6 @@ import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MemoryAccessProvider; import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.MethodHandleAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -139,8 +139,8 @@ * method references into a symbolic form that can be resolved at graph decode time using * {@link SymbolicJVMCIReference}. * - * This class only exists when {@link jdk.vm.ci.services.Services#IS_BUILDING_NATIVE_IMAGE} is true - * or the option {@link org.graalvm.compiler.core.common.GraalOptions#UseEncodedGraphs} is enabled. + * An instance of this class only exist when + * {@link jdk.vm.ci.services.Services#IS_BUILDING_NATIVE_IMAGE} is true. */ public class SymbolicSnippetEncoder { @@ -1052,21 +1052,6 @@ protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, Valu } } - private static boolean isGraalClass(ResolvedJavaType type) { - return isGraalClass(MetaUtil.internalNameToJava(type.getName(), true, true)); - } - - private static boolean isGraalClass(Class clazz) { - return isGraalClass(clazz.getName()); - } - - private static boolean isGraalClass(String className) { - return className.contains("jdk.vm.ci") || - className.contains("org.graalvm.") || - className.contains("com.oracle.graal") || - className.contains("com.oracle.truffle"); - } - private static final Map, SnippetResolvedJavaType> snippetTypes = new HashMap<>(); private static synchronized SnippetResolvedJavaType lookupSnippetType(Class clazz) { @@ -1182,7 +1167,7 @@ public int getArrayIndexScale(JavaKind elementKind) { * Returns a proxy {@link MetaAccessProvider} that can log types which are looked up during * normal processing. This is used to ensure that types needed for libgraal are available. */ - public MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { + public static MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { return new MetaAccessProviderDelegate(metaAccess); } } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 3c52660b0349..4d62cb7f48bc 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.meta; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; +import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; import static org.graalvm.compiler.hotspot.HotSpotBackend.AESCRYPT_DECRYPTBLOCK; @@ -276,6 +277,10 @@ private boolean registerStubCallFunctions(OptionValues options, HotSpotProviders if (config.invokeJavaMethodAddress == 0) { return true; } + if (IS_IN_NATIVE_IMAGE) { + // These helpers are only used for testing the jargraal + return true; + } ResolvedJavaMethod booleanReturnsBoolean = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), TestForeignCalls.class, "booleanReturnsBoolean"); invokeJavaMethodStub(options, providers, TestForeignCalls.BOOLEAN_RETURNS_BOOLEAN, config.invokeJavaMethodAddress, booleanReturnsBoolean); ResolvedJavaMethod byteReturnsByte = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), TestForeignCalls.class, "byteReturnsByte"); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/HotSpotWordTypes.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/HotSpotWordTypes.java index 8819823c3aa1..229c89aefec2 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/HotSpotWordTypes.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/HotSpotWordTypes.java @@ -74,6 +74,11 @@ public HotSpotWordTypes(MetaAccessProvider metaAccess, JavaKind wordKind) { this.methodPointerType = metaAccess.lookupJavaType(MethodPointer.class); this.methodCountersPointerType = metaAccess.lookupJavaType(MethodCountersPointer.class); this.methodCountersPointerClass = MethodCountersPointer.class; + // These assertion sanity check that the underlying types were properly resolved + // in the context of libgraal where these should actually be SnippetResolvedJavaTypes + assert metaspacePointerType.isAssignableFrom(klassPointerType); + assert metaspacePointerType.isAssignableFrom(methodPointerType); + assert metaspacePointerType.isAssignableFrom(methodCountersPointerType); } @Override @@ -81,7 +86,6 @@ public boolean isWord(JavaType type) { if (type instanceof ResolvedJavaType && metaspacePointerType.isAssignableFrom((ResolvedJavaType) type)) { return true; } - assert type == null || !type.getName().equals("Lorg/graalvm/compiler/hotspot/word/KlassPointer;") : type.getClass() + " " + klassPointerType.getClass() + " " + type + " " + klassPointerType; return super.isWord(type); } @@ -95,7 +99,7 @@ public boolean isWord(Class clazz) { @Override public JavaKind asKind(JavaType type) { - if (klassPointerType.equals(type) || methodPointerType.equals(type)) { + if (type instanceof ResolvedJavaType && metaspacePointerType.isAssignableFrom((ResolvedJavaType) type)) { return getWordKind(); } return super.asKind(type); diff --git a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java index d8ff66f005a5..dba3abfb3792 100644 --- a/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java +++ b/compiler/src/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionNodeSourcePositionTest.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeSourcePosition; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import java.util.List; @@ -39,7 +38,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.junit.Assert; -import org.junit.Assume; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -70,7 +68,6 @@ public void testSnippetLowering() { // // The precise snippet bytecodes don't matter, just ensure that some actually appear after // lowering. - Assume.assumeFalse(UseEncodedGraphs.getValue(getInitialOptions())); checkMappings("snippetLowering", true, SubstitutionNodeSourcePositionTest.class, "snippetLowering"); } diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java index de06ed310c1a..c94bc14ea851 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.replacements; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static org.graalvm.compiler.core.common.GraalOptions.UseEncodedGraphs; import java.util.concurrent.ConcurrentHashMap; @@ -97,7 +96,7 @@ protected GraphBuilderPhase.Instance createGraphBuilderPhaseInstance(IntrinsicCo @SuppressWarnings("try") private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) { StructuredGraph graphToEncode; - if (isSubstitution && (UseEncodedGraphs.getValue(options) || IS_IN_NATIVE_IMAGE)) { + if (isSubstitution && IS_IN_NATIVE_IMAGE) { throw GraalError.shouldNotReachHere("dead path"); } else { graphToEncode = buildGraph(method, intrinsicBytecodeProvider, isSubstitution); From 3e0acfa129fa7ab8e15598a414ea2aaa7cf8365e Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 11:09:40 -0800 Subject: [PATCH 11/18] Remove ROOT_COMPILATION and ROOT_COMPILATION_ENCODING --- .../graalvm/compiler/java/BytecodeParser.java | 76 +++++++------------ .../graphbuilderconf/IntrinsicContext.java | 23 +----- 2 files changed, 28 insertions(+), 71 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index d7bf1a3faafd..49f181d7cf47 100644 --- a/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/compiler/src/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -567,24 +567,21 @@ static class InliningScope implements AutoCloseable { @Override public void close() { - processPlaceholderFrameStates(false); + processPlaceholderFrameStates(); } /** * Fixes up the {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frame states * added to the graph while parsing/inlining the intrinsic for which this object exists. */ - protected void processPlaceholderFrameStates(boolean isCompilationRoot) { + protected void processPlaceholderFrameStates() { StructuredGraph graph = parser.getGraph(); graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method); for (FrameState frameState : graph.getNewNodes(mark).filter(FrameState.class)) { if (BytecodeFrame.isPlaceholderBci(frameState.bci)) { if (frameState.bci == BytecodeFrame.AFTER_BCI) { if (parser.getInvokeReturnType() == null) { - // A frame state in a root compiled intrinsic. - assert isCompilationRoot; - FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - frameState.replaceAndDelete(newFrameState); + throw GraalError.shouldNotReachHere("unhandled intrinsic path"); } else { JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); FrameStateBuilder frameStateBuilder = parser.frameState; @@ -684,16 +681,10 @@ static class IntrinsicScope extends InliningScope { @Override public void close() { IntrinsicContext intrinsic = parser.intrinsicContext; - boolean isRootCompilation; - if (intrinsic != null) { - if (intrinsic.isPostParseInlined()) { - return; - } - isRootCompilation = intrinsic.isCompilationRoot(); - } else { - isRootCompilation = false; + if (intrinsic != null && intrinsic.isPostParseInlined()) { + return; } - processPlaceholderFrameStates(isRootCompilation); + processPlaceholderFrameStates(); if (invalidStateUsers != null) { JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); ValueNode returnValue = parser.frameState.pop(returnKind); @@ -754,7 +745,7 @@ public void close() { * * See ByteCodeParser::inline and search for compilationRoot */ - assert intrinsic == null || intrinsic.isIntrinsicEncoding() || verifyIntrinsicRootCompileEffects(); + assert intrinsic == null || verifyIntrinsicRootCompileEffects(); } } @@ -2393,44 +2384,31 @@ private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlin boolean logInliningDecision = logInliningInvokable != null; if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) { - if (intrinsic.isCompilationRoot()) { - // A root compiled intrinsic needs to deoptimize - // if the slow path is taken. During frame state - // assignment, the deopt node will get its stateBefore - // from the start node of the intrinsic - append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint)); - printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)"); + if (intrinsic.getOriginalMethod().isNative()) { + printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)"); + if (logInliningDecision) { + graph.getInliningLog().addDecision(logInliningInvokable, false, "GraphBuilderPhase", null, null, "native method"); + } + return false; + } + if (canInlinePartialIntrinsicExit()) { + // Otherwise inline the original method. Any frame state created + // during the inlining will exclude frame(s) in the + // intrinsic method (see FrameStateBuilder.create(int bci)). + notifyBeforeInline(inlinedMethod); + printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)"); if (logInliningDecision) { - graph.getInliningLog().addDecision(logInliningInvokable, true, "GraphBuilderPhase", null, null, "compilation root"); + graph.getInliningLog().addDecision(logInliningInvokable, true, "GraphBuilderPhase", null, null, "partial intrinsic exit"); } + parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null); + notifyAfterInline(inlinedMethod); return true; } else { - if (intrinsic.getOriginalMethod().isNative()) { - printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)"); - if (logInliningDecision) { - graph.getInliningLog().addDecision(logInliningInvokable, false, "GraphBuilderPhase", null, null, "native method"); - } - return false; - } - if (canInlinePartialIntrinsicExit()) { - // Otherwise inline the original method. Any frame state created - // during the inlining will exclude frame(s) in the - // intrinsic method (see FrameStateBuilder.create(int bci)). - notifyBeforeInline(inlinedMethod); - printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)"); - if (logInliningDecision) { - graph.getInliningLog().addDecision(logInliningInvokable, true, "GraphBuilderPhase", null, null, "partial intrinsic exit"); - } - parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null); - notifyAfterInline(inlinedMethod); - return true; - } else { - printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)"); - if (logInliningDecision) { - graph.getInliningLog().addDecision(logInliningInvokable, false, "GraphBuilderPhase", null, null, "partial intrinsic exit"); - } - return false; + printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)"); + if (logInliningDecision) { + graph.getInliningLog().addDecision(logInliningInvokable, false, "GraphBuilderPhase", null, null, "partial intrinsic exit"); } + return false; } } else { boolean isIntrinsic = intrinsicBytecodeProvider != null; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java index 163d873b587b..680fecd3ae93 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java @@ -29,8 +29,6 @@ import static jdk.vm.ci.code.BytecodeFrame.BEFORE_BCI; import static jdk.vm.ci.code.BytecodeFrame.INVALID_FRAMESTATE_BCI; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; -import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.graph.NodeSourcePosition; @@ -86,7 +84,6 @@ public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, assert bytecodeProvider != null; this.compilationContext = compilationContext; this.allowPartialIntrinsicArgumentMismatch = allowPartialIntrinsicArgumentMismatch; - assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)"); } /** @@ -134,14 +131,6 @@ public boolean isPostParseInlined() { return compilationContext.equals(INLINE_AFTER_PARSING); } - public boolean isCompilationRoot() { - return compilationContext.equals(ROOT_COMPILATION) || compilationContext.equals(ROOT_COMPILATION_ENCODING); - } - - public boolean isIntrinsicEncoding() { - return compilationContext.equals(ROOT_COMPILATION_ENCODING); - } - public NodeSourcePosition getNodeSourcePosition() { return nodeSourcePosition; } @@ -164,17 +153,7 @@ public enum CompilationContext { /** * An intrinsic is being processed when inlining an {@link Invoke} in an existing graph. */ - INLINE_AFTER_PARSING, - - /** - * An intrinsic is the root of compilation. - */ - ROOT_COMPILATION, - - /** - * An intrinsic is the root of a compilation done for graph encoding. - */ - ROOT_COMPILATION_ENCODING + INLINE_AFTER_PARSING } /** From 8b49dd67aaa6ca2c49384c7d1fb04ff5149c8b17 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 23:01:35 -0800 Subject: [PATCH 12/18] Restore truffle initialization in LibgraalFeature --- .../compiler/hotspot/HotSpotReplacementsImpl.java | 11 +++++++++-- .../compiler/hotspot/SymbolicSnippetEncoder.java | 4 ++++ .../svm/graal/hotspot/libgraal/LibGraalFeature.java | 10 ++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index f39a3ed84d73..3e9afab665e8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -79,8 +79,11 @@ public void maybeInitializeEncoder() { return; } if (IS_BUILDING_NATIVE_IMAGE) { - assert snippetEncoder == null; - snippetEncoder = new SymbolicSnippetEncoder(this); + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); + } + } } } @@ -163,6 +166,10 @@ public static EncodedSnippets getEncodedSnippets() { return encodedSnippets; } + public static boolean snippetsAreEncoded() { + return encodedSnippets != null; + } + public static void maybeEncodeSnippets(OptionValues options) { if (!IS_IN_NATIVE_IMAGE && snippetEncoder != null) { snippetEncoder.encode(options); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index 810228d614af..be97073e725e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -436,6 +436,10 @@ private synchronized EncodedSnippets encodeSnippets(OptionValues options) { } synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { + if (HotSpotReplacementsImpl.snippetsAreEncoded()) { + throw new GraalError("Snippet encoding has already been done"); + } + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); SnippetKey key = new SnippetKey(method, original, receiver); findSnippetMethod(method); 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 4ee075cccf37..59abf4b4d88f 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 @@ -56,6 +56,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.GraalServiceThread; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -89,6 +90,7 @@ import org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentationFactory; import org.graalvm.compiler.truffle.compiler.substitutions.GraphBuilderInvocationPluginProvider; import org.graalvm.compiler.truffle.compiler.substitutions.GraphDecoderInvocationPluginProvider; +import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.jniutils.JNI; import org.graalvm.jniutils.JNIExceptionWrapper; import org.graalvm.jniutils.JNIMethodScope; @@ -419,6 +421,7 @@ public void registerLowerings(RuntimeConfiguration runtimeConfig, OptionValues o @Override public void beforeAnalysis(BeforeAnalysisAccess access) { FeatureImpl.BeforeAnalysisAccessImpl impl = (FeatureImpl.BeforeAnalysisAccessImpl) access; + DebugContext debug = impl.getBigBang().getDebug(); // Services that will not be loaded if native-image is run // with -XX:-UseJVMCICompiler. @@ -430,6 +433,13 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { GraalServices.load(HotSpotMBeanOperationProvider.class); GraalServices.load(DisassemblerProvider.class); + try (DebugContext.Scope scope = debug.scope("SnippetSupportEncode")) { + // Instantiate the truffle compiler ensure the backends it uses are initialized. + GraalTruffleRuntime.getRuntime().newTruffleCompiler(); + } catch (Throwable t) { + throw debug.handle(t); + } + // Filter out any cached services which are for a different architecture try { HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); From 4ad80f4eb2c0eb89000dd46b1e9367d939c48459 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 10 Feb 2022 23:05:14 -0800 Subject: [PATCH 13/18] Add comment --- .../graalvm/compiler/replacements/StringHelperIntrinsics.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java index e98e92490ef4..c39ed7e9cfb9 100644 --- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java +++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringHelperIntrinsics.java @@ -30,5 +30,8 @@ * Intrinsics for use by {@link StringUTF16Snippets} and {@link StringLatin1Snippets}. */ public class StringHelperIntrinsics { + /** + * Emits a array access without a bounds check. + */ public static native byte getByte(byte[] value, int i); } From 9ec69dd4c322787241831595d18aa5d64878cbd0 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 11 Feb 2022 11:09:07 -0800 Subject: [PATCH 14/18] Ensure InvokeJavaMethodStub is included in libgraal --- .../meta/HotSpotHostForeignCallsProvider.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 4d62cb7f48bc..540a46fcdd6a 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -273,14 +273,14 @@ public ForeignCallDescriptor lookupArraycopyDescriptor(JavaKind kind, boolean al } } - private boolean registerStubCallFunctions(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { - if (config.invokeJavaMethodAddress == 0) { - return true; - } - if (IS_IN_NATIVE_IMAGE) { - // These helpers are only used for testing the jargraal - return true; + private void registerStubCallFunctions(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + if (config.invokeJavaMethodAddress == 0 || IS_IN_NATIVE_IMAGE) { + return; } + // These functions are only used for testing purposes but their registration also ensures + // that libgraal has support for InvokeJavaMethodStub built into the image, which is + // required for support of Truffle. Because of the lazy initialization of this support in + // Truffle we rely on this code to ensure the support is built into the image. ResolvedJavaMethod booleanReturnsBoolean = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), TestForeignCalls.class, "booleanReturnsBoolean"); invokeJavaMethodStub(options, providers, TestForeignCalls.BOOLEAN_RETURNS_BOOLEAN, config.invokeJavaMethodAddress, booleanReturnsBoolean); ResolvedJavaMethod byteReturnsByte = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), TestForeignCalls.class, "byteReturnsByte"); @@ -295,8 +295,6 @@ private boolean registerStubCallFunctions(OptionValues options, HotSpotProviders invokeJavaMethodStub(options, providers, TestForeignCalls.LONG_RETURNS_LONG, config.invokeJavaMethodAddress, longReturnsLong); ResolvedJavaMethod objectReturnsObject = SnippetTemplate.AbstractTemplates.findMethod(providers.getMetaAccess(), TestForeignCalls.class, "objectReturnsObject"); invokeJavaMethodStub(options, providers, TestForeignCalls.OBJECT_RETURNS_OBJECT, config.invokeJavaMethodAddress, objectReturnsObject); - - return true; } private void registerArraycopyDescriptor(EconomicMap descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, LocationIdentity killedLocation, @@ -568,7 +566,7 @@ public void initialize(HotSpotProviders providers, OptionValues options) { registerForeignCall(VECTORIZED_MISMATCH, c.vectorizedMismatch, NativeCall); } - assert registerStubCallFunctions(options, providers, runtime.getVMConfig()); + registerStubCallFunctions(options, providers, runtime.getVMConfig()); } @SuppressWarnings("unused") From 7543655dec534fa401750bb643bd968a64471665 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 11 Feb 2022 12:05:37 -0800 Subject: [PATCH 15/18] Flatten SnippetKey inheritance --- .../hotspot/SymbolicSnippetEncoder.java | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index be97073e725e..b07a1faf7a5b 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -152,26 +152,15 @@ public class SymbolicSnippetEncoder { private final HotSpotReplacementsImpl originalReplacements; - abstract static class GraphKey { + static class SnippetKey { + final ResolvedJavaMethod method; final ResolvedJavaMethod original; - - GraphKey(ResolvedJavaMethod method, ResolvedJavaMethod original) { - this.method = method; - this.original = original; - } - - public abstract String keyString(); - - public abstract Class receiverClass(); - } - - static class SnippetKey extends GraphKey { - private final Class receiverClass; SnippetKey(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver) { - super(method, original); + this.method = method; + this.original = original; assert method.isStatic() == (receiver == null) : "static must not have receiver and non-static must"; this.receiverClass = receiver != null ? receiver.getClass() : null; } @@ -193,12 +182,10 @@ public int hashCode() { return Objects.hash(method, original, receiverClass); } - @Override public String keyString() { return methodKey(method); } - @Override public Class receiverClass() { return receiverClass; } @@ -213,7 +200,7 @@ public String toString() { } } - private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); + private final EconomicMap> pendingSnippetGraphs = EconomicMap.create(); private final EconomicMap snippetParameterInfos = EconomicMap.create(); @@ -417,10 +404,10 @@ private synchronized EncodedSnippets encodeSnippets(OptionValues options) { copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); copy.appendNodePlugin(new SnippetCounterPlugin(snippetReplacements)); - EconomicMap preparedSnippetGraphs = EconomicMap.create(); - MapCursor> cursor = pendingSnippetGraphs.getEntries(); + EconomicMap preparedSnippetGraphs = EconomicMap.create(); + MapCursor> cursor = pendingSnippetGraphs.getEntries(); while (cursor.advance()) { - GraphKey key = cursor.getKey(); + SnippetKey key = cursor.getKey(); preparedSnippetGraphs.put(key, cursor.getValue().apply(options, snippetReplacements)); } @@ -524,7 +511,7 @@ private boolean verifySingle(DebugContext debug, StructuredGraph graph) { } } - private synchronized EncodedSnippets encodeSnippets(DebugContext debug, EconomicMap preparedSnippetGraphs) { + private synchronized EncodedSnippets encodeSnippets(DebugContext debug, EconomicMap preparedSnippetGraphs) { GraphEncoder encoder = new GraphEncoder(HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch, debug); for (StructuredGraph graph : preparedSnippetGraphs.getValues()) { graph.resetDebug(debug); @@ -534,9 +521,9 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic encoder.finishPrepare(); EconomicMap graphDatas = EconomicMap.create(); - MapCursor cursor = preparedSnippetGraphs.getEntries(); + MapCursor cursor = preparedSnippetGraphs.getEntries(); while (cursor.advance()) { - GraphKey key = cursor.getKey(); + SnippetKey key = cursor.getKey(); String keyString = key.keyString(); GraphData previous = graphDatas.get(keyString); GraphData data = GraphData.create(encoder.encode(cursor.getValue()), originalMethods.get(keyString), snippetParameterInfos.get(keyString), key.receiverClass(), previous); From 14b21cac882e4806de2bcac26e2019b170edf888 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 11 Feb 2022 12:06:03 -0800 Subject: [PATCH 16/18] Add LibGraal scope around snippet graph preparation --- .../hotspot/SymbolicSnippetEncoder.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index b07a1faf7a5b..db4fe535f9d8 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -288,26 +288,27 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod args = new Object[method.getSignature().getParameterCount(true)]; args[0] = receiver; } - // To get dumping out from this context during image building, it's necessary to pass the - // dumping options directly to the VM, otherwise they aren't available during initialization - // of the backend. Use this: - // - // -J-Dgraal.Dump=SymbolicSnippetEncoder_:2 -J-Dgraal.PrintGraph=File - // -J-Dgraal.DebugStubsAndSnippets=true + // Dumps of the graph preparation step can be captured with -H:Dump=LibGraal:2 and + // MethodFilter can be used to focus on particular snippets. IntrinsicContext.CompilationContext contextToUse = IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; try (DebugContext debug = snippetReplacements.openDebugContext("LibGraalBuildGraph_", method, options)) { - StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, nonNullParameters, original, - trackNodeSourcePosition, null, contextToUse); - - // Check if all methods which should be inlined are really inlined. - for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { - ResolvedJavaMethod callee = callTarget.targetMethod(); - if (!delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original) && !Objects.equals(callee, method)) { - throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); + StructuredGraph graph; + try (DebugContext.Scope s = debug.scope("LibGraal", method)) { + graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, nonNullParameters, original, + trackNodeSourcePosition, null, contextToUse); + + // Check if all methods which should be inlined are really inlined. + for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { + ResolvedJavaMethod callee = callTarget.targetMethod(); + if (!delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original) && !Objects.equals(callee, method)) { + throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); + } } + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); + } catch (Throwable e) { + throw debug.handle(e); } assert verifySnippetEncodeDecode(debug, method, original, args, trackNodeSourcePosition, graph); - debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); assert graph.getAssumptions() == null : graph; return graph; } From 3e7b4fe5e18d75bc1547870333c256b94ec65681 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 11 Feb 2022 12:46:42 -0800 Subject: [PATCH 17/18] Increase timeout for gate-vm-ce-polybench-linux-amd64 --- vm/ci_common/common-bench.jsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/ci_common/common-bench.jsonnet b/vm/ci_common/common-bench.jsonnet index 5ab67d99762c..8eb2d66b8b07 100644 --- a/vm/ci_common/common-bench.jsonnet +++ b/vm/ci_common/common-bench.jsonnet @@ -110,7 +110,7 @@ local vm_common = import '../ci_common/common.jsonnet'; self.compiler_bench_cmd + ['--polybench-vm-config=native-standard', '--metric=partial-evaluation-time'], self.warmup_bench_cmd + ['--polybench-vm-config=native-standard', '--metric=one-shot'], ], - timelimit: '1:00:00', + timelimit: '1:30:00', notify_emails: [], }, From 604d98eabb00d574138a5cc1b4a0f9f60355b2ca Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sun, 13 Feb 2022 12:44:59 -0800 Subject: [PATCH 18/18] Cleanups --- .../graalvm/compiler/hotspot/HotSpotReplacementsImpl.java | 8 -------- .../graalvm/compiler/hotspot/SymbolicSnippetEncoder.java | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index 3e9afab665e8..ed53d4845446 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -170,12 +170,6 @@ public static boolean snippetsAreEncoded() { return encodedSnippets != null; } - public static void maybeEncodeSnippets(OptionValues options) { - if (!IS_IN_NATIVE_IMAGE && snippetEncoder != null) { - snippetEncoder.encode(options); - } - } - public void clearSnippetParameterNames() { assert snippetEncoder != null; snippetEncoder.clearSnippetParameterNames(); @@ -202,8 +196,6 @@ public boolean encode(OptionValues options) { public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { if (IS_IN_NATIVE_IMAGE) { - maybeEncodeSnippets(options); - // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index db4fe535f9d8..4cdb899eb66d 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -280,6 +280,7 @@ synchronized void registerConditionalPlugin(InvocationPlugin plugin) { conditionalPlugins.add(plugin); } + @SuppressWarnings("try") private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, BitSet nonNullParameters, boolean trackNodeSourcePosition, OptionValues options, ReplacementsImpl snippetReplacements) { assert method.hasBytecodes() : "Snippet must not be abstract or native";