简体   繁体   English

关闭 JIT,并控制 MSIL(自己的 VM)中的代码流

[英]Turning off JIT, and controlling codeflow in MSIL (own VM)

I'm writing my own scripting language in C#, with some features I like, and I chose to use MSIL as output's bytecode (Reflection.Emit is quite useful, and I dont have to think up another bytecode).我在 C# 中编写自己的脚本语言,具有一些我喜欢的功能,并且我选择使用 MSIL 作为输出的字节码(Reflection.Emit 非常有用,我不必想出另一个字节码)。 It works, emits executable, which can be run ( even decompiled with Reflector:) )and is quite fast.它可以工作,发出可执行文件,可以运行(甚至可以使用 Reflector 反编译:))并且速度非常快。

But - I want to run multiple 'processes' in one process+one thread, and control their assigned CPU time manually (also implement much more robust IPC that is offered by .NET framework) Is there any way to entirely disable JIT and create own VM, stepping instruction-after-instruction using .NET framework (and control memory usage, etc.), without need to write anything on my own, or to achieve this I must write entire MSIL interpret?但是 - 我想在一个进程+一个线程中运行多个“进程”,并手动控制它们分配的 CPU 时间(还实现 .NET 框架提供的更强大的 IPC)有没有办法完全禁用 JIT 并创建自己的 VM , 使用 .NET 框架(并控制 memory 使用等)的指令后指令步进,无需我自己编写任何东西,或者要实现这一点我必须编写整个 MSIL 解释?

EDIT 1): I know that interpreting IL isn't the fastest thing in the universe:)编辑 1): 我知道解释 IL 并不是世界上最快的事情:)

EDIT 2): To clarify - I want my VM to be some kind of 'operating system' - it gets some CPU time and divides it between processes, controls memory allocation for them, and so on.编辑2):澄清-我希望我的VM成为某种“操作系统”-它获得一些CPU时间并将其分配给进程,控制memory为它们分配,等等。 It doesnt have to be fast, nor effective, but just a proof of concept for some of my experiments.它不必很快,也不必有效,而只是我的一些实验的概念证明。 I dont need to implement it on the level of processing every instruction - if this should be done by .NET, I wont mind, i just want to say: step one instruction, and wait till I told you to step next.我不需要在处理每条指令的层面上实现它——如果这应该由 .NET 完成,我不介意,我只想说:第一步指令,等到我告诉你下一步。

EDIT 3): I realized, that ICorDebug can maybe accomplish my needs, now looking at implementation of Mono's runtime.编辑 3):我意识到,ICorDebug 可能可以满足我的需求,现在查看 Mono 运行时的实现。

You could use Mono - I believe that allows an option to interpret the IL instead of JITting it.您可以使用Mono - 我相信这允许一个选项来解释 IL 而不是 JITting 它。 The fact that it's open source means (subject to licensing) that you should be able to modify it according to your needs, too.它是开源的这一事实意味着(取决于许可)您也应该能够根据自己的需要对其进行修改。

Mono doesn't have all of .NET's functionality, admittedly - but it may do all you need.诚然,Mono 不具备 .NET 的所有功能 - 但它可能满足您的所有需求。

One thing you could consider doing is generating code in a state-machine style.您可以考虑做的一件事是以状态机样式生成代码。 Let me explain what I mean by this.让我解释一下我的意思。

When you write generator methods in C# with yield return, the method is compiled into an inner IEnumerator class that implements a state machine.当您在 C# 中使用 yield return 编写生成器方法时,该方法将编译到实现 state 机器的内部 IEnumerator class 中。 The method's code is compiled into logical blocks that are terminated with a yield return or yield break statement, and each block corresponds to a numbered state.该方法的代码被编译成以yield return或yield break语句终止的逻辑块,每个块对应一个编号为state。 Because each yield return must provide a value, each block ends by storing a value in a local field.因为每个收益返回都必须提供一个值,所以每个块都以在本地字段中存储一个值结束。 The enumerator object, in order to generate its next value, calls a method that consists of a giant switch statement on the current state number in order to run the current block, then advances the state and returns the value of the local field.枚举器 object 为了生成它的下一个值,调用一个由当前 state 编号上的巨型 switch 语句组成的方法,以便运行当前块,然后推进 Z9ED39E2EA931586B6A985A6942EF57 的值并返回。

