Assembly x86最快的虚拟机设计是什么?

Assembly x86最快的虚拟机设计是什么?,assembly,x86,vm-implementation,Assembly,X86,Vm Implementation,我将在x86中实现一个虚拟机,我想知道哪种设计会产生最好的结果。我应该集中精力做什么才能挤出果汁?我将在x86汇编中实现整个虚拟机 我没有太多说明,我可以选择它们的形式。这些指令以块的形式直接投射到smalltalk的语法中。我给出了我想到的教学设计: ^ ... # return ^null # return nothing object # address to object ... selector: ... # message pass (in this cas

我将在x86中实现一个虚拟机,我想知道哪种设计会产生最好的结果。我应该集中精力做什么才能挤出果汁?我将在x86汇编中实现整个虚拟机

我没有太多说明,我可以选择它们的形式。这些指令以块的形式直接投射到smalltalk的语法中。我给出了我想到的教学设计:

^ ...       # 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块的解释方式不同:

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
]
A:=B子类:[
定义a:x[^x*x]
clmet b[…]
def c[…]
def d[…]
]
[2

我需要解释例程带来的真正好处,那就是选择阅读程序的上下文。当然,好的编译器应该在大多数情况下编译明显的情况,如:“ifTrue:ifFalse”或“whileTrue:”或列表示例。对解释器的需求不会消失,因为你总是会遇到这样的情况,即你无法确保程序块得到你所期望的处理。

解释器的关键在于在大多数情况下的可移植性。我能想到的最快的方法是直接在内存中生成x86代码,就像JIT编译器一样,但是,当然,您不再有解释器了。你有一个编译器


然而,我不确定用汇编语言编写解释器是否能给您带来最好的性能(除非您是汇编专家,并且您的项目范围非常有限)。使用更高级的语言可以帮助您专注于更好的算法,例如,符号查找和寄存器分配策略。

我不得不问,为什么要创建一个注重性能的虚拟机?为什么不直接编写x86代码呢?没有比这更快的了


如果您想要一种非常快速的解释语言,请查看。他们的设计非常整洁,也很容易复制。

如果你想要快速的东西,试着使用。它可以从高级程序描述为大多数处理器生成本机代码。您可以使用自己的汇编语言,也可以跳过汇编阶段生成llvm结构,这取决于您觉得最方便的方式


我不确定它是否最适合您的问题,但如果我要执行一些性能关键的代码,而这些代码不能与程序的其余部分一起编译,我肯定会使用它。

如果您不喜欢JIT,并且您的目标不是可移植性。我想你们可能会对谷歌项目感兴趣。他们做静态分析,沙箱和其他。它们允许主机执行原始x86指令

我看到这里有一些关于可移植性的混淆,所以我觉得有必要澄清一些问题。这些是我的拙见,所以你当然可以自由地反对它们

我认为如果你认真考虑写一个虚拟机,你就来了,所以我不会详述所描述的技术。

前面已经提到过,以VM为目标具有一些优势,例如减少代码大小、降低编译器复杂性(通常转化为更快的编译)、可移植性(请注意,VM的要点是语言的可移植性,因此VM本身是否不可移植并不重要)

考虑到示例的动态特性,和其他更流行的编译器相比,您的VM更类似于JIT编译器。所以,虽然S.洛特没有抓住这一点,但他提到福斯的时候非常当场。如果我要为一种非常动态的语言设计一个VM,我会将解释分为两个阶段

  • 一个生产者阶段,它根据需要查询AST流,并将其转换为更有意义的形式(例如,获取一个块,决定是立即执行还是存储在某个地方以便以后执行),可能引入新的令牌类型。实际上,您可以恢复在这里解析时可能丢失的上下文敏感信息

  • 消费者阶段从1获取生成的流,并像任何其他机器一样盲目地执行它。如果您让它像这样向前移动,您只需推送一个存储的流并完成它,而不是在指令指针上跳来跳去

  • 正如你所说,仅仅以另一种方式模仿该死的处理器的工作方式并不能实现你所需要的任何动态性(或任何其他值得一提的特性,比如安全性)。否则,您将编写编译器


    当然,您可以在阶段1中任意添加comlex优化。

    您可以通过将未编码指令设置为:

    mov eax, [esi]
    add esi, 4
    add eax, pOpcodeTable
    jmp eax
    
    在cpu的奔腾4上,每次调度的开销应小于4个周期

    此外,出于性能原因,最好在每个基本例程中递增ESI(IP),因为递增很可能与其他指令配对:

    mov eax, [esi]
    add eax, pOpcodeTable
    jmp eax
    

    ~1-2个周期的开销。

    因为我需要以多种方式解释指令。我能想到的关于便携性的另一个原因是,需要真正方便,或者使用更具体的指令来节省空间。除了虚拟机生成器的形式外,这些都是你无法轻松转化为库的东西。@Cheery:“我的目标不是可移植性”与“我能想到的另一个关于可移植性的原因”。因此,可移植性并不重要,而是首要考虑因素。“用更具体的指令节省空间”是编译器最擅长的。我对可移植性不感兴趣