为什么VM需要是“堆栈计算机”或“注册计算机”等?


48

(这是一个极其新手的问题)。

我一直在研究有关虚拟机的知识。

事实证明,其中许多设计与物理或理论计算机非常相似。

例如,我读到JVM是一个“堆栈机”。这意味着(如果我错了,请纠正我)是它将所有的“临时内存”存储在堆栈中,并对所有操作码在该堆栈上进行操作。

例如,源代码2 + 3将被转换为类似于以下内容的字节码:

push 2
push 3
add

我的问题是这样的:

JVM可能是使用C / C ++等编写的。如果是这样,JVM为什么不执行以下C代码:2 + 3..?我的意思是,为什么它需要堆栈,或在其他虚拟机“寄存器”中(例如在物理计算机中)?

底层的物理CPU负责所有这些工作。VM编写者为什么不使用VM编程所使用的语言简单地使用“通常”指令执行解释后的字节码?

当实际的硬件已经为我们做到了时,为什么虚拟机需要仿真硬件?

同样,非常新手的问题。谢谢你的帮助


5
您是否考虑过虚拟机基于什么?

5
@MichaelT您的意思是物理机?
Aviv Cohn 2014年

当然,大多数Javascript VM都不是堆栈机或注册机-V8 / IonMonkey / Chakra等是实现Javascript的VM。“ VM”只是解释器或JIT编译器,可以实现设计人员所需的任何语言。
Billy ONeal 2014年

@BillyONeal例如,如果我正在为某种语言编写VM,并以C编写它:VM解析字节码行'print“ hi”'并执行printf("hi");:这是否被视为VM?它没有“堆栈”或“寄存器”或其他任何内容。
Aviv Cohn 2014年

@Prog:是的,是的。
Billy ONeal 2014年

Answers:


51

不论虚拟与否,一台机器都需要一个计算模型,模型描述了如何在其上进行计算。根据定义,它一经计算就实现某种计算模型。问题是:我们应该为虚拟机选择哪种模型?物理机器受到可以在硬件中有效完成的工作的约束。但是,正如您所注意到的,虚拟机没有这样的约束,它们是使用任意高级语言在软件中定义的。

实际上,您所描述的虚拟机是高级的。它们被称为编程语言。例如,C标准将其页面的大部分专用于定义所谓的“ C抽象机”的模型,该模型描述C程序的行为,并通过扩展(按规则)(遵循规则)来遵循C编译器(或解释器)的方式应该表现。

当然,我们通常不将其称为虚拟机。VM通常指的是更底层的,更接近硬件的东西,并非旨在直接编程,而是旨在有效执行。这种选择偏差意味着接受高级可组合代码(例如您所描述的内容)的东西将不被视为VM,因为它会执行高级代码。

但是要弄清楚点,这里有一些使VM(例如,字节码编译器所针对的对象)基于寄存器的原因。堆叠和套准机非常简单。每条指令都有一系列指令,一些状态和语义(一个功能State-> State)。没有复杂的树缩减,没有运算符优先级。解析,分析和执行它非常简单,因为它是一种最少的语言(语法糖已被编译掉)并且被设计为机器可读而不是人类可读。

相反,即使解析最简单的类C语言也非常困难,并且执行它需要非本地分析,例如检查和传播类型,解决重载,维护符号表,解决字符串标识符,将线性文本转换为优先驱动的AST。 , 等等。它建立在人类自然而然的概念上,但必须经过机器的艰苦反向工程。

例如,JVM字节码由发出javac。实际上,它几乎不需要人类读写,因此很自然地使其适应机器的使用。如果你优化它对于人类来说,在JVM只会在每次启动时读取代码,解析它,分析是,然后将其转换成中间表示类似这样的简化机型反正。最好也切掉中间人。


因此,您要说的是,将所有内容编译为堆栈上的指令(即System.out.println("hi");,编译为堆栈上的某个指令,int a = 7编译为堆栈上的指令,等等)使程序执行起来更简单,更高效吗?
Aviv Cohn 2014年

2
@Prog基本上是。但不仅仅是执行,还有分析。以编程方式完成的所有操作。

不过,我仍然不明白为什么2 + 3将其编译为push 2 push 3 addadd无论如何,最后的步骤是由JVM通过运行C代码来执行的2 + 3。JVM的程序员没有其他方法可以做到这一点。为什么不将其编译为2 + 3,让JVM立即执行C代码2 + 3(假设它是用C编写的)?
Aviv Cohn 2014年

@Prog JVM作者不能只写2 + 3JVM源代码,因为JVM必须与以任何顺序进行任何操作的任何程序一起使用。构建C源代码并推迟使用C实现只会将相同的问题推入C实现中(而且不容易实现,更不用说高效了)。必须有一些描述程序的数据结构,以便可以对其进行解释和JIT编译,并且由于上述原因,“人类可读的源代码”是对数据结构的糟糕选择。

7
@Prog您似乎过于关注2 + 3的特定情况a + b。然后要添加的值不来自i.argument{1,2},而是从局部变量加载。那frobnicate(x[i]) + (Foo.bar() * 2)呢 使用这种设计,只有一个add运算int符(for ),它的工作方式与加数的计算方式无关。另外,添加整数文字的指令将毫无意义:它的结果也可以预先计算(即add(2,3)应为而不是push(5))。

20

这个答案主要针对JVM,但实际上它适用于任何VM。

当实际的硬件已经为我们做到了时,为什么虚拟机需要仿真硬件?

它们没有,但是它使VM更加简单和可移植:与硬件CPU相比,模拟硬件的VM可以使用相同的计算模型。

