我将在 x86 中实现一个虚拟机,我想知道什么样的设计会产生最好的结果。我应该集中注意什么才能挤出果汁?我将在 x86 汇编中实现整个虚拟机。
我没有太多说明,我可以选择它们的形式。这些指令直接转换到smalltalk 的语法 block 中。我给出我想到的教学设计:
^ ... # return
^null # return nothing
object # address to object
... selector: ... # message pass (in this case arity:1 selector: #selector:)
var := ... # set
var # get
我正在考虑的虚拟机类型:
mov eax, [esi]
add esi, 2
mov ecx, eax
and eax, 0xff
and ecx, 0xff00 # *256
shr ecx, 5 # *8
jmp [ecx*4 + operations]
align 8:
operations:
dd retnull
dd ret
# so on...
retnull: # jumps here at retnul
# ... retnull action
ret:
# ... ret action
#etc.
不要开始问为什么我需要另一个虚拟机实现。解释例程并不是你需要时就可以拿起的库存东西。您在其他地方建议的大多数虚拟机都注重可移植性和性能成本。我的目标不是便携性,我的目标是性能。
之所以需要这个解释器,是因为 Smalltalk block 最终不会以相同的方式被解释:
A := B subclass: [
def a:x [^ x*x]
clmet b [...]
def c [...]
def d [...]
]
[ 2 < x ] whileTrue: [...]
(i isNeat) ifTrue: [...] ifFalse: [...]
List fromBlock: [
"carrots"
"apples"
"oranges" toUpper
]
我需要来自解释例程的真正好处,即选择在其中读取程序的上下文。当然,好的编译器应该在大多数情况下编译明显的情况,例如:“ifTrue:ifFalse”或'whileTrue:',或列表示例。对口译员的需求并不会消失,因为您总是可能会遇到无法确定该 block 得到您期望的处理的情况。
最佳答案
我发现这里对可移植性存在一些困惑,所以我觉得有必要澄清一些问题。这些是我的拙见,所以你当然可以自由地反对它们。
我假设您遇到过http://www.complang.tuwien.ac.at/forth/threading/如果您认真考虑编写虚拟机,那么我不会详细讨论所描述的技术。
已经提到,以 VM 为目标具有一些优势,例如减少代码大小、降低编译器复杂性(通常转化为更快的编译)、可移植性(请注意,VM 的重点是语言的可移植性,所以如果虚拟机本身不可移植也没关系)。
考虑到您的示例的动态特性,您的虚拟机将比其他更流行的编译器更类似于 JIT 编译器。所以,虽然S.Lott在这个例子中没有捕获要点,但他对福斯的提及却非常恰到好处。如果我要为一种非常动态的语言设计一个 VM,我会将解释分为两个阶段;
生产者阶段,根据需要查询 AST 流并将其转换为更有意义的形式(例如,获取一个 block ,决定是否应该立即执行它或存储在某个地方以供以后执行),可能会引入新类型的代币。本质上,您可以恢复在此处解析时可能丢失的上下文敏感信息。
消费者阶段从 1 获取生成的流并像任何其他机器一样盲目执行它。如果你像 Forth 那样,你可以只推送一个存储的流并完成它,而不是跳跃指令指针。
正如您所说,仅以另一种方式模仿该死的处理器的工作方式并不能实现您所需的任何动态(或任何其他值得该死的功能,例如安全性)。否则,您将编写一个编译器。
当然,您可以在第 1 阶段添加任意复杂的优化。
关于assembly - x86 最快的虚拟机设计是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/435141/