oracle/graal · error · PermanentBailoutException

OSR compilation without OSR entry loop.

Error message

OSR compilation without OSR entry loop.

What it means

PermanentBailoutException thrown by OnStackReplacementPhase when an OSR compilation's EntryMarkerNode cannot be associated with any loop in the CFG (osrLoop() returns null). Graal can only compile an OSR entry if the bytecode position sits inside a loop it can identify; without it there is no safe point to deoptimize to or frame state to use, so the compilation is permanently bailed out (the method keeps running interpreted).

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/phases/OnStackReplacementPhase.java:139

        if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) {
            // This happens during inlining in a OSR method, because the same phase plan will be
            // used.
            assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty();
            return;
        }
        debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());

        final EntryMarkerNode originalOSRNode = getEntryMarker(graph);
        final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode, providers);
        final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode);

        if (originalOSRLoop == null) {
            /*
             * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we
             * cannot decide where to deopt and which framestate will be used. In the worst case the
             * framestate of the OSR entry would be used.
             */
            throw new PermanentBailoutException("OSR compilation without OSR entry loop.");
        }

        if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) {
            throw new PermanentBailoutException("OSR with locks disabled.");
        }

        EntryMarkerNode osr = OnStackReplacementUtils.peelEntryLoops(graph, providers.getLoopsDataProvider(), () -> getEntryMarker(graph), loop -> {
        },
                        (iterations, maxIterations) -> {
                            throw GraalError.shouldNotReachHere(iterations + " " + maxIterations); // ExcludeFromJacocoGeneratedReport
                        }, "OnStackReplacement loop peeling result");

        StartNode start = graph.start();
        FrameState osrState = osr.stateAfter();
        OSRStartNode osrStart;
        try (DebugCloseable context = osr.withNodeSourcePosition()) {
            osr.setStateAfter(null);
            osrStart = graph.add(new OSRStartNode());

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Treat it as non-fatal: it is a bailout — HotSpot falls back to the interpreter for this OSR; no user action is strictly required.
  2. If it recurs noisily, disable Graal OSR for the method/class (-Dgraal.CompileLocally... or use -XX:-UseJVMCICompiler for that run) to confirm.
  3. Compiler developers: dump the graph (-Dgraal.Dump=:1 around OSR) and inspect why the entry marker is loop-less before OnStackReplacementPhase runs.
Defensive patterns

Strategy: fallback

Try / catch

// Compiler-internal; callers of CompilationTask/CompilationResult may treat bailouts as expected:
try {
    compileResult = compile(task);
} catch (PermanentBailoutException e) { // e.g. 'OSR compilation without OSR entry loop.'
    // expected for some OSR shapes: method stays interpreted, request returns failure gracefully
}

Prevention

When it happens

Trigger: A HotSpot OSR compilation request (compile_at_bci with a non-negative OSR bci) where after parsing the OSR entry marker's block belongs to no CFGLoop — e.g. the loop was removed/optimized away during parsing, or the entry bci no longer lies inside a natural loop because of prior transformations.

Common situations: Long-running loops in startup/warmup code that trigger OSR while the graph shape confuses loop detection; changes in frontend parsing or loop peeling logic in compiler development; rarely, exotic bytecode from instrumentation agents.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/286445dac36a77b3. Report an issue: GitHub.