I'm toying with the idea of writing a JIT compiler and am just wondering if it is even theoretically possible to write the whole thing in managed code. In particular, once you've generated assembler into a byte array how do you jump into it to begin execution?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Generic Generics in Managed C++
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
And for the full proof of concept here is a fully capable translation of Rasmus' approach to JIT into F#
that happily executes yielding
Yes, you can. In fact, it's my job :)
I've written GPU.NET entirely in F# (modulo our unit tests) -- it actually disassembles and JITs IL at run-time, just like the .NET CLR does. We emit native code for whatever underlying acceleration device you want to use; currently we only support Nvidia GPU's, but I've designed our system to be retargetable with a minimum of work so it's likely we'll support other platforms in the future.
As for performance, I have F# to thank -- when compiled in optimized mode (with tailcalls), our JIT compiler itself is probably about as fast as the compiler within the CLR (which is written in C++, IIRC).
For execution, we have the benefit of being able to pass control to hardware drivers to run the jitted code; however, this wouldn't be any harder to do on the CPU since .NET supports function pointers to unmanaged/native code (though you'd lose any safety/security normally provided by .NET).
Using unsafe code, you can "hack" a delegate and make it point to an arbitrary assembly code that you generated and stored in an array. The idea is that delegate has a
_methodPtr
field, which can be set using Reflection. Here is some sample code:This is, of course, a dirty hack that may stop working at any time when the .NET runtime changes.
I guess that, in principle, fully managed safe code cannot be allowed to implement JIT, because that would break any security assumptions that the runtime relies on. (Unless, the generated assembly code came with a machine-checkable proof that it does not violate the assumptions...)
The trick should be VirtualAlloc with the
EXECUTE_READWRITE
-flag (needs P/Invoke) and Marshal.GetDelegateForFunctionPointer.Here is a modified version of the rotate integer example (note that no unsafe code is needed here):
Full example (now works with both X86 and X64).