19

我一直在研究编程语言是如何工作的,其中一些具有所谓的虚拟机。我知道这是在另一种编程语言中对编程语言进行某种形式的仿真,并且它的工作方式类似于使用堆栈执行编译语言的方式。我做对了吗?

有了我所做的附带条件,让我感到困惑的是,许多非编译语言允许具有“自由”类型系统的变量。例如,在 Python 中,我可以这样写:

x = "Hello world!"
x = 2**1000

字符串和大整数是完全不相关的,并且在内存中占用的空间量不同,那么这段代码怎么能在基于堆栈的环境中表示呢?这里到底发生了什么?x 是否指向堆栈上的新位置并且未引用旧的字符串数据?这些语言不使用堆栈吗?如果不是,它们如何在内部表示变量?

4

5 回答 5

7

也许,您的问题应该标题为“动态语言如何工作?”。

这很简单,它们将变量类型信息连同它一起存储在内存中。这不仅在解释或 JIT 编译语言中完成,而且在 Objective-C 等本机编译语言中也是如此。

于 2009-05-29T21:05:35.193 回答
2

在大多数 VM 语言中,变量可以概念化为指向堆中内存的指针(或引用),即使变量本身位于堆栈上。对于具有原始类型(例如 Java 中的 int 和 bool)的语言,它们也可以存储在堆栈中,但不能动态地为它们分配新类型。

忽略原始类型,堆栈中存在的所有变量都将其实际值存储在堆中。因此,如果您动态地为它们重新分配值,则原始值将被放弃(并通过某种垃圾收集算法清理内存),并且新值将分配到新的内存位中。

于 2009-05-29T21:09:34.763 回答
2

VM 与语言无关。任何语言都可以在 VM 上运行(Java VM 已经有数百种语言)。

VM 可以运行一种不同类型的“汇编语言”,一种更适合编译器适应的“汇编语言”。在 VM 中完成的所有事情都可以在 CPU 中完成,因此将 VM 视为 CPU。(有些实际上是在硬件中实现的)。

它是极低级别的,并且在许多情况下严重基于堆栈——而不是寄存器,机器级数学都是相对于相对于当前堆栈指针的位置的。

对于普通的编译语言,一个步骤需要许多指令。a + 可能看起来像“将项目从相对于堆栈指针的点抓取到 reg a,将另一个抓取到 reg b。添加 reg a 和 b。将 reg a 放入相对于堆栈指针的位置。

VM 使用一条短指令完成所有这些操作,可能是一个或两个字节,而不是机器语言中的 4 或 8 个字节(取决于 32 或 64 位架构),这(猜测)应该意味着大约 16 或 32 个字节的 x86用于 1-2 字节的机器代码。(我可能是错的,我最后的 x86 编码是在 80286 时代。)

微软在其办公产品中使用(可能仍在使用)虚拟机来减少代码量。

创建 VM 代码的过程与创建机器语言的过程相同,只是处理器类型不同而已。

VM 还可以实现自己的与语言密切相关的安全、错误恢复和内存机制。

我在这里的一些描述是总结和记忆。如果您想自己探索字节码定义,这很有趣:

http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html

于 2009-05-29T22:09:24.660 回答
1

许多“虚拟机如何处理这样或那样的变量”的关键实际上归结为元数据......存储然后更新的元信息使虚拟机可以更好地处理如何分配然后做正确的事情变量。

在许多情况下,这是真正会影响性能的开销类型。然而,现代的实现等在做正确的事情方面已经走了很长一段路。

至于您的具体问题-将变量视为普通对象/等...归结为重新分配/重新评估新分配的元信息-这就是为什么 x 可以先看一种方式,然后再看另一种方式。

于 2009-05-29T21:10:55.527 回答
1

要回答您的部分问题,我建议您在google tech talk about python中回答您有关动态语言的一些问题;例如变量是什么(它不是指针,也不是引用,但在 python 的情况下是标签)。

于 2009-05-29T21:12:17.910 回答