1
4
我在模拟器中使用的模式是这样的:
这是一个简化,但想法是存在的。基本上,每次要求引擎执行“基本块”(通常是下一个流控制操作之前的所有操作或可能的整个功能)时,它都会查看是否已经创建了该块。如果是,执行它,否则创建它,添加它,然后执行。 冲洗重复: 至于代码生成,这有点复杂,但其思想是生成一个适当的“函数”,它在VM上下文中执行基本块的工作。 编辑:请注意,我也没有演示过任何优化,但您要求“温和介绍” 编辑2:我忘了提一个你能用这个模式实现的最快的生产力加速。基本上,如果你 从未 从树中删除一个块(如果这样做,您可以绕过它,但如果不这样做,则会简单得多),然后您可以将这些块“链接”在一起以避免查找。这是概念。每当您从f()返回并将要执行“update_instruction_pointer”时,如果您刚执行的块以调用、无条件跳转或根本没有以流控制结束,那么您可以使用直接JMP“修正”其RET指令到它将执行的下一个块(因为它始终是同一个块)。 如果 你已经发射了。这使得您在VM中执行的频率越来越高,而在“execute_block”函数中执行的频率越来越低。 |
2
2
我不知道任何与JIT特别相关的源代码,但是我认为它非常像一个普通的编译器,只有在您不担心性能的情况下才会更简单。 最简单的方法是从一个VM解释器开始。然后,对于每个VM指令,生成解释器将要执行的汇编代码。 除此之外,我设想您将解析VM字节代码并将其转换为某种合适的中间形式(三个地址代码?SSA?)然后像其他编译器一样优化和生成代码。 对于基于堆栈的VM,在将字节代码转换为中间形式时跟踪“当前”堆栈深度可能会有所帮助,并将每个堆栈位置视为一个变量。例如,如果您认为当前堆栈深度为4,并且看到一条“push”指令,那么您可能会生成一个“stack_variable_5”的赋值,并增加一个编译时堆栈计数器,或者类似的东西。当堆栈深度为5时,“添加”可能会生成代码“stack_variable_4=stack_variable_4+stack_variable_5”,并减少编译时堆栈计数器。 也可以将基于堆栈的代码转换为语法树。维护编译时堆栈。每一条“推”指令都会导致被推的对象的一个表示被存储在堆栈上。运算符创建包含其操作数的语法树节点。例如,“x y+”可能会导致堆栈包含“var(x)”,然后“var(x)var(y)”,然后加号会弹出var引用,并将其推送到“plus(var(x),var(y))”。 |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
rainer · 后台插入程序的初始化 1 年前 |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |