Skip to content

Commit

Permalink
[GR-47515] Use inlinebeforeanalysis method handle intrinsification fo…
Browse files Browse the repository at this point in the history
…r Runtime Compilations.

PullRequest: graal/16747
  • Loading branch information
teshull committed Feb 19, 2024
2 parents 39ae91f + 4d2e935 commit 8b36b74
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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]) {

Expand Down Expand Up @@ -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;
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<Boolean> 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<Boolean> RuntimeCompilationInlineBeforeAnalysis = new HostedOptionKey<>(true);
}

Expand Down Expand Up @@ -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);
}
Expand All @@ -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<Boolean> graphInvalidator = DeoptimizationUtils.createGraphInvalidator(graph);
if (aMethod.isOriginalMethod() && DeoptimizationUtils.canDeoptForTesting(aMethod, false, graphInvalidator)) {
DeoptimizationUtils.registerDeoptEntriesForDeoptTesting(bb, graph, aMethod);
return true;
}
Supplier<Boolean> 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) {
/*
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Boolean> graphInvalidator) {
public static boolean canDeoptForTesting(AnalysisMethod method, boolean deoptimizeAll, Supplier<Boolean> graphChecker) {
if (SubstrateCompilationDirectives.singleton().isRegisteredForDeoptTesting(method)) {
return true;
}
Expand All @@ -146,7 +146,7 @@ public static boolean canDeoptForTesting(AnalysisMethod method, boolean deoptimi
return false;
}

if (graphInvalidator.get()) {
if (!graphChecker.get()) {
return false;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -500,26 +500,28 @@ public static Collection<ResolvedJavaMethod> 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<Boolean> createGraphInvalidator(StructuredGraph graph) {
public static Supplier<Boolean> 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;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 8b36b74

Please sign in to comment.