oracle/graal · error · PermanentBailoutException
Frame size (%d) exceeded maximum allowed frame size (%d).
Error message
Frame size (%d) exceeded maximum allowed frame size (%d).
What it means
FrameMap.finish() finalizes the frame size (spill slots + outgoing argument area + saved registers, rounded up to stack alignment) and enforces the target's maximum frame size from the RegisterConfig. Exceeding it throws a PermanentBailoutException because the platform ABI cannot address a larger frame. This is a deliberate, non-retryable bailout: the method simply cannot be compiled within the ABI limit.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/framemap/FrameMap.java:188
* Aligns the given frame size to the stack alignment size and return the aligned size.
*
* @param size the initial frame size to be aligned
* @return the aligned frame size
*/
protected int alignFrameSize(int size) {
return NumUtil.roundUp(size, getTarget().stackAlignment);
}
/**
* Computes the final size of this frame. After this method has been called, methods that change
* the frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can
* be requested.
*/
public void finish() {
GraalError.guarantee(frameSize == -1, "frame size may only be computed once");
frameSize = currentFrameSize();
if (frameSize > getRegisterConfig().getMaximumFrameSize()) {
throw new PermanentBailoutException("Frame size (%d) exceeded maximum allowed frame size (%d).", frameSize, getRegisterConfig().getMaximumFrameSize());
}
}
/**
* Computes the offset of a stack slot relative to the frame register.
*
* @param slot a stack slot
* @return the offset of the stack slot
*/
public int offsetForStackSlot(StackSlot slot) {
if (slot.isInCallerFrame()) {
accessesCallerFrame = true;
}
return slot.getOffset(totalFrameSize());
}
/**
* Informs the frame map that the compiled code calls a particular method, which may need stackView on GitHub (pinned to a66e9ccd1d)
Solutions
- Split the offending method into smaller methods so each compiled unit needs fewer spill slots
- Reduce inlining of the offending call chain (make helpers non-inlinable, e.g., @TruffleBoundary in Truffle contexts or lower inline thresholds)
- Cap loop unrolling/peeling growth for that method so the LIR does not balloon
- Locate the method with -Dgraal.Dump=:1 (the bailout dump shows the frame size and method) and target only that method
Example fix
// before: thousands of locals live simultaneously after inlining
void dispatch(int op) { /* 4000 lines, all locals live */ }
// after: partition into per-op methods
void dispatch(int op) { switch (op) { case 0 -> op0(); case 1 -> op1(); ... } } Defensive patterns
Strategy: fallback
Try / catch
try {
compile(method);
} catch (PermanentBailoutException e) { // frame-size bailout is permanent
// ABI hard limit: this exact method can never be compiled; use interpreter/baseline
runInterpreted(method);
} Prevention
- Keep methods small enough that spill-slot counts stay far below ABI frame limits
- Limit inlining depth around known-huge methods
- For generated code, cap the number of live locals per generated method
When it happens
Trigger: A compiled method with an enormous number of spill slots (very high register pressure across a huge method) or very large outgoing argument areas (huge call signatures), so currentFrameSize() > getRegisterConfig().getMaximumFrameSize(). Frequently seen after aggressive inlining or full unrolling creates one gigantic method.
Common situations: AOT-compiling generated code with giant methods; deep inlining chains fusing into one compilation unit; machine-generated dispatch methods with thousands of locals; sparc/aaarch64 ABIs with tighter frame limits than amd64.
Related errors
- too many iterations in computeGlobalLiveSets
- Graal implementation restriction: Method with %s loop explos
- Graal implementation restriction: Method with %s loop explos
- NormalizeCompareNode connected to %s (%s %s %s)
- LogFile substitution %s cannot be combined with any other ch
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/0c3d2d49371d3c8b.
Report an issue: GitHub.