Skip to content

Commit

Permalink
[GR-52211] Re-enable should verify framestates for runtime compiled m…
Browse files Browse the repository at this point in the history
…ethods.

PullRequest: graal/17045
  • Loading branch information
teshull committed Feb 26, 2024
2 parents 0ffae37 + f646601 commit c49f114
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
2 changes: 2 additions & 0 deletions sdk/mx.sdk/mx_sdk_vm_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,8 @@ def contents(self):
] + svm_experimental_options([
'-H:+AssertInitializationSpecifiedForAllClasses',
'-H:+EnforceMaxRuntimeCompileMethods',
'-H:+VerifyRuntimeCompilationFrameStates',
'-H:+GuaranteeSubstrateTypesLinked',
])
if _debug_images():
build_args += ['-ea', '-O0',] + svm_experimental_options(['-H:+PreserveFramePointer', '-H:-DeleteLocalSymbols'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ enum InlineDecision {
private final Set<SubstrateMethod> substrateAnalysisMethods = ConcurrentHashMap.newKeySet();
private final Map<AnalysisMethod, String> invalidForRuntimeCompilation = new ConcurrentHashMap<>();
private final Set<RuntimeCompilationCandidate> runtimeCompilationCandidates = ConcurrentHashMap.newKeySet();
private final Set<AnalysisMethod> runtimeCompilationsFailedDuringParsing = ConcurrentHashMap.newKeySet();
private CallTreeInfo callTreeMetadata = null;
private HostedProviders analysisProviders = null;
private AllowInliningPredicate allowInliningPredicate = (builder, target) -> AllowInliningPredicate.InlineDecision.INLINING_DISALLOWED;
Expand Down Expand Up @@ -513,6 +514,12 @@ private void checkMaxRuntimeCompiledMethods(CallTreeInfo callTreeInfo) {
public void afterAnalysis(Feature.AfterAnalysisAccess access) {
VMError.guarantee(callTreeMetadata == null);
callTreeMetadata = CallTreeInfo.create(((FeatureImpl.AfterAnalysisAccessImpl) access).getUniverse(), invalidForRuntimeCompilation);
if (!runtimeCompilationsFailedDuringParsing.isEmpty()) {
System.out.println("PermanentBailouts seen while parsing runtime compiled methods. One reason for this can be encountering invalid frame states.");
for (AnalysisMethod failedMethod : runtimeCompilationsFailedDuringParsing) {
printFailingRuntimeMethodTrace(callTreeMetadata, failedMethod, failedMethod);
}
}

ProgressReporter.singleton().setNumRuntimeCompiledMethods(callTreeMetadata.runtimeCompilations().size());
// after analysis has completed we must ensure no new SubstrateTypes are introduced
Expand Down Expand Up @@ -596,20 +603,24 @@ public void reportAnalysisError(AnalysisUniverse aUniverse, Throwable t) {
} else if (errorMethod.isDeoptTarget()) {
failingRuntimeMethod = errorMethod.getMultiMethod(RUNTIME_COMPILED_METHOD);
}
System.out.println("Parsing failed on a special method version: " + errorMethod.format("%H.%n"));
System.out.println("Method reachability trace");
if (failingRuntimeMethod != null) {
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod, registeredRuntimeCompilations)).forEach(System.out::println);
} else {
System.out.println("trace unavailable");
}
printFailingRuntimeMethodTrace(treeInfo, failingRuntimeMethod, errorMethod);
System.out.println("error: " + e.getMessage());
}
}
}
}
}

private void printFailingRuntimeMethodTrace(CallTreeInfo treeInfo, AnalysisMethod failingRuntimeMethod, AnalysisMethod errorMethod) {
System.out.println("Parsing failed on a special method version: " + errorMethod.format("%H.%n"));
System.out.println("Method reachability trace");
if (failingRuntimeMethod != null) {
Arrays.stream(CallTreeInfo.getCallTrace(treeInfo, failingRuntimeMethod, registeredRuntimeCompilations)).forEach(System.out::println);
} else {
System.out.println("trace unavailable");
}
}

private class RuntimeCompilationParsingSupport implements SVMParsingSupport {
RuntimeCompilationInlineBeforeAnalysisPolicy runtimeInlineBeforeAnalysisPolicy = null;

Expand Down Expand Up @@ -665,6 +676,7 @@ private Object parseRuntimeCompiledMethod(BigBang bb, DebugContext debug, Analys
if (graph == null) {
if (!method.hasBytecodes()) {
recordFailed(method);
runtimeCompilationsFailedDuringParsing.add(method);
return HostVM.PARSING_FAILED;
}

Expand All @@ -684,6 +696,7 @@ private Object parseRuntimeCompiledMethod(BigBang bb, DebugContext debug, Analys
} catch (PermanentBailoutException ex) {
bb.getUnsupportedFeatures().addMessage(method.format("%H.%n(%p)"), method, ex.getLocalizedMessage(), null, ex);
recordFailed(method);
runtimeCompilationsFailedDuringParsing.add(method);
return HostVM.PARSING_FAILED;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ public class RuntimeCompiledMethodSupport {
public static class Options {
@Option(help = "Remove Deopt(Entries,Anchors,Proxies) determined to be unneeded after the runtime compiled graphs have been finalized.")//
public static final HostedOptionKey<Boolean> RemoveUnneededDeoptSupport = new HostedOptionKey<>(true);

@Option(help = "Verify runtime compilation framestates during bytecode parsing.")//
public static final HostedOptionKey<Boolean> VerifyRuntimeCompilationFrameStates = new HostedOptionKey<>(false);
}

private record CompilationState(
Expand Down Expand Up @@ -462,14 +465,7 @@ protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, Valu

@Override
protected boolean shouldVerifyFrameStates() {
/*
* (GR-46115) Ideally we should verify frame states in methods registered for runtime
* compilations, as well as any other methods that can deoptimize. Because runtime
* compiled methods can pull in almost arbitrary code, this means most frame states
* should be verified. We currently use illegal states as placeholders in many places,
* so this cannot be enabled at the moment.
*/
return false;
return Options.VerifyRuntimeCompilationFrameStates.getValue();
}
}

Expand Down

0 comments on commit c49f114

Please sign in to comment.