Volatile local variable in LazyInitializer.EnsureInitialized?

情到浓时终转凉″ 提交于 2019-12-10 15:56:43

问题


I was looking at LazyInitializer.EnsureInitialized(ref T, Func{T}) in Reflector, and there appears to be a volatile local variable in that method volatile object local1 = s_barrier; . I can think of two possible reasons for this:

  1. .NET may get to use features that are not supported by a given language, or

  2. The actual code does not declare a volatile local variable, but when the compiled code is decompiled by Reflector, it looks like a volatile local variable.

Does anyone know which is the case here (or whether there might be some other explanation)? If it is a matter of decompilation, does anyone have an idea of what the "true" code would look like?


回答1:


This looks like a Reflector bug : it's just a normal volatile read of the s_barrier field. There's no "special" IL here that's not expressible in C#.

 L_000d: volatile. 
 L_000f: ldsfld object modreq(System.Runtime.CompilerServices.IsVolatile) System.Threading.LazyInitializer::s_barrier

This is just the normal code the compiler emits when reading from a static volatile field.


Here's a simpler repro: just compile the following (wrapped in a type) in release mode:

private static volatile object field;

private static void Main()
{
    var temp = field;
}

Reflector produces the following decompiled C#:

private static void Main()
{
    volatile object field = Program.field;
}

when the IL is actually:

L_0000: volatile. 
L_0002: ldsfld object modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) WindowsFormsApplication1.Program::field
L_0007: pop 
L_0008: ret 

UPDATE: Here's my guess about what's happening: In release mode, the C# compiler optimizes away the assignment of the value of the field (the result of the volatile read) to the local variable (the stloc instruction) since the local is not subsequently used. This appears to confuse Reflector. If you changed the method to use the subsequently use local, the stloc (or similar) instruction would indeed be emitted, following which the decompiled output from Reflector looks sensible.




回答2:


Ani is right. This is the actual source code, as retrieved from the Reference Source. Reflector is nice but can't hold a candle to actual commented source code.

    public static T EnsureInitialized<T>(ref T target) where T : class
    {
        // Fast path.
        if (target != null)
        {
            object barrierGarbage = s_barrier; // Insert a volatile load barrier. Needed on IA64.

            return target;
        }

        return EnsureInitializedCore<T>(ref target, LazyHelpers<T>.s_activatorFactorySelector);
    }

The naming choice gives some insight too in what the Microsoft programmer thought about the joy of writing code for the Titanium.



来源:https://stackoverflow.com/questions/8702335/volatile-local-variable-in-lazyinitializer-ensureinitialized

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!