JVM或CLR在运行JIT编译的代码时是否使用寄存器?

6

我知道JVM和CLR都是基于栈的虚拟机。当JIT将字节码编译成本地代码时,它是否也会将栈原语(load/store)翻译成X86平台上的寄存器?

如果是这样,似乎无论字节码是基于栈还是寄存器,都并不重要。JIT才是关键。

3个回答

7
我认为你混淆了两个不同的概念。
至少对于Java而言,JVM充当虚拟机 - 它是一台理想化的计算机,具有相对高级的汇编语言(字节码),基于带有堆栈帧的调用栈。在将Java编译成字节码时,Java程序被转换为(实质上)用于控制此机器的汇编程序。
实际运行Java在给定系统上时,JVM实现的任务是忠实地模拟使用任何可用硬件的基于堆栈的机器的执行。这通常意味着大量的堆栈操作将在可能时使用寄存器进行实现,并且可能使用其他在Java虚拟机描述中不存在的专用硬件。如何完成这项工作的实际细节是特定于实现的 - 一些实现可能将其编译成几乎所有内容都在寄存器中执行的机器代码,而简单的实现可能只编译成内存中的操作。我曾在JavaScript JVM实现上工作了几个月,在这种情况下,我们将代码“编译”为JS函数,然后将其交给浏览器的JS实现。
这种区别的原因是Java旨在易于下载和嵌入(考虑applet)。在这种情况下,安全性和可移植性是重要问题。字节码必须具有某种自动检查的方式,以排除某些类型的恶意代码(例如缓冲区溢出)。同样,无论使用何种格式,它都必须足够高级,以便在各种不同的平台上运行(手持设备、超级计算机、个人电脑等)。堆栈式JVM的选择使得可以同时满足这两个问题。它高级到足以检查字节码以排除许多类型错误或未初始化内存的读/写,同时又足够低级,使得JVM可以使用诸如编译为使用寄存器的代码之类的技巧。
如果你想知道你特定的JVM会对特定的一段代码做什么,你应该查看文档。大多数JVM都有一些方法可以提供有关它们如何执行代码的信息。如果你的问题是“为什么不让字节码进行基于寄存器的操作”,原因有两个:
1.字节码中有一个类似于寄存器的模拟 - 每个堆栈帧都有一些额外的专用空间用于存储临时值; 2.与x86或MIPS中存在的支持寄存器的强大支持不同,没有为寄存器提供强大的支持,因为JVM代码必须易于在多个硬件上执行,而硬编码一些寄存器可能会使事情变得复杂。
希望对你有所帮助!

2

在x86核心上不使用寄存器是不可能的。处理器没有指令可以添加两个局部变量。其中一个必须在寄存器中加载。然后您可以将寄存器中的值与变量中的值相加。并将结果存回堆栈变量。

从这个序列中可以看出优化机会。比如不将其存回而将结果保留在寄存器中,并在以后使用它,节省了存储和加载。这是优化器的工作,它寻找利用可用寄存器的最佳方法。


0

唯一确定的方法是检查JIT编译输出,但可以肯定的是使用寄存器是JIT编译器最差的优化之一。我相信大多数程序员很难编写比JIT编译器更快的代码。

JIT编译器有很多功能,可能会尽可能地使用寄存器。像方法内联这样的东西鼓励使用寄存器,并且许多命令式程序代码可以在基于寄存器的架构上更简单地表达,因此JIT编译器使用寄存器是有意义的。


注意:这篇文章是从C#开发者的角度写的,因此可能更适用于CLR而不是JVM。 - Kendall Frey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接