为什么没有ICMP指令?

时间:2015-03-18 19:46:54

标签: 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_LCMPEQIF_FCMPLT,......指令,但我想知道为什么没有ICMP指令,看到它对布尔人或Integer.compare(int, int)非常有用。

1 个答案:

答案 0 :(得分:5)

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

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

  

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

现在可以合理地问为什么这个“丰富的补充”似乎排除一个等同于所有其他类型的指令。


没有int指令的主要原因可能是既没有必要也没有益处。

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

icmp

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

return icmp, arg0, arg1;

显然可以翻译成现有if (x > y) return 1; if (x < y) return -1; return 0; 指令的序列。

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


有人可能也会提出问题,并提出问题:为什么 if_icmp<?>lcmpfcmp_指令适用于dcmp_,分别是longfloat

在这里,明确的答案要容易得多:提供整套doubleeqneltle和{{1} } gtgelong的比较指令意味着18个额外的指令(甚至更多,对浮点类型采用float处理)。考虑到一个字节可能存在256个指令的硬限制,这就是很多。

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