oracle/graal · error · GraalError

All non-recursive calls in the intrinsic %s must be inlined

Error message

All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s

What it means

The companion check in ReplacementsImpl.notifyNotInlined (ReplacementsImpl.java:236): a call inside an intrinsic's graph was not inlined and has no intrinsifying plugin. Unlike error 218, the callee is an ordinary method — intrinsic graphs must be self-contained except for calls to the original method, so any leftover ordinary call is rejected.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java:236

        }
        return null;
    }

    @Override
    public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) {
        if (b.parsingIntrinsic()) {
            IntrinsicContext intrinsic = b.getIntrinsic();
            if (!intrinsic.isCallToOriginal(method)) {
                Class<? extends GraphBuilderPlugin> pluginClass = getIntrinsifyingPlugin(method);
                if (pluginClass != null) {
                    String methodDesc = method.format("%H.%n(%p)");
                    throw new GraalError("Call to %s should have been intrinsified by a %s. " +
                                    "This is typically caused by Eclipse failing to run an annotation " +
                                    "processor. This can usually be fixed by forcing Eclipse to rebuild " +
                                    "the source file in which %s is declared",
                                    methodDesc, pluginClass.getSimpleName(), methodDesc);
                }
                throw new GraalError("All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s",
                                intrinsic.getIntrinsicMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)"));
            }
        }
    }

    // This map is key'ed by a class name instead of a Class object so that
    // it is stable across VM executions (in support of replay compilation).
    private final EconomicMap<String, SnippetTemplateCache> snippetTemplateCache;

    @SuppressWarnings("this-escape")
    public ReplacementsImpl(DebugDumpHandlersFactory debugHandlersFactory, Providers providers, BytecodeProvider bytecodeProvider, TargetDescription target) {
        this.providers = providers.copyWith(this);
        this.target = target;
        this.snippetGraphs = new ConcurrentHashMap<>();
        this.snippetTemplateCache = EconomicMap.create(Equivalence.DEFAULT);
        this.defaultBytecodeProvider = bytecodeProvider;
        this.debugHandlersFactory = debugHandlersFactory;
        this.templatesCache = Collections.synchronizedMap(new SnippetTemplate.LRUCache<>());

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Make the called method a @NodeIntrinsic, mark it for forced inlining (e.g., @Inline/@ForceInline or must-inline mechanism) so the parser inlines it
  2. Reimplement the call using Graal graph nodes directly inside the intrinsic
  3. If the call is meant to hit the substituted method itself, use the intrinsic's isCallToOriginal escape hatch (invoke the original via the intrinsic context)

Example fix

// before
@MethodSubstitution static int sub(int x) { return helper(x); } // helper not inlined

// after
@Inline static int helper(int x) { ... } // forced inline, call disappears from intrinsic graph
Defensive patterns

Strategy: validation

Validate before calling

// before shipping an intrinsic, grep its body for ordinary calls:
// every invoked method must be @NodeIntrinsic, force-inlined, or the substituted original
if (!callee.isIntrinsicCandidate() && !isForceInlined(callee) && !intrinsic.isCallToOriginal(callee)) fail();

Try / catch

try {
    replacements.registerSubstitution(MySubstitution.class);
} catch (GraalError e) {
    // message names the offending call; fix the intrinsic body, don't suppress
    throw e;
}

Prevention

When it happens

Trigger: Writing an @MethodSubstitution/intrinsic that calls a helper method that is neither inlined by the bytecode parser (too large, not force-inline) nor a node intrinsic; calling library methods (Math.max, etc.) that lack a registered plugin in this context.

Common situations: New hand-written intrinsics that forget @Inline/force-inline on helpers; refactoring shared logic out of an intrinsic into a utility method; relying on JVM intrinsics (like String/Matrix methods) that Graal must re-provide.

Related errors


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