尤其是考虑到可移植性而构建的JVM,实际上,它的构建是为了使其甚至可以在硬件中实现(今天很难相信,但是Java起源是在嵌入式世界中-特别是交互式电视的控制器)。 )。

如果您有这样的目标,则希望VM在尽可能接近物理机的地方运行,因为转换为实际的机器代码会变得更容易,从而也更快。从理论上讲,一旦有了VM的操作码,您要做的就是将其转换为程序实际运行所在的CPU的操作码。实际上,这并非那么简单。

我的意思是,为什么它需要堆栈,或在其他虚拟机“寄存器”中(例如在物理计算机中)?

使用基于堆栈的虚拟机模型的优点是可以轻松地将其转移到寄存器机和堆栈机上,而相反的情况不一定成立。基于寄存器的VM将需要对寄存器的数量,寄存器的大小等进行假设。对于堆栈计算机,无需进行此类假设。

底层的物理CPU负责所有这些工作。VM编写者为什么不使用VM编程所使用的语言简单地使用“通常”指令执行解释后的字节码?

嗯,这些VM就是这样做的,它们解释字节码。甚至JVM实际上都至少在JIT(即时)启动之前这样做:它解释字节码并以JVM编写的语言(通常为C或C ++)执行语句,但是甚至编写了一个在JavaScript中,Doppio)。但是请注意,即使这样的语句也由编译器翻译成机器代码,实际上看起来与Java编译器产生的内容非常相似-即它们使用寄存器和堆栈来执行其工作。请注意,此时“解释”与“编译”语言的使用变得有些模糊


当然,任何可以用软件实现的东西都可以用硬件实现。此外,目前的JVM(热点)是JIT编译器-它并没有在JVM写于语言执行语句如果那样,将Java的可怕执行和将远不及可行的平台,因为它是今天。 。(地狱,大多数Javascript实现会更快)
Billy ONeal 2014年

2
@BillyONeal“ Java HotSpot VM不会立即按方法进行编译,而是立即使用解释器运行程序,并在运行时分析代码以检测程序中的关键热点。然后,它将重点放在全球热点上的本地代码优化器。”引用自oracle.com/technetwork/java/whitepaper-135217.html#2,“热点检测”部分
miraculixx,2014年

是。“本机代码优化器” == JIT编译。对于代码,有一个解释器阶段,该阶段似乎并不“热”,以避免JIT处理很少使用的东西。但这并不意味着完全没有JITing。
Billy ONeal 2014年

谢谢回答。我从您的答案中收集到的信息是,在VM中模拟硬件(也称为“堆栈”或“寄存器”等)的原因是因为它使得以后可以轻松将字节码或源代码编译为虚拟机的实际机器代码。物理CPU。但是,除此之外,在VM中模拟硬件还有什么好处?我仍然不明白为什么设计虚拟机的人会以“堆栈机”或“注册机”等来思考,而实际上我们在谈论软件。我想念什么吗?
Aviv Cohn 2014年

@Prog好,您有一种编程语言,说X。您将如何运行其程序?您可以解释源代码或将其编译为机器代码,或将其编译为某些中间代码。现在,您有了另一种编程语言Y,并希望使用X来实现它。如果两个实现都是解释器,则将在X的解释器上运行Y的解释器,这将非常慢。
18446744073709551615 2014年

11

为什么VM需要是“堆栈计算机”或“注册计算机”等?

他们不。如果您需要虚拟机,则可以是任何东西。

现有的虚拟机已成为解决以下问题的解决方案:我想到了一个非常绝妙的主意,我发明了一种新的编程语言!但是我必须生成代码。(多么无聊的任务!)但是我不想生成i8086代码,因为它很丑陋,并且我不想生成68k代码,因为其他所有人都在使用Intel。还有VAX,但我没有任何VAX,既没有计算机也没有VAX书。因此,我将为物理上不存在的某些处理器生成代码,并以软件实现该处理器。该VM的规格将在我的论文中占据一章。从理论上讲,可以将其编译为任何处理器的本机代码,但这不是我自己。

另一方面,在可预见的将来,诸如“ 2 + 3”之类的符号可能不会被VM使用,因为它意味着在执行某些操作之前要进行大量转换。


谢谢回答。因此,我从您的答案中得出的结论是,设计可模拟物理CPU的VM的动机是因为它使以后实现编译为实际机器代码的编译器变得容易。除此之外,在“堆栈机”或“注册机”等方面设计VM是否有任何优势?
Aviv Cohn 2014年

1
寄存器需要寄存器分配算法,这需要理论和调试。堆栈计算机(尤其是零操作数的堆栈计算机)可以将数据放在堆栈上。OTOH,硬件通常实现数量有限的寄存器,而不是可变大小的堆栈。因此,堆栈对软件来说更容易,寄存器对硬件来说更容易,因此可能更快一些。
18446744073709551615 2014年

-2

回答提出的实际问题。术语“虚拟机”是指所有软件/硬件都是模拟/仿真的。如果您使用基础软件/硬件执行指令,则说明您没有VM,而是拥有编译器/解释器。


这仅仅是您的意见,还是可以通过某种方式予以支持?
蚊蚋

@Kyrelel这是不正确的。在“系统”或“完整” VM中模拟“所有”硬件。并非所有虚拟机都已满。例如,尽管没有在此处模拟硬件,但BSD VM层被命名为“虚拟机”。
Netch

我认为问题不一定与术语有关,而是为什么虚拟机实现似乎已经由实际硬件处理的功能
Ryan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.