oracle/graal · error · AssertionError
Performance warning detected and is treated as a compilation
Error message
Performance warning detected and is treated as a compilation error.
What it means
Thrown as an AssertionError at the end of Truffle performance-warning reporting when any warning kind recorded for the compiled graph intersects the kinds listed in TruffleCompilerOptions.TreatPerformanceWarningsAsErrors. It is a deliberate escape hatch: the compiler detected a coding pattern known to hurt Truffle peak performance (e.g. megamorphic virtual calls in hot code) and the configuration says to fail the compilation instead of just logging. This is not a compiler bug; it is a lint gate for guest-language bytecode produced by partial evaluation.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PerformanceInformationHandler.java:241
if (!ProfileSource.isTrusted(split.getProfileData().getProfileSource())) {
logPerformanceWarning(TruffleCompilerOptions.PerformanceWarningKind.MISSING_LOOP_FREQUENCY_INFO, context.compilable, Arrays.asList(loop.getHeader().getBeginNode()),
String.format("Missing loop profile for %s at loop %s.", split, loop.getHeader().getBeginNode()), null);
}
}
}
}
}
if (debug.areScopesEnabled() && !warnings.isEmpty()) {
try (DebugContext.Scope s = debug.scope("TrufflePerformanceWarnings", graph)) {
debug.dump(DebugContext.BASIC_LEVEL, graph, "performance warnings %s", warnings);
} catch (Throwable t) {
debug.handle(t);
}
}
if (!Collections.disjoint(getWarnings(), TruffleCompilerOptions.TreatPerformanceWarningsAsErrors.getValue(options).kinds())) {
throw new AssertionError("Performance warning detected and is treated as a compilation error.");
}
}
/**
* On HotSpot, a type check against a class that is at a depth <= 8 in the class hierarchy
* (including Object) is just one extra memory load.
*/
private static boolean isPrimarySupertype(ResolvedJavaType type) {
if (type.isInterface()) {
return false;
}
ResolvedJavaType supr = type;
int depth = 0;
while (supr != null) {
depth++;
supr = supr.getSuperclass();
}
return depth <= 8;View on GitHub (pinned to a66e9ccd1d)
Solutions
- Run with -Dgraal.TrufflePerformanceWarningsAsErrors= to disable the error conversion, or remove the specific kind matching the warning, then recompile to see the dumped warnings (enable -Dgraal.Dump=TrufflePerformanceWarnings to get the 'performance warnings %s' dump).
- Inspect the graph dump named 'performance warnings' to identify which node/warning kind fired (e.g. megamorphic dispatch, virtual call not inlined).
- Fix the guest-language code or node implementation that produced the warning (specialize, use @Specialization guards, avoid megamorphic call sites).
- If the warning is a false positive for your language, exclude only that warning kind from TreatPerformanceWarningsAsErrors instead of disabling the check entirely.
Example fix
// before -Dgraal.TrufflePerformanceWarningsAsErrors=all // after: narrow to the kinds you actually enforce, dump details first -Dgraal.Dump=TrufflePerformanceWarnings,level=1 -Dgraal.TrufflePerformanceWarningsAsErrors=Megamorphic
Defensive patterns
Strategy: try-catch
Validate before calling
// Before compiling, check the option value yourself
import static jdk.graal.compiler.truffle.TruffleCompilerOptions.TreatPerformanceWarningsAsErrors;
var kinds = TreatPerformanceWarningsAsErrors.getValue(options).kinds();
if (!kinds.isEmpty()) {
System.err.println("strict perf warnings active: " + kinds);
} Try / catch
// At the compilation-request boundary
try {
compile(graph, options);
} catch (AssertionError e) {
if (e.getMessage() != null && e.getMessage().contains("Performance warning detected")) {
// treat as code-quality failure: log, collect CI artifact, recompile with warnings non-fatal
reportPerfWarnings(compilationId);
} else {
throw e;
}
} Prevention
- Keep TreatPerformanceWarningsAsErrors limited to specific warning kinds you actually police, not 'all'.
- Run CI with -Dgraal.Dump=TrufflePerformanceWarnings so any failure ships with the graph dump that explains it.
- Re-baseline the warning-kind set after every GraalVM upgrade; new kinds can start failing previously-clean code.
When it happens
Trigger: Compiling a Truffle guest-language method whose graph accumulates performance warnings (via PerformanceInformationHandler.getWarnings()), while -Dgraal.TrufflePerformanceWarningsAsErrors (TreatPerformanceWarningsAsErrors) is set to a kind set such as 'all' or 'Megamorphic' that overlaps those warnings. The check runs Collections.disjoint(getWarnings(), optionKinds) after every compilation, so any single matching warning triggers it.
Common situations: Language implementers enabling strict performance checking in CI to catch regressions; upgrading a Truffle language after new warning kinds were added (a pattern previously silent now fails); running with TreatPerformanceWarningsAsErrors=AnNOTATED/Bailout on code that uses @NeverValidTruffleBundle or optimistic assumptions that became megamorphic.
Related errors
- Early inlining exceeded the maximum depth of %s for method %
- No inlining policy provider with provided name:
- This VM does not support continuations.
- Continuations must be run on the Java on Truffle JVM with th
- You can't resume an already executing continuation.
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/27f20a5a2a813239.
Report an issue: GitHub.