为什么COMPUTE_FRAMES会产生大量冗余指令?

rwa*_*ace 4 java java-bytecode-asm jvm-bytecode

我正在编写一个输出 JVM 字节代码的编译器,并使用 ASM 9.4 作为后端。这工作得很好,但我对一个特殊的怪癖感到困惑。

我指定COMPUTE_FRAMES自动计算堆栈帧。据说,这种权衡是(可以理解)这使得代码生成需要更多时间,但它似乎足够快。

我能找到的任何地方都没有记录,指定COMPUTE_FRAMES会导致生成大量冗余指令。具体来说,athrow每个方法末尾都有一个 ,并且在某些情况下,一堆长运行的nops 分散在该方法中。

这似乎并没有造成任何伤害;我最初的测试用例顺利通过,我想 JIT 编译器实际上不会为冗余指令生成任何机器代码。但这有点令人不安。它为什么要这样做?我做错了什么吗?

Hol*_*ger 8

这表明您生成的字节码中存在无法访问的代码。使用堆栈映射,前一条指令无法访问的每条指令都必须有一个堆栈帧,即使不是分支的目标。这对于在单次线性传递中验证代码是必要的。

\n

但对于无法访问的代码,没有已知的初始状态,为任意指令序列发明有效的初始状态将非常具有挑战性。ASM\xe2\x80\x99s 的解决方案是用 nop 指令替换整个不可达代码,后跟单个athrow语句。对于这个序列,可以指定一个有效的初始堆栈帧;it\xe2\x80\x99 是一个在堆栈上有单个 throwable 的帧。此序列对后续可能可达的代码也没有影响。

\n

由于代码无法访问,因此此替换对执行没有影响,正如您在测试中已经注意到的那样。你\xe2\x80\x99是对的,JIT编译器不会\xe2\x80\x99为其生成任何本机代码。

\n

但是为了摆脱这个令人不安的代码,你\xe2\x80\x99d必须修改你的编译器代码,以找出它在哪一部分生成了无法访问的代码。

\n