是否可以在不使用汇编的情况下用C在字节码解释器中实现JIT?

我已经在(GNU)C中为简单的基于堆栈的VM编写了字节码解释器。所有VM指令均实现为标签之间的代码。大多数指令不使用内联参数,因为它们只是将其从VM堆栈中弹出(例如add从堆栈中弹出两个数字ab并重新推入a+b

我认为JIT就像识别字节码中的基本块一样简单,只需通过memcpy将标签之间的标签插入使用{{1}标记为可执行文件的缓冲区中,即可将指令实现缝合在一起,从而生成“动态超级指令” } / mmap。这对除mprotect指令以外的所有指令均有效,该指令将字节码流的下一个字节推入VM堆栈(例如push b)。

有没有至少某种可移植的方式来实现以类似方式使用参数的指令,方法是将参数“注入”到push 17指令的每个实例中(因此在运行时伪造关闭(?)),或者至少通过某种方式使用setjmp / longjmp的某些变体访问正在运行的实例的PC(尽管提及PC可能固有地不是可移植的)我读了PC值吗?

编辑:通过在伪C(???)中执行以下操作,PC可能会很有用

push

也许这样会更现实?

memcpy
abiaoa 回答:是否可以在不使用汇编的情况下用C在字节码解释器中实现JIT?

一个好技巧可能是为您的推送代码提供两个“模板”-一个推送常量0x01020304,另一个推送常量0x10203040(对于32位常量)。然后对这两个模板进行异或运算-如果一切顺利,结果中除4个字节以外的所有字节都将为0,而这4个字节将为0x11、0x22、0x33和0x44,并确定要填充模板的哪4个字节用您的4个字节输入以生成任何特定常量的推入。如果模板的大小不同,或者除了这4个值以外,模板的方式不同,则您知道您需要做其他事情。

,

我不确定我是否理解这个问题,但是您真的不需要做任何与PC相关的事情,对吗? 字节码中只有这种方式。您真正需要的是将即时(适当大小)推入VM堆栈的实现,以及每个体系结构的fixup函数。该实现可以推送任意任意值(尽管为了通用起见,您可能应避免使用诸如0之类的值,这些值可能具有更有效的编码,实际上,您最好的选择可能是诸如{{ 1}}),然后fixup函数使用字节码中的适当常量处理替换实现的某些字节。显然,哪个字节到达哪里,以及字节序交换等内容的详细信息将根据CPU体系结构和实现而有所不同。显然,在这里很难实现可移植性,并且必须以一种艰难的方式来收集细节,但是一旦对给定系统执行了此操作,就可以添加一个0x01020304,该assert的字节位于在实施模板中的预期位置。 (甚至可以生成具有两个不同值的两个版本,以提高安全性)。这样,如果您的实现发生变化,至少您可以在编译阶段的早期进行轰炸,而不必在运行时执行错误的代码。

本文链接:https://www.f2er.com/3169617.html

大家都在问