-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mixing C# and IL locals #23
Comments
Hi Victor! InlineIL doesn't let you access variables declared in C# that way primarily because that would produce very brittle code, as the compiler can decide to manage locals in unpredictable ways. For instance, a local can be present in Debug builds, but it could be entirely eliminated in Release builds if the compiler can use the stack instead. You couldn't also rely on the index of your local to be stable. Because of this, InlineIL lets you treat locals defined by Note that in your example, Still, you can access C# variables in InlineIL by using methods like Similarly, I'm not sure I understood you correctly though (I don't really understand the link between the example and your real use case), so let me know if something's still missing in that toolbox. |
With simple |
Probably this is what I've missed. |
I think with a ref local you can do anything you like on the target, but there's no method that would let you reassign the ref... I initially tried to write I can see if I can add a |
I was able to measure the impact of double inlining and it appears that the cost of Thanks for your help! I really like how easy it is to use this lib 😄 |
Yeah, the But I think you probably have a GC hole here since you're going through a I think I'll have to provide some kind of |
I do not understand why the second picture from here doesn't work #23 (comment) The stack should be balanced, we put two references on it in a loop, then pop outside the loop. The code is identical other than the loop... If it worked, I would really like a method:
So that there is no struct copying when accessing it's content for ref local. |
The evaluation stack doesn't work that way, its state needs to be statically defined at each instruction: See ECMA-335, §I.12.3.2.1:
|
It's somewhat 🤯 to deal with dotnet value stack and locals while working on implementing value stack and locals. Those code sample are from Lua interpreter, trying to move values between the stack and variables in the most efficient branchless way 😀 |
Haha yeah I can imagine 😅 Good luck with that! 😄 |
Thanks! It's already faster than C on SciMark benchmark. But absolutely meaningless timing of the benchmark is 1095, and you could guess what my obsession is and what a round number is the goal 😂 I have implemented kind of JIT, or an optimization phase, that rewrites instructions from stack-based to virtual-registers based ones. Could eliminate more than 25% of all instructions. Without that the timing is at 1460. I should probably continue with this direction, and not IL rewrite. Very fun experience overall. |
Hello Lucas!
I tried to use InlineIL for a painful case of working with ref locals, and found some limitations. A simplified sample below. I want to mix locals defined normally and via InlineIL. For ref locals, I really miss reference to reference similar to pointer to pointer and C# does not allow to initialize ref local in efficient way in my case. But after initialization, I would rather continue to use C#, not IL. The type under question if a struct with objects, so using
Unsafe.AsPointer
is dangerous and questionable.Here we define
baz
in C# and then add two additional locals via IL. The output locals will be merged as expected. I want to have access tobaz
from IL.Looking into
MethodLocals
implementation I think the fix could be simple. Even though Mono.Cecil does not support names of locals (or technically there are no names in IL), we could use indices.A potential fix is to add this:
![image](https://user-images.githubusercontent.com/489852/100514541-de925a00-3175-11eb-949a-00e0c6a60340.png)
This will create some complexity with indexing, because the required index will be the one from combined locals, not from IL-defined locals. And in the presence of local functions, like in the sample, there could be autogenerated locals. To get the right indices one will have to look into generated IL. Thankfully, in Rider, IL View is one click away and it shows IL after weaving. So this indexing behavior could be left as "by design".
But since it's the first time I look into this source code, I don't know if something else could break after the proposed change.
The real use case looks like this:
![image](https://user-images.githubusercontent.com/489852/100514725-4f864180-3177-11eb-9372-4a930dbfb229.png)
This is one of the hottest methods, and
GetLoadRef2
is not trivial. But it's still faster to have it as AggressivelyInlined. However, this generates twice as much of the assembly code. So the idea is to initialize ref locals in a loop to have theGetLoadRef2
inlined once.The text was updated successfully, but these errors were encountered: