Skip to content

JIT optimization removes some necessary code in .NET Core 3.0/3.1 #764

@SergeMatskov

Description

@SergeMatskov

If the next code will be built in the Release configuration, an exception will be thrown because the object summary is null. This affects only .NET Core 3.0 and later. There is no issue in .NET Core 1.0-2.2.

    public struct Ptr<T>
        where T: class
    {
        private T _value;

        public Ptr(T value)
        {
            _value = value;
        }

        //[MethodImpl(MethodImplOptions.NoInlining)]
        public T Release()
        {
            T tmp = _value;
            _value = null;
            return tmp;
        }
    }

    public class TestClass
    {
    }

    class Program
    {
        private static void Main(string[] args)
        {
            Ptr<TestClass> ptr = new Ptr<TestClass>(new TestClass());

            bool res = false;
            while (res)
            {
            }

            TestClass summary = ptr.Release();

            if (summary == null)
                throw new Exception("JIT optimization failure");
            Consume(summary);
            Console.WriteLine("OK");
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void Consume(TestClass summary)
        { 
        }
    }

There are some ways to fix an issue under .NET Core 3.0:

  • Disable optimization in the project settings.
  • Remove empty while loop.
  • Uncomment MethodImpl attribute on Ptr.Release() method.
  • Make Ptr non-generic class (or just make private T _value; member of Ptr class of type object).

Disassembly of JITed code in .NET Core 3.1:

           Ptr<TestClass> ptr = new Ptr<TestClass>(new TestClass());
00007FF7C9420F50  push        rsi  
00007FF7C9420F51  sub         rsp,20h  

            bool res = false;
00007FF7C9420F55  mov         rcx,7FF7C94A4170h  
00007FF7C9420F5F  call        00007FF828F36CB0  
00007FF7C9420F64  mov         rsi,rax  
00007FF7C9420F67  mov         rcx,rsi  
00007FF7C9420F6A  call        00007FF7C9414C10  
00007FF7C9420F6F  mov         ecx,1  
00007FF7C9420F74  mov         rdx,7FF7C94BF788h  
00007FF7C9420F7E  call        00007FF8290605B0  
00007FF7C9420F83  lea         rcx,[rsi+10h]  
00007FF7C9420F87  mov         rdx,rax  
00007FF7C9420F8A  call        00007FF828F35DF0  
                throw new Exception("JIT optimization failure");
00007FF7C9420F8F  mov         rcx,rsi  
00007FF7C9420F92  call        00007FF828EAB900  
00007FF7C9420F97  int         3  

Disassembly of JITed code in .NET Core 2.2:

            Ptr<TestClass> ptr = new Ptr<TestClass>(new TestClass());
00007FF7C9401520  sub         rsp,28h  
00007FF7C9401524  mov         rcx,7FF7C92E6708h  
00007FF7C940152E  call        00007FF828EEB3B0  
00007FF7C9401533  mov         rcx,rax  
00007FF7C9401536  mov         rax,rcx  
            {
            }

            TestClass summary = ptr.Release();
00007FF7C9401539  mov         rcx,rax  
00007FF7C940153C  call        00007FF7C94010A0  
            Console.WriteLine("OK");
00007FF7C9401541  mov         rcx,262B4E23068h  
00007FF7C940154B  mov         rcx,qword ptr [rcx]  
00007FF7C940154E  call        00007FF7C9401398  
00007FF7C9401553  nop  
00007FF7C9401554  add         rsp,28h  
00007FF7C9401558  ret  

The test project was attached:
JitOptimizationFailure.zip

category:correctness
theme:importer
skill-level:intermediate
cost:small

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbug

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions