diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 8145cbcf2b6b67..081c64c2a4a987 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -289,6 +289,14 @@ void Compiler::lvaInitTypeRef() { JITDUMP("Setting lvPinned for V%02u\n", varNum); varDsc->lvPinned = 1; + + if (opts.IsOSR()) + { + // OSR method may not see any references to the pinned local, + // but must still report it in GC info. + // + varDsc->lvImplicitlyReferenced = 1; + } } else { diff --git a/src/tests/JIT/opt/OSR/pinnedlocal.cs b/src/tests/JIT/opt/OSR/pinnedlocal.cs new file mode 100644 index 00000000000000..5641b0e85c0671 --- /dev/null +++ b/src/tests/JIT/opt/OSR/pinnedlocal.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// Run under COMPlus_GCStress=3 + +class PinnedLocal +{ + static int F(char c) + { + return (int) c; + } + + public static unsafe int Main() + { + string ss = "goodbye, world\n"; + string s = "hello, world\n"; + int r = 0; + fixed(char* p = s) + { + for (int i = 0; i < 100_000; i++) + { + r += F(p[i % s.Length]); + + if ((i % 10_000) == 0) + { + GC.Collect(2); + ss = new String('a', 100); + } + } + + Console.WriteLine($"r is {r}"); + return r - 9000061 + 100; + } + } +} diff --git a/src/tests/JIT/opt/OSR/pinnedlocal.csproj b/src/tests/JIT/opt/OSR/pinnedlocal.csproj new file mode 100644 index 00000000000000..14804c23dba34d --- /dev/null +++ b/src/tests/JIT/opt/OSR/pinnedlocal.csproj @@ -0,0 +1,21 @@ + + + Exe + + True + True + + + + + + + + +