I was wondering how field pinning is expressed in .Net IL, so I looked at an example code:
struct S { public fixed int buf[8]; } S s = default(S); public void MyMethod() { fixed (int* ptr = s.buf){ *ptr = 2; } }
This generates IL:
.method private hidebysig instance void MyMethod () cil managed { // Method begins at RVA 0x2050 // Code size 25 (0x19) .maxstack 2 .locals init ( [0] int32& pinned ) IL_0000: ldarg.0 // Load argument 0 onto the stack IL_0001: ldflda valuetype C/SC::s // Push the address of field of object obj on the stack IL_0006: ldflda valuetype C/S/'<buf>e__FixedBuffer' C/S::buf // Push the address of field of object obj on the stack IL_000b: ldflda int32 C/S/'<buf>e__FixedBuffer'::FixedElementField // Push the address of field of object obj on the stack IL_0010: stloc.0 // Pop a value from stack into local variable 0 IL_0011: ldloc.0 // Load local variable 0 onto stack IL_0012: conv.i // Convert to native int, pushing native int on stack IL_0013: ldc.i4.2 // Push 2 onto the stack as int32 IL_0014: stind.i4 // Store value of type int32 into memory at address IL_0015: ldc.i4.0 // Push 0 onto the stack as int32 IL_0016: conv.u // Convert to native unsigned int, pushing native int on stack IL_0017: stloc.0 // Pop a value from stack into local variable 0 IL_0018: ret // Return from method, possibly with a value } // end of method C::MyMethod
I don’t see anything here, I will explicitly tell GC to bind an array, which instruction is actually responsible for committing? In addition, are there other basic operations that are associated with fixing “under the hood”?
c # cil pinvoke
torgabor
source share