jvm-为什么java字节码指令iload_只有0-3?

2021-01-07  本文已影响0人  小北觅

​没错,事情是这样的。在阅读周志明大大的《深入理解jvm 第三版》的字节码指令一节的时候,讲到iload_<n style="margin: 0px; padding: 0px; font-size: inherit; color: inherit; line-height: inherit;">指令中,n只能取0~3。有点不解,遂du了一下。</n>

然后!然后!然后!果然没让我失望,那个对jvm有着深厚造诣的蓝人--R大!!在b乎回答了这个问题。膜拜R大,这个蓝人tql。

直接上链接好了。

java字节码指令iload_<n style="margin: 0px; padding: 0px; font-size: inherit; color: inherit; line-height: inherit;">为什么只有0到3?- RednaxelaFX的回答 - 知乎
https://www.zhihu.com/question/54390587/answer/139423116</n>

总结一下:

这是Java字节码上针对字节码大小的一个早期优化。Java字节码指令集里,大部分操作局部变量的指令(例如iload、istore)都有完整版:

iload n

例如iload 5,以及针对前4个局部变量/参数的缩写版

iload_<n>

例如iload_0,这样两个版本。其中缩写版只有0~3的范围。

二者的区别是,完整版有显式的“操作数”(operand),缩写版把操作数融合到了操作码(opcode)中。分别用两种指令举个例子:

iload的指令格式是:

iload index
image

index是一个unsigned byte,用来指定局部变量的下标。另外看Notes里标注,还有wide版,如果在iload前面带有wide前缀的话,则格式为:

wide iload index1 index2

其中wide、iload、index1、index2各自为一个字节,(index1<<8)| index2 构成指令局部变量下标的操作数。

iload_<n>的指令格式是:

iload_<n>
image

其中iload_<n>自身就是opcode,它可能的取值为:
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)
这样的话,针对前4个局部变量,iload_<n>就可以只用一个字节的opcode来表达整条指令,比使用完整版的iload要少一个字节。使用缩写版指令不但可以让字节码的大小减少,还可以让解释器的性能提升。原因如下图所示:摘自R大的知乎回答。

image

当使用缩写版指令时,decode_operands()就不需要做任何额外的内存读,因为operand已经隐藏在opcode里了,于是就会比完整版指令要快一些。

至于选择03的范围来做的原因,R大猜测大概只是正好发现,如果用03的话基本可以把opcode范围用满(因为字节码是1字节,最多256个),而如果用04的话就把编码空间超了,02的话则用不满,仅此而已。

《!-- 毁灭吧,赶紧的,累了 --》

上一篇下一篇

猜你喜欢

热点阅读