Comments (13)
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 DeclareLocals
as always starting at index 0, and then remaps the indices of locals in emitted IL instructions to the real index (it actually appends the locals you define to the ones that already exist, and Ldloc_1
in your example would load the value of bar
). Changing this would be a major breaking change.
Note that in your example, baz
is not an int32
local in IL, but is wrapped in a "DisplayClass" struct because of the IncrBaz
method.
Still, you can access C# variables in InlineIL by using methods like IL.Push
. In your example, if you replace Ldloc_1();
with IL.Push(baz);
, you'll get baz
on the stack. ๐
Similarly, IL.Push(ref baz);
would push a ref to baz
on the stack, and you could use IL.Pop(out baz);
to assign the value on top of the stack to baz
.
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.
from inlineil.fody.
Yeah, the for
loop won't work, as you need to have a well-defined evaluation stack state for each basic block.
But I think you probably have a GC hole here since you're going through a void*
local... I guess it depends on the way this is going to get JITted. ๐
I think I'll have to provide some kind of PopRef
method or add something similar which would let you reassign a ref.
from inlineil.fody.
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.
from inlineil.fody.
With simple baz
as int I understood how to do things, but what is baz
was ref local, e.g. ref KeyValuePair<long,object> baz
? I think there are not enough overloads to store a value to such baz
, but maybe I missed something.
from inlineil.fody.
you could use IL.Pop(out baz); to assign the value on top of the stack to baz.
Probably this is what I've missed.
from inlineil.fody.
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 IL.Pop
as T Pop<T>()
but I had to change it to void Pop<T>(out T value)
since the other one didn't play very well with the compiler (it would emit code that did not lend itself to weaving very well). I guess I'd need to write a method like void Pop<T>(out ref T value)
but that's not a valid signature ๐ข
I can see if I can add a ref T PopRef<T>()
method, but I suppose if will prove difficult for the same reason as T Pop<T>()
didn't work.
from inlineil.fody.
Do you think this creates a GC hole? DynValue
is the same as KeyValuePair<long,object>
from GC perspective.
This doesn't work as on the picture. But if I was sure it's safe from GC point of view, I will work out pointer arithmetics, maybe even without IL.
from inlineil.fody.
So this works:
But it doesn't with the loop:
The stack should be balanced
from inlineil.fody.
I was able to measure the impact of double inlining and it appears that the cost of for
loop - additional local, int arithmetic, branch - is higher. Measured not exactly the same thing, but close, and will just leave two inlined methods. The main interest was to understand the impact. Sometimes very tiny obscure change improves (or kills) performance dramatically.
Thanks for your help! I really like how easy it is to use this lib ๐
from inlineil.fody.
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:
public ref T Ldlocal<T>(index or name)
// usage
if(Ldlocal<DynValue>(0).IsNumber && Ldlocal<DynValue>(1).IsNumber)
...
// same as:
ref DynValue B = ref ...
ref DynValue C = ref ...
if(B.IsNumber && C.IsNumber)
...
So that there is no struct copying when accessing it's content for ref local.
from inlineil.fody.
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:
The evaluation stack is made up of slots that can hold any data type, including an unboxed
instance of a value type. The type state of the stack (the stack depth and types of each element on
the stack) at any given point in a program shall be identical for all possible control flow paths.
For example, a program that loops an unknown number of times and pushes a new element on
the stack at each iteration would be prohibited.
from inlineil.fody.
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 ๐
from inlineil.fody.
Haha yeah I can imagine ๐ Good luck with that! ๐
from inlineil.fody.
Related Issues (20)
- MethodRef to overloaded generic method HOT 4
- InlineIL produces corrupted portable PDB file HOT 11
- Using Calli() causes a build error in Debug configuration HOT 6
- Support .NET Standard 1.1 HOT 13
- Proposal: simplified arguments passing and first-class support of in parameters HOT 27
- nop after any Il HOT 2
- Loading of invalid method token HOT 4
- InlineIL.Fody and .NET Core 3.1 HOT 17
- [Feature] Would it be possible to declare fields? HOT 23
- [Proposal] Simplified ldftn/ldvirtftn HOT 14
- [Proposal] Referencing user-defined operators HOT 14
- Proposal: macroassembler-like support HOT 3
- IL.Push(expression) leads to invalid program HOT 2
- Error in .NET 7 Preview 7 HOT 7
- Creating labels in otherwise unreachable code fails HOT 3
- Usage Suggestion HOT 3
- Issue with calling T[] Span<T>.ToArray() HOT 7
- .NET 8 and static BLOB pattern using ROS<T> HOT 4
- Add a way to get a TypeRef from an assembly at provided path HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from inlineil.fody.