为什么没有ICMP指令?

Cla*_*oft 4 java jvm jvm-bytecode

正如你们中的一些人可能知道的那样,我们有大量的操作码来比较不同类型的原始值:

LCMP
FCMPL
FCMPG
DCMPL
DCMPG
IFEQ
IFNE
IFLT
IFGE
IFGT
IFLE
IF_ICMPEQ
IF_ICMPNE
IF_ICMPLT
IF_ICMPGE
IF_ICMPGT
IF_ICMPLE
IF_ACMPEQ
IF_ACMPNE
...
Run Code Online (Sandbox Code Playgroud)

由于显而易见的原因,指令集的创建者并没有费心去添加所有IF_LCMPEQ,IF_FCMPLT...指令,但我想知道为什么没有ICMP指令,看到它对于布尔值或者非常有用Integer.compare(int, int).

Mar*_*o13 5

已经有两个"主要基于意见"的近距离投票.事实上,没有人可以在这里给出一个明确的答案,并且在试图争论25年前一群工程师做出的决定时,可能会有一些牵手.但我会尝试一下......

首先,我认为这个问题是合理的:int类型是Java语言中最"突出"的类型(最后但并非最不重要的是因为它作为数组索引的作用).这与它在Java虚拟机中的特殊作用密切相关,其中语言中存在的所有(较小的)整数类型,如byteshort,有效地转换int为所有计算.或者,如Java虚拟机规范第2.11.7节中所述:

由于强调了int比较,Java虚拟机为类型提供了丰富的条件分支指令int.

现在可以合理地问为什么这个"丰富的补充"似乎排除了对所有其他类型等效的指令.


没有icmp指示的主要原因可能是既没有必要也没有益处.

使用它的建议应用案例Integer#compare(int, int)很难算作一个论点:这种方法的实现(即使icmp存在)也不会

return icmp, arg0, arg1;
Run Code Online (Sandbox Code Playgroud)

将方法转换为字节码可能相当复杂,并且考虑到Java语言本身的可能性,无论如何必须将这种方法等效地实现为

if (x > y) return 1;
if (x < y) return -1;
return 0;
Run Code Online (Sandbox Code Playgroud)

这显然可以翻译成现有if_icmp<?>指令的序列.

在这里,应该记住,这些比较指令的主要目的是分支:它们导致跳转到不同的位置.它们不是用于在堆栈上推送值,然后可以"用作方法的返回值".谈论语言和谈论虚拟机是两件完全不同的事情.


人们可能还问题反过来了,请问:为什么那里lcmp,fcmp_dcmp_说明可供long,floatdouble分别?

在这里,一个明确的答案要容易得多:提供整套的eq,ne,lt,le,gtge用于对比说明long,float并且double将意味着额外的18条指令(甚至更多,与NaN治疗浮点类型).考虑到一个字节可能存在256个指令的硬限制,这就是很多.

通过提供lcmp,fcmp_dcmp_为这些类型的指令,剩下的指令可用于int可用于模拟所有其他可能的比较情况.但同样,这些主要用于分支,因此根本不需要icmp指令,因为int所有必要的分支指令("跳转条件")已经可用.