Java 为什么没有ICMP指令?

Java 为什么没有ICMP指令?,java,jvm,jvm-bytecode,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 ... 由于明显的原因,指令集的创建者没有费心添加所有的IF\u LCMPEQ,IF\u FCMPLT。。。指令,但我想知道为什么没有ICMP指

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

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
...
由于明显的原因,指令集的创建者没有费心添加所有的
IF\u LCMPEQ
IF\u FCMPLT
。。。指令,但我想知道为什么没有
ICMP
指令,因为它特别适用于布尔或
Integer。比较(int,int)

已经有两张“主要基于意见”的接近票了。事实上,在这里没有人能给出明确的答案,当试图就一群工程师25年前做出的决定进行辩论时,可能会涉及一些手工操作。但我会试试看

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

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

现在有理由问为什么这个“丰富补码”似乎排除了所有其他类型的指令


没有
icmp
指令的主要原因可能是它既不是必需的,也不是有益的

建议将其用于
Integer#compare(int,int)
的应用案例很难算作一个参数:这样一种方法的实现(即使
icmp
存在)也不会成功

return icmp, arg0, arg1;
将一个方法转换成字节码可能相当复杂,并且考虑到Java语言本身的可能性,这样一个方法无论如何都必须按照

if (x > y) return 1;
if (x < y) return -1;
return 0;
if(x>y)返回1;
如果(x
这显然是可以翻译成一系列现有的
if\u icmp
指令

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


有人可能会反过来问:为什么有
lcmp
fcmp
dcmp
指令分别适用于
long
float
double

在这里,一个明确的答案要容易得多:提供整套
eq
ne
lt
le
gt
ge
float
double
的比较指令意味着另外18条指令(甚至更多,对于浮点类型的
NaN
处理)。考虑到一个字节可能有256条指令的硬限制,这是很多


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

这是一个六乘一、六乘另一件事;使用什么字节码并不重要。(而且
Long.compare
不直接使用lcmp;只是这样,Long上的等等都是根据lcmp实现的。)Integer.compare参数的要点是,假设的编译器可以使用ICMP指令内联此方法,同时避免重字节码。@Clashsoft当然,无意冒犯:-)人们确实可以想象一个
ICMP
被转换为将结果存储在
EAX
寄存器中(作为x86上的返回值)或者在任意寄存器中(内联时)可能是有益的。但在这里,我认为人们必须争论实际(通常基于寄存器)目标机器是否有一条与
icmp
等价的指令,以及虚拟机与实际机器代码之间的转换过程。同样,这里很难找到“答案”,所以这些只是一些(希望有说服力的)论点。。。