Local local variable in LazyInitializer.EnsureInitialized?

I looked at LazyInitializer.EnsureInitialized(ref T, Func{T}) in Reflector, and this method has an unstable local variable volatile object local1 = s_barrier; I can think of two possible reasons for this:

  • .NET may use features that are not supported by this language, or

  • The actual code does not declare a mutable local variable, but when the compiled code decompiles Reflector, it looks like a mutable local variable.

Does anyone know what is here (or maybe some other explanation)? If this is a matter of decompilation, does anyone have an idea of ​​what the "true" code looks like?

+4
source share
2 answers

It looks like a reflector error: it's just a normal volatile reading of the s_barrier field. There is no "special" IL that is not expressed in C #.

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

This is regular code that the compiler emits when reading from a static unstable field.


It’s easier to reproduce here: just compile the following (wrapped in type) in release mode:

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

Reflector creates the following decompiled C #:

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

when IL really:

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

UPDATE : Here I guess what happens: in release mode, the C # compiler optimizes the distribution of the field value (the result of a mutable read) to a local variable ( stloc instruction), since the local one is not used later, It seems to confuse the reflector. If you changed the method of using subsequent use of local, the stloc command (or similar) would indeed stloc , after which the decompiled output from Reflector would look reasonable.

+2
source

Ani is right. This is the actual source code obtained from the Reference Source . A reflector is good, but cannot hold a candle in the 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 choice of naming gives some insight into what the Microsoft programmer thought about the joy of writing code for Titanium.

+1
source

Source: https://habr.com/ru/post/1388947/


All Articles