You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CORINFO_HELP_CHECK_OBJ is implemented as HCIMPL1_RAW(Object*, JIT_CheckObj, Object* obj) in src/coreclr/vm/jithelpers.cpp — it returns Object*. The JIT models it inconsistently:
src/coreclr/jit/morph.cpp (fgMorphInit, argument check): gtNewHelperCallNode(CORINFO_HELP_CHECK_OBJ, TYP_VOID, op) — models a value-returning helper as void.
On register-based targets the second form is benign (the returned reference is simply left in the return register and dropped). On wasm the call_indirect / call signature is derived from the JIT-modeled return type in CodeGen::genCallInstruction, so a TYP_VOID model for a value-returning helper emits a mismatched signature and the engine traps with function signature mismatch — the same class of defect as #130813 and the inline-unbox slow-path helper.
This only fires under DOTNET_JitGCChecks=1 (opts.compGcChecks) in a Debug/Checked JIT, so it is low severity, but it is the same modeling bug and is cheap to fix.
Reproduction Steps
Checked/Debug JIT, DOTNET_JitGCChecks=1, wasm target, on any method with a TYP_REF argument.
Expected behavior
The helper is modeled with a return type matching JIT_CheckObj (TYP_REF), and the unused result is discarded (e.g. via gtUnusedValNode) so the enclosing statement stays void.
Actual behavior
fgMorphInit creates the call as TYP_VOID; on wasm the emitted call signature does not match the helper.
Description
CORINFO_HELP_CHECK_OBJis implemented asHCIMPL1_RAW(Object*, JIT_CheckObj, Object* obj)insrc/coreclr/vm/jithelpers.cpp— it returnsObject*. The JIT models it inconsistently:src/coreclr/jit/importer.cpp(return-value check):gtNewHelperCallNode(CORINFO_HELP_CHECK_OBJ, TYP_REF, op2)— correct.src/coreclr/jit/morph.cpp(fgMorphInit, argument check):gtNewHelperCallNode(CORINFO_HELP_CHECK_OBJ, TYP_VOID, op)— models a value-returning helper as void.On register-based targets the second form is benign (the returned reference is simply left in the return register and dropped). On wasm the
call_indirect/ call signature is derived from the JIT-modeled return type inCodeGen::genCallInstruction, so aTYP_VOIDmodel for a value-returning helper emits a mismatched signature and the engine traps withfunction signature mismatch— the same class of defect as #130813 and the inline-unbox slow-path helper.This only fires under
DOTNET_JitGCChecks=1(opts.compGcChecks) in a Debug/Checked JIT, so it is low severity, but it is the same modeling bug and is cheap to fix.Reproduction Steps
Checked/Debug JIT,
DOTNET_JitGCChecks=1, wasm target, on any method with aTYP_REFargument.Expected behavior
The helper is modeled with a return type matching
JIT_CheckObj(TYP_REF), and the unused result is discarded (e.g. viagtUnusedValNode) so the enclosing statement stays void.Actual behavior
fgMorphInitcreates the call asTYP_VOID; on wasm the emitted call signature does not match the helper.Configuration
browser-wasm/wasi-wasm, Checked/Debug,DOTNET_JitGCChecks=1,main.Related: #129622, #130813
Note
This issue was created with assistance from GitHub Copilot (AI).