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

问题描述 投票:3回答:2

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

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

[是否有至少可以移植的方式,我可以实现以类似方式使用参数的指令,方法是将参数“注入”到push i的memcpy指令的每个实例中(因此,伪造的闭包位于运行时(?))或至少通过使用[setjmp / longjmp]的某种变体访问正在运行的实例的PC(尽管有人提及PC可能本质上是不可移植的)来让我读取PC值?编辑:通过在伪C(???)中执行以下操作,PC可能会很有用

char arg; char args[] = {1, 2, 3}; push: uintptr_t pc = get_pc(); arg = args[some_clever_hash(pc)]; stack.push(arg);

也许这样会更现实吗?:

char arg; char args[] = {1, 2, 3}; push: setarg(); stack.push(arg); void setarg(void) { uintptr_t pc = get_pc_of_caller(); arg = args[some_clever_hash(pc)]; }

我已经为(GNU)C中的基于堆栈的简单VM编写了字节码解释器。所有VM指令均实现为标签之间的代码。大多数指令不使用内联参数,因为它们只是...
c virtual-machine jit portability
2个回答
2
投票
一个好技巧可能是为您的推送代码提供两个“模板”-一个推送常量0x01020304,另一个推送常量0x10203040(对于32位常量)。然后对这两个模板进行异或运算-如果一切顺利,结果中除4个字节以外的所有字节都将为0,而这4个字节将为0x11、0x22、0x33和0x44,并确定要填充模板的哪4个字节用您的4个字节输入以生成任何特定常量的推入。如果模板的大小不同,或者除了这4个值以外,模板的方式不同,则您需要做其他事情。

1
投票
我不确定我是否理解这个问题,但是您真的不需要做任何与PC相关的事情,对吗?

bytecode

© www.soinside.com 2019 - 2024. All rights reserved.