-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone
Description
The following example throws NRE without printing any output when tiered PGO is enabled. It should print "Should be printed" before throwing NRE.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
public class Program
{
public static void Main()
{
for (int i = 0; i < 100; i++)
{
long sum = Foo(i => i * 42, true);
if (i > 30 && i < 40)
Thread.Sleep(100);
}
Foo(null, false);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static long Foo(Func<long, long> f, bool silent)
{
long result = 0;
for (long i = 0; i < 100000; i++)
result += f(Test(i, silent));
return result;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static long Test(long i, bool silent)
{
if (i == 0 && !silent)
Console.WriteLine("Should be printed");
return i;
}
}The evaluation order is meant to be:
- Evaluate this
- Evaluate arguments
- Null check this
- Do call
With GDV, since the guard involves dereferencing 'this', step 3 happens too early. This happens for both vtable, interface and delegate GDV.
Tricky to solve unfortunately. We need to evaluate the guard after the arguments (hard to represent without lots of additional spilling) or add a null check to the guard (expensive). cc @AndyAyersMS @EgorBo
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI