为什么没有ICMP指令?
Why is there no ICMP instruction?
你们中的一些人可能知道,我们有大量的操作码用于比较不同类型的原始值:
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_LCMPEQ
、IF_FCMPLT
、...指令,但我想知道为什么没有 ICMP
指令,看到它非常有用,特别是对于布尔值或 Integer.compare(int, int)
.
已经有两个 "primarily opinion based" 接近的投票。事实上,没有人能在这里给出明确的答案,当试图争论一群工程师 25 年前做出的决定时,可能会涉及到一些挥手。但我会试一试...
首先,我认为这个问题是有道理的:int
类型是Java语言中最"prominent"的类型(最后但并非最不重要的是因为它的作用作为数组索引)。这与它在 Java 虚拟机中的特殊作用密切相关,在虚拟机中,语言中存在的所有(较小的)整数类型,如 byte
或 short
,都有效地转换为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
.
现在有理由问为什么这个 "rich complement" 似乎 排除了 对所有其他类型等效存在的指令。
没有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<?>
指令。
在这里,应该记住这些比较指令的主要目的是分支:它们导致跳转到不同的地点。它们不是为了将值压入堆栈,然后可能是 "used as a return value of a method"。谈论语言和谈论虚拟机在这里是完全不同的两件事。
有人可能还会反过来问:为什么 有 lcmp
、fcmp_
和 dcmp_
指令可用于 [ =24=、float
和 double
?
在这里,一个明确的答案要容易得多:提供整套 eq
、ne
、lt
、le
、gt
和 ge
用于 long
、float
和 double
的比较指令将意味着 18 个附加指令(或者甚至更多,对浮点类型进行 NaN
处理)。考虑到一个字节可能有 256 条指令的硬性限制,这已经很多了。
通过为这些类型提供 lcmp
、fcmp_
和 dcmp_
指令,可用于 int
的其余指令可用于 emulate 所有其他可能的比较情况。但同样,这些主要用于 分支 ,因此根本不需要 icmp
指令,因为对于 int
,所有必要的分支指令("jump conditions") 已经可用。
你们中的一些人可能知道,我们有大量的操作码用于比较不同类型的原始值:
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_LCMPEQ
、IF_FCMPLT
、...指令,但我想知道为什么没有 ICMP
指令,看到它非常有用,特别是对于布尔值或 Integer.compare(int, int)
.
已经有两个 "primarily opinion based" 接近的投票。事实上,没有人能在这里给出明确的答案,当试图争论一群工程师 25 年前做出的决定时,可能会涉及到一些挥手。但我会试一试...
首先,我认为这个问题是有道理的:int
类型是Java语言中最"prominent"的类型(最后但并非最不重要的是因为它的作用作为数组索引)。这与它在 Java 虚拟机中的特殊作用密切相关,在虚拟机中,语言中存在的所有(较小的)整数类型,如 byte
或 short
,都有效地转换为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
.
现在有理由问为什么这个 "rich complement" 似乎 排除了 对所有其他类型等效存在的指令。
没有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<?>
指令。
在这里,应该记住这些比较指令的主要目的是分支:它们导致跳转到不同的地点。它们不是为了将值压入堆栈,然后可能是 "used as a return value of a method"。谈论语言和谈论虚拟机在这里是完全不同的两件事。
有人可能还会反过来问:为什么 有 lcmp
、fcmp_
和 dcmp_
指令可用于 [ =24=、float
和 double
?
在这里,一个明确的答案要容易得多:提供整套 eq
、ne
、lt
、le
、gt
和 ge
用于 long
、float
和 double
的比较指令将意味着 18 个附加指令(或者甚至更多,对浮点类型进行 NaN
处理)。考虑到一个字节可能有 256 条指令的硬性限制,这已经很多了。
通过为这些类型提供 lcmp
、fcmp_
和 dcmp_
指令,可用于 int
的其余指令可用于 emulate 所有其他可能的比较情况。但同样,这些主要用于 分支 ,因此根本不需要 icmp
指令,因为对于 int
,所有必要的分支指令("jump conditions") 已经可用。