After some code inspection we nailed it down to a foreach loop, something as simple as:
var list = new List<int>(); // the code bellow allocates memory. foreach(var item in list) { }Interestingly enough, when compiled against C# 3.5 / 4.0 compilers we could not reproduce this behavior; it was only when compiling on Mono 2.6 (on mono 2.10 it didn't happened).
After some investigation (and head banging) we found the issue; for reasons that I'll not explain here (basically to avoid gc allocations) the enumerator returned by List
finally { IL_0048: ldloc.2 IL_0049: box valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator< int32> IL_004e: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0053: endfinally }Well, it happens that MS C# compiler (and newer mono ones also) emit different IL for that finally block:
finally { IL_004b: ldloca.s 3 IL_004d: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator< int32> IL_0053: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0058: nop IL_0059: endfinally }See, no box instruction. Instead of boxing, the compiler loads the value type address and then asks the runtime to handle that address as a reference to IDisposable.
Really interesting (at least IMHO)
Happy codding!
No comments:
Post a Comment