From 94bd8e69224a556b8ec4b749c385a8c2bf3dfa8b Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:02:44 -0700 Subject: [PATCH] Fix R2R GC ref map mismatch for unboxing stubs crossgen2 optimizes MethodEntry fixups into a compact MethodEntry_DefToken/ _RefToken form that emits only a token. This compact form cannot carry the READYTORUN_METHOD_SIG_UnboxingStub signature flag, so for an unboxing stub the emitted import cell lost its unboxing-ness. The GC ref map node, however, reads the same signature's IsUnboxingStub (== _method.Unboxing) and correctly emits a full GC ref (R) for the boxed object reference. At load time the runtime decoded the flagless token as a non-unboxing entry and computed an interior pointer (I), producing the checked-build assert: GC ref map mismatch detected for method: System.Int32::ToString This reproduces with a box + tail. callvirt Object::ToString() (test JIT/Regression/JitBlue/DevDiv_754566) when compiled in a Large Version Bubble, where System.Private.CoreLib is in the version bubble and the compact-token optimization applies to the cross-assembly call. Exclude unboxing stubs from the compact-token optimization (mirroring the existing !IsInstantiatingStub exclusion) so they use the full method signature, which preserves the UnboxingStub flag. The common, non-unboxing case is unaffected and still uses the compact form. Fixes #129778 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs index e041a325743ff0..80506e6c2411c0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs @@ -117,10 +117,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder(factory, relocsOnly); dataBuilder.AddSymbol(this); - // Optimize some of the fixups into a more compact form + // Optimize some of the fixups into a more compact form. + // The compact token forms cannot carry signature flags, so instantiating and unboxing + // stubs must use the full method signature. ReadyToRunFixupKind fixupKind = _fixupKind; bool optimized = false; - if (_method.Method.IsPrimaryMethodDesc() && !IsInstantiatingStub + if (_method.Method.IsPrimaryMethodDesc() && !IsInstantiatingStub && !_method.Unboxing && _method.ConstrainedType == null && fixupKind == ReadyToRunFixupKind.MethodEntry) { if (!_method.Method.HasInstantiation && !_method.Method.OwningType.HasInstantiation && !_method.Method.OwningType.IsArray)