{"record":{"id":"0c3d2d49371d3c8b","repo":"oracle/graal","slug":"frame-size-d-exceeded-maximum-allowed-frame-siz","errorCode":null,"errorMessage":"Frame size (%d) exceeded maximum allowed frame size (%d).","messagePattern":"Frame size \\((.+?)\\) exceeded maximum allowed frame size \\((.+?)\\)\\.","errorType":"exception","errorClass":"PermanentBailoutException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/framemap/FrameMap.java","lineNumber":188,"sourceCode":"     * Aligns the given frame size to the stack alignment size and return the aligned size.\n     *\n     * @param size the initial frame size to be aligned\n     * @return the aligned frame size\n     */\n    protected int alignFrameSize(int size) {\n        return NumUtil.roundUp(size, getTarget().stackAlignment);\n    }\n\n    /**\n     * Computes the final size of this frame. After this method has been called, methods that change\n     * the frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can\n     * be requested.\n     */\n    public void finish() {\n        GraalError.guarantee(frameSize == -1, \"frame size may only be computed once\");\n        frameSize = currentFrameSize();\n        if (frameSize > getRegisterConfig().getMaximumFrameSize()) {\n            throw new PermanentBailoutException(\"Frame size (%d) exceeded maximum allowed frame size (%d).\", frameSize, getRegisterConfig().getMaximumFrameSize());\n        }\n    }\n\n    /**\n     * Computes the offset of a stack slot relative to the frame register.\n     *\n     * @param slot a stack slot\n     * @return the offset of the stack slot\n     */\n    public int offsetForStackSlot(StackSlot slot) {\n        if (slot.isInCallerFrame()) {\n            accessesCallerFrame = true;\n        }\n        return slot.getOffset(totalFrameSize());\n    }\n\n    /**\n     * Informs the frame map that the compiled code calls a particular method, which may need stack","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/framemap/FrameMap.java#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: thousands of locals live simultaneously after inlining\nvoid dispatch(int op) { /* 4000 lines, all locals live */ }\n\n// after: partition into per-op methods\nvoid dispatch(int op) { switch (op) { case 0 -> op0(); case 1 -> op1(); ... } }","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    compile(method);\n} catch (PermanentBailoutException e) { // frame-size bailout is permanent\n    // ABI hard limit: this exact method can never be compiled; use interpreter/baseline\n    runInterpreted(method);\n}","preventionTips":["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"],"tags":["graalvm","frame-map","stack-frame","abi","permanent-bailout"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}