diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisGraphDecoder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisGraphDecoder.java index 86c87c5b4dd7..4c33c88bb6c0 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisGraphDecoder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisGraphDecoder.java @@ -37,7 +37,6 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.graal.pointsto.phases.InlineBeforeAnalysisPolicy.AbstractPolicyScope; -import com.oracle.graal.pointsto.util.AnalysisError; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.debug.GraalError; @@ -163,7 +162,7 @@ protected void cleanupGraph(MethodScope ms) { super.cleanupGraph(ms); // at the very end we record all inlining - var methodScope = cast(ms); + InlineBeforeAnalysisMethodScope methodScope = cast(ms); methodScope.encodedGraphs.add(methodScope.encodedGraph); for (var encodedGraph : methodScope.encodedGraphs) { super.recordGraphElements(encodedGraph); @@ -318,7 +317,6 @@ protected void finishInlining(MethodScope is) { if (graph.getDebug().isLogEnabled()) { graph.getDebug().logv(" ".repeat(callerScope.inliningDepth) + " aborted " + invokeData.callTarget.targetMethod().format("%H.%n(%p)") + ": " + inlineScope.policyScope); } - AnalysisError.guarantee(inlineScope.policyScope.allowAbort(), "Unexpected abort: %s", inlineScope); if (callerScope.policyScope != null) { callerScope.policyScope.abortCalleeScope(inlineScope.policyScope); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisPolicy.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisPolicy.java index 4d17a00af129..fed6b6483af9 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisPolicy.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/phases/InlineBeforeAnalysisPolicy.java @@ -63,8 +63,6 @@ protected AbstractPolicyScope(int inliningDepth) { this.inliningDepth = inliningDepth; } - public abstract boolean allowAbort(); - public abstract void commitCalleeScope(AbstractPolicyScope callee); public abstract void abortCalleeScope(AbstractPolicyScope callee); @@ -104,9 +102,7 @@ protected InlineBeforeAnalysisPolicy(NodePlugin[] nodePlugins) { protected abstract AbstractPolicyScope openCalleeScope(AbstractPolicyScope outer, AnalysisMethod method); /** @see InlineBeforeAnalysisGraphDecoder#shouldOmitIntermediateMethodInStates */ - protected boolean shouldOmitIntermediateMethodInState(AnalysisMethod method) { - return false; - } + protected abstract boolean shouldOmitIntermediateMethodInState(AnalysisMethod method); public static final InlineBeforeAnalysisPolicy NO_INLINING = new InlineBeforeAnalysisPolicy(new NodePlugin[0]) { @@ -149,5 +145,10 @@ protected AbstractPolicyScope createRootScope() { protected AbstractPolicyScope openCalleeScope(AbstractPolicyScope outer, AnalysisMethod method) { throw AnalysisError.shouldNotReachHere("NO_INLINING policy should not try to inline"); } + + @Override + protected boolean shouldOmitIntermediateMethodInState(AnalysisMethod method) { + return false; + } }; } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java index 9be4c2d93382..8a8f83b99d82 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java @@ -44,7 +44,6 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import org.graalvm.nativeimage.AnnotationAccess; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -125,10 +124,12 @@ import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.Indent; +import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.lir.phases.LIRSuites; import jdk.graal.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; +import jdk.graal.compiler.nodes.CallTargetNode; import jdk.graal.compiler.nodes.FixedWithNextNode; import jdk.graal.compiler.nodes.GraphEncoder; import jdk.graal.compiler.nodes.StructuredGraph; @@ -138,6 +139,7 @@ import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import jdk.graal.compiler.nodes.graphbuilderconf.NodePlugin; +import jdk.graal.compiler.nodes.spi.CoreProviders; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionStability; import jdk.graal.compiler.phases.OptimisticOptimizations; @@ -174,7 +176,7 @@ public static class Options { @Option(help = "Enforce checking of maximum number of methods allowed for runtime compilation. Useful for checking in the gate that the number of methods does not go up without a good reason.")// public static final HostedOptionKey EnforceMaxRuntimeCompileMethods = new HostedOptionKey<>(false); - @Option(help = "Perform InlineBeforeAnalysis on runtime compiled methods")// + @Option(help = "Deprecated, option no longer has any effect.", deprecated = true, deprecationMessage = "It no longer has any effect, and no replacement is available")// public static final HostedOptionKey RuntimeCompilationInlineBeforeAnalysis = new HostedOptionKey<>(true); } @@ -693,11 +695,6 @@ private Object parseRuntimeCompiledMethod(BigBang bb, DebugContext debug, Analys } new ConvertDeoptimizeToGuardPhase(canonicalizer).apply(graph, analysisProviders); - if (DeoptimizationUtils.createGraphInvalidator(graph).get()) { - recordFailed(method); - return HostVM.PARSING_FAILED; - } - } catch (Throwable ex) { debug.handle(ex); } @@ -714,16 +711,16 @@ private void recordFailed(AnalysisMethod method) { public boolean validateGraph(PointsToAnalysis bb, StructuredGraph graph) { PointsToAnalysisMethod aMethod = (PointsToAnalysisMethod) graph.method(); MultiMethod.MultiMethodKey multiMethodKey = aMethod.getMultiMethodKey(); - Supplier graphInvalidator = DeoptimizationUtils.createGraphInvalidator(graph); - if (aMethod.isOriginalMethod() && DeoptimizationUtils.canDeoptForTesting(aMethod, false, graphInvalidator)) { - DeoptimizationUtils.registerDeoptEntriesForDeoptTesting(bb, graph, aMethod); - return true; - } + Supplier graphChecker = DeoptimizationUtils.createGraphChecker(graph, + multiMethodKey == RUNTIME_COMPILED_METHOD ? DeoptimizationUtils.RUNTIME_COMPILATION_INVALID_NODES : DeoptimizationUtils.AOT_COMPILATION_INVALID_NODES); if (multiMethodKey != ORIGINAL_METHOD) { - if (graphInvalidator.get()) { + if (!graphChecker.get()) { recordFailed(aMethod); return false; } + } else if (DeoptimizationUtils.canDeoptForTesting(aMethod, false, graphChecker)) { + DeoptimizationUtils.registerDeoptEntriesForDeoptTesting(bb, graph, aMethod); + return true; } if (multiMethodKey == RUNTIME_COMPILED_METHOD) { /* @@ -770,10 +767,8 @@ public void afterParsingHook(AnalysisMethod method, StructuredGraph graph) { @Override public void initializeInlineBeforeAnalysisPolicy(SVMHost svmHost, InlineBeforeAnalysisPolicyUtils inliningUtils) { - if (RuntimeCompilationFeature.Options.RuntimeCompilationInlineBeforeAnalysis.getValue()) { - assert runtimeInlineBeforeAnalysisPolicy == null; - runtimeInlineBeforeAnalysisPolicy = new RuntimeCompilationInlineBeforeAnalysisPolicy(svmHost, inliningUtils); - } + assert runtimeInlineBeforeAnalysisPolicy == null : runtimeInlineBeforeAnalysisPolicy; + runtimeInlineBeforeAnalysisPolicy = new RuntimeCompilationInlineBeforeAnalysisPolicy(svmHost, inliningUtils); } @Override @@ -783,11 +778,8 @@ public InlineBeforeAnalysisPolicy inlineBeforeAnalysisPolicy(MultiMethod.MultiMe } else if (multiMethodKey == DEOPT_TARGET_METHOD) { return InlineBeforeAnalysisPolicy.NO_INLINING; } else if (multiMethodKey == RUNTIME_COMPILED_METHOD) { - if (RuntimeCompilationFeature.Options.RuntimeCompilationInlineBeforeAnalysis.getValue()) { - assert runtimeInlineBeforeAnalysisPolicy != null; - return runtimeInlineBeforeAnalysisPolicy; - } - return InlineBeforeAnalysisPolicy.NO_INLINING; + assert runtimeInlineBeforeAnalysisPolicy != null; + return runtimeInlineBeforeAnalysisPolicy; } else { throw VMError.shouldNotReachHere("Unexpected method key: %s", multiMethodKey); } @@ -843,9 +835,19 @@ protected boolean needsExplicitExceptions() { return false; } + @Override + protected boolean shouldOmitIntermediateMethodInState(AnalysisMethod method) { + /* + * We don't want to miss any FrameStates within runtime compiled methods since they are + * needed in case a deoptimization occurs. + */ + return false; + } + @Override protected FixedWithNextNode processInvokeArgs(AnalysisMethod targetMethod, FixedWithNextNode insertionPoint, ValueNode[] arguments, NodeSourcePosition sourcePosition) { StructuredGraph graph = insertionPoint.graph(); + assert SubstrateCompilationDirectives.isRuntimeCompiledMethod(targetMethod) : targetMethod; InlinedInvokeArgumentsNode newNode = graph.add(new InlinedInvokeArgumentsNode(targetMethod, arguments)); newNode.setNodeSourcePosition(sourcePosition); graph.addAfterFixed(insertionPoint, newNode); @@ -859,7 +861,7 @@ protected boolean shouldInlineInvoke(GraphBuilderContext b, AbstractPolicyScope } InlineBeforeAnalysisPolicyUtils.AccumulativeInlineScope accScope; - if (policyScope instanceof InlineBeforeAnalysisPolicyUtils.AlwaysInlineScope) { + if (policyScope instanceof RuntimeCompilationAlwaysInlineScope) { /* * If we are in "trivial inlining" mode, we make inlining decisions as if we are * still the root (= null) accumulative inlining scope. @@ -892,13 +894,13 @@ protected AbstractPolicyScope createRootScope() { protected AbstractPolicyScope openCalleeScope(AbstractPolicyScope outer, AnalysisMethod method) { if (outer instanceof InlineBeforeAnalysisPolicyUtils.AccumulativeInlineScope accOuter) { /* - * once the accumulative policy is activated, then we cannot return to the trivial - * policy + * Once the accumulative policy is activated, we cannot return to the trivial + * policy. */ - return inliningUtils.createAccumulativeInlineScope(accOuter, method); + return inliningUtils.createAccumulativeInlineScope(accOuter, method, DeoptimizationUtils.RUNTIME_COMPILATION_INVALID_NODES); } - assert outer == null || outer instanceof InlineBeforeAnalysisPolicyUtils.AlwaysInlineScope : "unexpected outer scope: " + outer; + assert outer == null || outer instanceof RuntimeCompilationAlwaysInlineScope : "unexpected outer scope: " + outer; /* * Check if trivial is possible. We use the graph size as the main criteria, similar to @@ -909,13 +911,13 @@ protected AbstractPolicyScope openCalleeScope(AbstractPolicyScope outer, Analysi * handle intrinsification with larger thresholds in order to fully inline the method * handle. */ - boolean trivialInlineAllowed = hostVM.isAnalysisTrivialMethod(method) && !AnnotationAccess.isAnnotationPresent(method, InlineBeforeAnalysisPolicyUtils.COMPILED_LAMBDA_FORM_ANNOTATION); + boolean trivialInlineAllowed = hostVM.isAnalysisTrivialMethod(method) && !InlineBeforeAnalysisPolicyUtils.isMethodHandleIntrinsificationRoot(method); int inliningDepth = outer == null ? 1 : outer.inliningDepth + 1; if (trivialInlineAllowed && inliningDepth <= trivialAllowingInliningDepth) { - return new InlineBeforeAnalysisPolicyUtils.AlwaysInlineScope(inliningDepth); + return new RuntimeCompilationAlwaysInlineScope(inliningDepth); } else { // start with a new accumulative inline scope - return inliningUtils.createAccumulativeInlineScope(null, method); + return inliningUtils.createAccumulativeInlineScope(null, method, DeoptimizationUtils.RUNTIME_COMPILATION_INVALID_NODES); } } } @@ -1135,3 +1137,42 @@ public boolean canVirtualize(ResolvedJavaType instanceType) { return true; } } + +/** + * This scope will always allow nodes to be inlined. + */ +class RuntimeCompilationAlwaysInlineScope extends InlineBeforeAnalysisPolicy.AbstractPolicyScope { + + RuntimeCompilationAlwaysInlineScope(int inliningDepth) { + super(inliningDepth); + } + + @Override + public void commitCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope callee) { + // nothing to do + } + + @Override + public void abortCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope callee) { + // nothing to do + } + + @Override + public boolean processNode(AnalysisMetaAccess metaAccess, AnalysisMethod method, Node node) { + /* + * Inline as long as an invalid node has not been seen. + */ + return !DeoptimizationUtils.RUNTIME_COMPILATION_INVALID_NODES.test(node); + } + + @Override + public boolean processNonInlinedInvoke(CoreProviders providers, CallTargetNode node) { + // always inlining + return true; + } + + @Override + public String toString() { + return "RuntimeCompilationAlwaysInlineScope"; + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index debcdb7e1784..828c28d27b37 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -141,7 +141,6 @@ import com.oracle.svm.core.c.struct.OffsetOf; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.cpufeature.RuntimeCPUFeatureCheck; -import com.oracle.svm.core.deopt.DeoptimizationSupport; import com.oracle.svm.core.graal.EconomyGraalConfiguration; import com.oracle.svm.core.graal.GraalConfiguration; import com.oracle.svm.core.graal.code.SubstrateBackend; @@ -1366,9 +1365,7 @@ public static void registerGraphBuilderPlugins(FeatureHandler featureHandler, Ru SubstrateReplacements replacements = (SubstrateReplacements) providers.getReplacements(); plugins.appendInlineInvokePlugin(replacements); - boolean useInlineBeforeAnalysisMethodHandleSupport = !SubstrateOptions.UseOldMethodHandleIntrinsics.getValue() && - !DeoptimizationSupport.enabled(); - if (useInlineBeforeAnalysisMethodHandleSupport) { + if (!SubstrateOptions.UseOldMethodHandleIntrinsics.getValue()) { if (reason.duringAnalysis()) { plugins.appendNodePlugin(new MethodHandleWithExceptionPlugin(providers.getConstantReflection().getMethodHandleAccess(), false)); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerPolicy.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerPolicy.java index 69d32dc917e5..3112feafbd88 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerPolicy.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerPolicy.java @@ -69,11 +69,6 @@ public static final class SimulateClassInitializerInlineScope extends InlineBefo this.accumulativeCounters = accumulativeCounters; } - @Override - public boolean allowAbort() { - return true; - } - @Override public void commitCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope callee) { SimulateClassInitializerInlineScope calleeScope = (SimulateClassInitializerInlineScope) callee; @@ -165,4 +160,9 @@ protected AbstractPolicyScope openCalleeScope(AbstractPolicyScope o, AnalysisMet var outer = (SimulateClassInitializerInlineScope) o; return new SimulateClassInitializerInlineScope(outer.accumulativeCounters, outer.inliningDepth + 1); } + + @Override + protected boolean shouldOmitIntermediateMethodInState(AnalysisMethod method) { + return false; + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DeoptimizationUtils.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DeoptimizationUtils.java index eb78a7373dc0..8f43772fd617 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DeoptimizationUtils.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DeoptimizationUtils.java @@ -127,7 +127,7 @@ static void insertDeoptTests(HostedMethod method, StructuredGraph graph) { * * Note this should only be called within CompileQueue#parseAheadOfTimeCompiledMethods */ - public static boolean canDeoptForTesting(AnalysisMethod method, boolean deoptimizeAll, Supplier graphInvalidator) { + public static boolean canDeoptForTesting(AnalysisMethod method, boolean deoptimizeAll, Supplier graphChecker) { if (SubstrateCompilationDirectives.singleton().isRegisteredForDeoptTesting(method)) { return true; } @@ -146,7 +146,7 @@ public static boolean canDeoptForTesting(AnalysisMethod method, boolean deoptimi return false; } - if (graphInvalidator.get()) { + if (!graphChecker.get()) { return false; } @@ -291,7 +291,7 @@ static boolean verifyDeoptTarget(HostedMethod method, StructuredGraph graph, Com /* * No deopt targets can have a StackValueNode in the graph. */ - assert !createGraphInvalidator(graph).get() : "Invalid nodes in deopt target: " + graph; + assert createGraphChecker(graph, AOT_COMPILATION_INVALID_NODES).get() : "Invalid nodes in deopt target: " + graph; for (Infopoint infopoint : result.getInfopoints()) { if (infopoint.debugInfo != null) { @@ -500,26 +500,28 @@ public static Collection registerDeoptEntries(StructuredGrap * We also do not allow class initialization at run time to ensure the partial evaluator does * not constant fold uninitialized fields. */ - private static final NodePredicate invalidNodes = n -> NodePredicates.isA(StackValueNode.class).or(NodePredicates.isA(EnsureClassInitializedNode.class)).test(n); + public static final NodePredicate RUNTIME_COMPILATION_INVALID_NODES = n -> NodePredicates.isA(StackValueNode.class).or(NodePredicates.isA(EnsureClassInitializedNode.class)).test(n); + + public static final NodePredicate AOT_COMPILATION_INVALID_NODES = n -> NodePredicates.isA(StackValueNode.class).test(n); /** - * @return Supplier which returns true if the graph contains invalid nodes. + * @return Supplier which returns true if the graph does not violate the checks. */ - public static Supplier createGraphInvalidator(StructuredGraph graph) { + public static Supplier createGraphChecker(StructuredGraph graph, NodePredicate invalidNodes) { return () -> { if (!graph.method().getDeclaringClass().isInitialized()) { /* * All types which are used at run time should build-time initialized. This ensures * the partial evaluator does not constant fold uninitialized fields. */ - return true; + return false; } if (graph.getNodes().filter(invalidNodes).isNotEmpty()) { - return true; + return false; } - return false; + return true; }; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java index a85ac193cfef..8823bf9746ad 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyImpl.java @@ -80,7 +80,7 @@ protected AbstractPolicyScope createRootScope() { @Override protected AbstractPolicyScope openCalleeScope(AbstractPolicyScope outer, AnalysisMethod method) { - return inliningUtils.createAccumulativeInlineScope((InlineBeforeAnalysisPolicyUtils.AccumulativeInlineScope) outer, method); + return inliningUtils.createAccumulativeInlineScope((InlineBeforeAnalysisPolicyUtils.AccumulativeInlineScope) outer, method, (ignore) -> false); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyUtils.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyUtils.java index ba3113452123..6e394f7c6b33 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyUtils.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/InlineBeforeAnalysisPolicyUtils.java @@ -44,6 +44,7 @@ import jdk.graal.compiler.api.replacements.Fold; import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.graph.iterators.NodePredicate; import jdk.graal.compiler.nodes.AbstractBeginNode; import jdk.graal.compiler.nodes.AbstractEndNode; import jdk.graal.compiler.nodes.CallTargetNode; @@ -71,6 +72,7 @@ import jdk.graal.compiler.options.Option; import jdk.graal.compiler.replacements.nodes.MethodHandleWithExceptionNode; import jdk.internal.vm.annotation.ForceInline; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * The defaults for node limits are very conservative. Only small methods should be inlined. The @@ -125,9 +127,13 @@ public static class Options { public final int optionMethodHandleAllowedInlinings = Options.InlineBeforeAnalysisMethodHandleAllowedInlinings.getValue(); @SuppressWarnings("unchecked") // - public static final Class COMPILED_LAMBDA_FORM_ANNOTATION = // + private static final Class COMPILED_LAMBDA_FORM_ANNOTATION = // (Class) ReflectionUtil.lookupClass(false, "java.lang.invoke.LambdaForm$Compiled"); + public static boolean isMethodHandleIntrinsificationRoot(ResolvedJavaMethod method) { + return AnnotationAccess.isAnnotationPresent(method, COMPILED_LAMBDA_FORM_ANNOTATION); + } + public boolean shouldInlineInvoke(GraphBuilderContext b, SVMHost hostVM, AccumulativeInlineScope policyScope, AnalysisMethod method) { boolean result = shouldInlineInvoke0(b, hostVM, policyScope, method); if (result && policyScope != null) { @@ -177,7 +183,7 @@ private boolean shouldInlineInvoke0(GraphBuilderContext b, SVMHost hostVM, Accum */ return false; } - if (policyScope != null && AnnotationAccess.isAnnotationPresent(method, COMPILED_LAMBDA_FORM_ANNOTATION)) { + if (policyScope != null && isMethodHandleIntrinsificationRoot(method)) { /* * We are not in a method handle intrinsification i.e., the method handle was not * the root inlining context. Do not inline compiled lambda forms at all. Since the @@ -231,48 +237,6 @@ public boolean alwaysInlineInvoke(@SuppressWarnings("unused") AnalysisMetaAccess return false; } - /** - * This scope will always allow nodes to be inlined. - */ - public static class AlwaysInlineScope extends InlineBeforeAnalysisPolicy.AbstractPolicyScope { - - public AlwaysInlineScope(int inliningDepth) { - super(inliningDepth); - } - - @Override - public boolean allowAbort() { - // should not be able to abort - return false; - } - - @Override - public void commitCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope callee) { - // nothing to do - } - - @Override - public void abortCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope callee) { - // nothing to do - } - - @Override - public boolean processNode(AnalysisMetaAccess metaAccess, AnalysisMethod method, Node node) { - // always inlining - return true; - } - - @Override - public boolean processNonInlinedInvoke(CoreProviders providers, CallTargetNode node) { - return true; - } - - @Override - public String toString() { - return "AlwaysInlineScope"; - } - } - static final class AccumulativeCounters { int maxNodes; int maxInvokes; @@ -294,7 +258,7 @@ private AccumulativeCounters(int maxNodes, int maxInvokes, boolean inMethodHandl * has exceeded a specified count, or an illegal node is inlined, then the process will be * aborted. */ - public AccumulativeInlineScope createAccumulativeInlineScope(AccumulativeInlineScope outer, AnalysisMethod method) { + public AccumulativeInlineScope createAccumulativeInlineScope(AccumulativeInlineScope outer, AnalysisMethod method, NodePredicate invalidNodePredicate) { AccumulativeCounters accumulativeCounters; int depth; if (outer == null) { @@ -304,7 +268,7 @@ public AccumulativeInlineScope createAccumulativeInlineScope(AccumulativeInlineS */ depth = 1; - if (AnnotationAccess.isAnnotationPresent(method, COMPILED_LAMBDA_FORM_ANNOTATION)) { + if (isMethodHandleIntrinsificationRoot(method)) { /* * Method handle intrinsification root: create counters with relaxed limits and * permit more types of nodes, but not recursively, i.e., not if we are already in a @@ -337,11 +301,12 @@ public AccumulativeInlineScope createAccumulativeInlineScope(AccumulativeInlineS depth = outer.inliningDepth + 1; accumulativeCounters = outer.accumulativeCounters; } - return new AccumulativeInlineScope(accumulativeCounters, depth); + return new AccumulativeInlineScope(accumulativeCounters, depth, invalidNodePredicate); } public final class AccumulativeInlineScope extends InlineBeforeAnalysisPolicy.AbstractPolicyScope { final AccumulativeCounters accumulativeCounters; + final NodePredicate invalidNodePredicate; /** * The number of nodes and invokes which have been inlined from this method (and also @@ -351,15 +316,10 @@ public final class AccumulativeInlineScope extends InlineBeforeAnalysisPolicy.Ab int numNodes = 0; int numInvokes = 0; - AccumulativeInlineScope(AccumulativeCounters accumulativeCounters, int inliningDepth) { + AccumulativeInlineScope(AccumulativeCounters accumulativeCounters, int inliningDepth, NodePredicate invalidNodePredicate) { super(inliningDepth); this.accumulativeCounters = accumulativeCounters; - } - - @Override - public boolean allowAbort() { - // when too many nodes are inlined any abort can occur - return true; + this.invalidNodePredicate = invalidNodePredicate; } @Override @@ -392,6 +352,10 @@ public void abortCalleeScope(InlineBeforeAnalysisPolicy.AbstractPolicyScope call @Override public boolean processNode(AnalysisMetaAccess metaAccess, AnalysisMethod method, Node node) { + if (invalidNodePredicate.test(node)) { + return false; + } + if (node instanceof StartNode || node instanceof ParameterNode || node instanceof ReturnNode || node instanceof UnwindNode || node instanceof CallTargetNode || node instanceof MethodHandleWithExceptionNode) { /* @@ -498,7 +462,7 @@ public boolean processNode(AnalysisMetaAccess metaAccess, AnalysisMethod method, @Override public boolean processNonInlinedInvoke(CoreProviders providers, CallTargetNode node) { - if (node.targetMethod() != null && AnnotationAccess.isAnnotationPresent(node.targetMethod(), COMPILED_LAMBDA_FORM_ANNOTATION)) { + if (node.targetMethod() != null && isMethodHandleIntrinsificationRoot(node.targetMethod())) { /* * Prevent partial inlining of method handle code, both with and without * "intrinsification of method handles". We rather want to keep a top-level call to @@ -530,7 +494,7 @@ public String toString() { private static boolean inlineForMethodHandleIntrinsification(AnalysisMethod method) { return AnnotationAccess.isAnnotationPresent(method, ForceInline.class) || - AnnotationAccess.isAnnotationPresent(method, COMPILED_LAMBDA_FORM_ANNOTATION) || + isMethodHandleIntrinsificationRoot(method) || INLINE_METHOD_HANDLE_CLASSES.contains(method.getDeclaringClass().getJavaClass()) || isManuallyListed(method.getJavaMethod()); } @@ -547,6 +511,6 @@ private static boolean isManuallyListed(Executable method) { * @see MethodHandleInvokerRenamingSubstitutionProcessor */ protected boolean shouldOmitIntermediateMethodInState(AnalysisMethod method) { - return method.isAnnotationPresent(COMPILED_LAMBDA_FORM_ANNOTATION); + return isMethodHandleIntrinsificationRoot(method); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java index b6ed52e87d5d..48d2ac850615 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java @@ -207,7 +207,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec dmh.register(new RequiredInvocationPlugin("getDeclaringClass", Receiver.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - JavaConstant constReceiver = receiver.get().asJavaConstant(); + JavaConstant constReceiver = receiver.get(false).asJavaConstant(); if (constReceiver == null || constReceiver.isNull()) { return false; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index db2ce3292c9f..57fa3dfdd615 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -125,7 +125,6 @@ import jdk.graal.compiler.nodes.calc.ZeroExtendNode; import jdk.graal.compiler.nodes.extended.BytecodeExceptionNode; import jdk.graal.compiler.nodes.extended.LoadHubNode; -import jdk.graal.compiler.nodes.extended.StateSplitProxyNode; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; @@ -829,8 +828,6 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec EnsureClassInitializedNode ensureInitialized = b.append(new EnsureClassInitializedNode(clazzNonNull)); ensureInitialized.setStateAfter(b.getInvocationPluginBeforeState()); DynamicNewInstanceNode.createAndPush(b, clazzNonNull); - /* Capture the correct state after these operations. */ - b.add(new StateSplitProxyNode()); return true; } }); diff --git a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java index 80af00069820..1ed21c3076ee 100644 --- a/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java +++ b/substratevm/src/org.graalvm.polyglot.nativeapi/src/org/graalvm/polyglot/nativeapi/PolyglotNativeAPI.java @@ -2413,17 +2413,20 @@ private static PolyglotStatus doRegisterRecurringCallback0(long intervalNanos, P PolyglotCallbackInfoInternal info = new PolyglotCallbackInfoInternal(new ObjectHandle[0], data); var infoHandle = (PolyglotCallbackInfo) objectHandles.create(info); var handles = getHandles(); - RecurringCallback recurringCallback = access -> { - handles.freezeHandleCreation(); - try { - callback.invoke((PolyglotIsolateThread) CurrentIsolate.getCurrentThread(), infoHandle); - CallbackException ce = threadLocals.get().callbackException; - if (ce != null) { - access.throwException(ce); + RecurringCallback recurringCallback = new RecurringCallback() { + @Override + public void run(Threading.RecurringCallbackAccess access) { + handles.freezeHandleCreation(); + try { + callback.invoke((PolyglotIsolateThread) CurrentIsolate.getCurrentThread(), infoHandle); + CallbackException ce = threadLocals.get().callbackException; + if (ce != null) { + access.throwException(ce); + } + } finally { + threadLocals.get().callbackException = null; + handles.unfreezeHandleCreation(); } - } finally { - threadLocals.get().callbackException = null; - handles.unfreezeHandleCreation(); } }; try { diff --git a/vm/mx.vm/mx_vm_gate.py b/vm/mx.vm/mx_vm_gate.py index 1da74e382b81..b3b119f43c87 100644 --- a/vm/mx.vm/mx_vm_gate.py +++ b/vm/mx.vm/mx_vm_gate.py @@ -693,6 +693,7 @@ def _collect_excludes(suite, suite_import, excludes): ] + mx_sdk_vm_impl.svm_experimental_options([ '-H:ClassInitialization=:build_time', '-H:+EnforceMaxRuntimeCompileMethods', + '-H:+UseOldMethodHandleIntrinsics', '-cp', cp, '-H:-FoldSecurityManagerGetter',