java - 为什么没有ICMP指令?

标签 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 指令,看到它非常有用,尤其是对于 boolean 值或 Integer.compare(int, int)

最佳答案

已经有两个“主要基于意见”的接近投票。事实上,没有人能在这里给出明确的答案,当试图争论一群工程师 25 年前做出的决定时,可能会涉及到一些挥手。但我会试一试...

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

Because of its emphasis on int comparisons, the Java Virtual Machine provides a rich complement of conditional branch instructions for type 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_icmp<?>的序列指示。

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


人们也可能会反过来问:为什么在那里lcmp , fcmp_dcmp_可用于 long 的说明, floatdouble , 分别?

在这里,明确的答案要容易得多:提供整套 eq , ne , lt , le , gtge long 的比较说明, floatdouble将意味着 18 个额外的指令(或者更多,用 NaN 处理浮点类型)。考虑到一个字节可能有 256 条指令的硬性限制,这已经很多了。

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

关于java - 为什么没有ICMP指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29131376/

相关文章:

java - session 范围 bean - 如何处理多用户数据

java - 构造有向图,出现空指针异常

java - 如果 mapred.job.reuse.jvm.num.tasks 设置为 -1,则 hadoop 集群中每个节点启动了多少个 jvm

java - 是否值得从 Oracle JVM 1.6.0_07 升级到更新的版本?

java - 未使用的局部变量 Java 8 - java.lang.VerifyError : Inconsistent stackmap frames

java - 创建 pi(x) 表

java - 如何将构造函数参数分配给成员

java - 保留堆的镜像并在执行某些方法后返回它

compiler-construction - Mindustry Game CPU 架构的最简单编译器

java - 长度超过 65535 字节的 Java 字符串文字的字节码