IL for binding the value of ref T as void * (for working with Span <T> from parallel code)

Before the current question, a small reservation:

This is the related / next question of this , but since I'm talking about a more general problem (how to bind the variable ref T to be able to perform pointer operations on it), and I suggest a possible (possibly incorrect) solution, I opened a separate question.

So, the question is: the variable ref T (suppose this is the first element of the array), how can I bind it so that the GC does not cause problems when working with the base array with unsafe pointers?

I'm not sure if this is possible in C # (but I hope I'm wrong), but looking at the IL code for a method that just fixes the ref int variable, I tried to come up with a variant that worked on type types. Here is my idea:

Suppose I have this delegate in the "MyTestClass" class:

 public unsafe delegate void UnsafeAction(void* p); 

Then in IL:

 .method public hidebysig static void Foo<valuetype .ctor (class [netstandard]System.ValueType) T>( !!0/*T*/& r, class MyTestClass/UnsafeAction action ) cil managed { .maxstack 2 .locals init ( [0] void* p, [1] !!0/*T*/& pinned V_1 ) // Load the ref T argument into the pinned variable (as if fixed were used) IL_0000: nop IL_0001: ldarg.0 // r IL_0002: stloc.1 // V_1 // Cast the T* pointer to void* IL_0003: ldloc.1 // V_1 IL_0004: conv.u IL_0005: stloc.0 // p // Invoke the action passing the p pointer IL_0006: ldarg.1 // action IL_0007: ldloc.0 // p IL_0008: callvirt instance void MyTestClass/UnsafeAction::Invoke(void*) IL_000d: nop // Set the pinned variable V_1 to NULL IL_000e: ldc.i4.0 IL_000f: conv.u IL_0010: stloc.1 // V_1 IL_0011: ret } 

The idea would be to use this method as follows:

 public static void Test<T>(this Span<T> span, Func<T> provider) { void Func(void* p) { // Do stuff with p, possibly in parallel // eg. Unsafe.Write(p, provider()); } Foo(ref span.DangerousGetPinnableReference(), Func); } 

Something like this work? If so, what is the best way to incorporate such a method written in IL into an existing .NET Standard 2.0 project?

Thanks!

Bonus question . I saw a CoreFX repo using .ilproj files for projects with IL classes, but they are not actually supported by VS. Is this some kind of extension or do they use their own scripts to support this project format? I know that there is an ILProj extension , but it is not official and is not compatible with VS2017.

Change Perhaps I had an idea on how to solve this problem, think about this:

 public static void Foo<T>(ref T value) { fixed (void* p = &Unsafe.As<T, byte>(ref value)) { // Shouldn't the ref T be correctly fixed here, since // the "dummy" byte ref had the same address? } } 
0
source share
1 answer

Yes, storing the link in the attached local is enough. During the execution of the method, the reference memory will not be moved, and therefore the pointer will remain valid.

You can also remove nop from your method (the result of analyzing code compiled in Debug), and also set a null variable after that, because the method exists immediately after it.

Regarding how to distribute CIL code with a C # project, I would use DynamicMethod, but I don't know if this is available in .NET Standard. If not, compiling IL to .dll or .netmodule and .netmodule to it or automatically linking it to the main project is not such a big problem.

0
source

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


All Articles