Your scripting language could generate its methods in a similar style, where a method corresponds to a state machine object, and the VM allocates time by advancing the state machine during the time allotted.您的脚本语言可以以类似的方式生成其方法,其中方法对应于 state 机器 object,并且 VM 通过在此期间推进 state 机器来分配时间。 A few tricky parts to this method: implementing things like method calls and try/finally blocks are harder than generating straight-up MSIL.这个方法有一些棘手的部分:实现方法调用和 try/finally 块比直接生成 MSIL 更难。

Beware that MSIL was designed to be parsed by a JIT compiler.请注意,MSIL 被设计为由 JIT 编译器解析。 It is not very suitable for an interpreter.它不太适合口译员。 A good example is perhaps the ADD instruction.一个很好的例子可能是 ADD 指令。 It is used to add a wide variety of value type values: byte, short, int32, int64, ushort, uint32, uint64.它用于添加多种值类型值:byte、short、int32、int64、ushort、uint32、uint64。 Your compiler knows what kind of add is required but you'll lose that type info when generating the MSIL.您的编译器知道需要什么样的添加,但在生成 MSIL 时您会丢失该类型信息。

Now you need to find it back at runtime and that requires checking the types of the values on the evaluation stack.现在您需要在运行时找到它,这需要检查评估堆栈上的值的类型。 Very slow.非常慢。

An easily interpreted IL has dedicated ADD instructions like ADD8, ADD16, etc.易于解释的 IL 具有专用的 ADD 指令,例如 ADD8、ADD16 等。

Microsofts implementation of the Common Language Runtime has only one execution system, the JIT. Microsoft 的公共语言运行时实现只有一个执行系统,即 JIT。 Mono, on the other hand comes with both, a JIT and an interpreter.另一方面,Mono 同时带有 JIT 和解释器。

I, however, do not fully understand what exactly you want to do yourself and what you would like to leave to Microsofts implementation:但是,我并不完全了解您自己到底想做什么以及您希望将什么留给微软的实施:

Is there any way to entirely disable JIT and create own VM?有没有办法完全禁用 JIT 并创建自己的 VM?

and

... without need to write anything on my own, or to achieve this I must write entire MSIL interpret? ...无需我自己写任何东西,或者为了实现这一点,我必须编写整个 MSIL 解释?

is sort of contradicting.有点矛盾。

If you think, you can write a better execution system than microsofts JIT, you will have to write it from scratch.如果你认为,你可以写出比微软的 JIT 更好的执行系统,你将不得不从头开始编写它。 Bear in mind, however, that both microsofts and monos JIT are highly optimized compilers.但是请记住,microsoft 和 monos JIT 都是高度优化的编译器。 (Programming language shootout) (编程语言枪战)

Being able to schedule CPU time for operating system processes exactly is not possible from user mode.在用户模式下,无法准确地为操作系统进程安排 CPU 时间。 That's the operating systems task.这就是操作系统的任务。

Some implementation of green threads might be an idea, but that is definitely a topic for unmanaged code.一些绿色线程的实现可能是一个想法,但这绝对是非托管代码的主题。 If that's what you want, have a look at the CLR hosting API.如果这是您想要的,请查看托管 API 的 CLR。

I would suggest, you try to implement your language in CIL.我建议您尝试在 CIL 中实现您的语言。 After all, it gets compiled down to raw x86.毕竟,它被编译成原始的 x86。 If you don't care about verifiability, you can use pointers where necessary.如果您不关心可验证性,则可以在必要时使用指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM