Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C# 'is' operator suffer under release mode optimization on .NET 4?

Below is a simple test fixture. It succeeds in Debug builds and fails in Release builds (VS2010, .NET4 solution, x64):

[TestFixture] public sealed class Test {     [Test]     public void TestChecker()     {         var checker = new Checker();         Assert.That(checker.IsDateTime(DateTime.Now), Is.True);     } }  public class Checker {     public bool IsDateTime(object o)     {         return o is DateTime;     } } 

It seems code optimization wreaks some havoc; if I disable it on the Release build, it works as well. That was rather puzzling to me. Below, I've used ILDASM to disassemble the 2 versions of the build:

Debug IL:

.method public hidebysig instance bool IsDateTime(object o) cil managed {   // Code size       15 (0xf)   .maxstack  2   .locals init (bool V_0)   IL_0000:  nop   IL_0001:  ldarg.1   IL_0002:  isinst     [mscorlib]System.DateTime   IL_0007:  ldnull   IL_0008:  cgt.un   IL_000a:  stloc.0   IL_000b:  br.s       IL_000d   IL_000d:  ldloc.0   IL_000e:  ret } // end of method Validator::IsValid 

Release IL:

.method public hidebysig instance bool IsDateTime(object o) cil managed {   // Code size       10 (0xa)   .maxstack  8   IL_0000:  ldarg.1   IL_0001:  isinst     [mscorlib]System.DateTime   IL_0006:  ldnull   IL_0007:  cgt.un   IL_0009:  ret } // end of method Validator::IsValid 

It seems a store and load is optimized away. Targeting earlier versions of the .NET framework made the problem go away, but that may just be a fluke. I found this behaviour somewhat unnerving, can anybody explain why the compiler would think it safe to do an optimization that produces different observable behaviour?

Thanks in advance.

like image 833
Cumbayah Avatar asked Apr 04 '11 20:04

Cumbayah


People also ask

Is Can-C good for your eyes?

Benefits of Can-C Eye Drops:Can assist to lower the intraocular pressure associated with glaucoma. Are also beneficial for contact lens disorders. Have also been shown to help those suffering from presbyopia. Can be used to treat corneal disorders.

Is Can-C good for dogs?

SAFE FOR HUMANS AND DOGS - Can-C is the first and only patented NAC eye drop that uses the exact formula proven effective in both animal and human trials, offering a non-invasive alternative to cataract surgery. EVERY BLINK HYDRATES and lubricates the eye and cornea.

Does Can-C work for cataracts?

By managing cataracts with Can-C, some patients may be able to avoid cataract surgery and keep their own natural lens. Cataract surgery is an in-office or outpatient procedure done without the need for general anesthetic. The diseased lens is removed and replaced.

Can-C NAC?

The main ingredient of Can-C™ NAC eye drops is N-acetylcarnosine (NAC), a special analogue of di-peptide carnosine, a naturally occurring anti-oxidant nutrient. NAC is extremely effective at 'mopping up' free radicals, which accelerate aging in the body, including the growth of cataracts.


2 Answers

This bug already came up in this SO question by Jacob Stanley. Jacob has already reported the bug, and Microsoft has confirmed that it is indeed a bug in the CLR JIT. Microsoft had this to say:

This bug will be fixed in a future version of the runtime. I'm afraid it's too early to tell if that will be in a service pack or the next major release.

Thank you again for reporting the issue.

You should be able to work around the bug by adding the following attribute to TestChecker():

[MethodImpl(MethodImplOptions.NoInlining)] 
like image 115
Elian Ebbing Avatar answered Oct 11 '22 21:10

Elian Ebbing


It isn't related to the C# compiler, the IL is identical. You found a bug in the .NET 4.0 jitter optimizer. You can repro it in Visual Studio. Tools + Options, Debugging, General, untick the "Suppress JIT optimization on module load" option and run the Release build to repro the failure.

I haven't looked at it closely enough yet to identify the bug. It looks very strange, it inlines the method and completely omits the code for the boxing conversion. The machine code is substantially different from the code generated by the version 2 jitter.

A clean workaround isn't that easy, you can do it by suppressing inlining. Like this:

    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]     public bool IsDateTime(object o) {         return o is DateTime;     } 

You can report the bug at connect.microsoft.com. Let me know if you don't want to and I'll take care of it.


Never mind, that was already done. It wasn't fixed in the maintenance release that was included with VS2010 SP1.


This bug has been fixed, I can no longer repro it. My current version of clrjit.dll is 4.0.30319.237 dated May 17th 2011. I can't tell exactly what update repaired it. I got a security update on Aug 5th 2011 that updated clrjit.dll to revision 235 with a date of Apr 12, that would be the earliest.

like image 32
Hans Passant Avatar answered Oct 11 '22 20:10

Hans Passant