jvm 双精度和长值的Java字节码SWAP?

ma8fv8wu  于 2022-12-18  发布在  Java
关注(0)|答案(7)|浏览(140)

我正在使用ASM开发Java插装引擎,在这种情况下,计算堆栈的顶部有一个特定的 value,我想在现有的 value 之前插入一个 ref(这是 getstatic 的结果)。也就是说,考虑只有一个 value 的堆栈:value ->,然后在 getstatic 之后,我希望堆栈变成这样:ref, value -> .
要执行此行为,我必须插入以下字节码:* gettatic * 和 swap。使用ASM时,我将执行如下操作(考虑MethodVisitor类型的mv):

mv.visitFieldInsn(Opcodes.GETSTATIC, ...);
mv.visitInsn(Opcodes.SWAP);

问题是 swap 字节码不支持longdouble值,所以上面的代码对于单个单词类型是可以的,但是对于longdouble类型就不能正常工作了。
对于longdouble类型,是否有简单的解决方案来解决此问题,并且不需要辅助局部值?

bd1hkmkf

bd1hkmkf1#

我们有一个双字值VV和参考值R。要从VV...获取到VVR...,您可以将R值添加到堆栈顶部(RVV...),然后使用dup_x2(RVVR...),然后弹出(VVR...)。

snz8szmq

snz8szmq2#

这里有一个ASM的实用函数,它注入字节码,用于交换栈顶任何类型的操作数:

public static void swap(MethodVisitor mv, Type stackTop, Type belowTop) {
    if (stackTop.getNumberSlots() == 1) {
        if (belowTop.getNumberSlots() == 1) {
            // Top = 1, below = 1
            mv.visitInsn(Opcodes.SWAP);
        } else {
            // Top = 1, below = 2
            mv.visitInsn(Opcodes.DUP_X2);
            mv.visitInsn(Opcodes.POP);
        }
    } else {
        if (belowTop.getNumberSlots() == 1) {
            // Top = 2, below = 1
            mv.visitInsn(Opcodes.DUP2_X1);
        } else {
            // Top = 2, below = 2
            mv.visitInsn(Opcodes.DUP2_X2);
        }
        mv.visitInsn(Opcodes.POP2);
    }
}
gblwokeq

gblwokeq3#

最简单的解决方案是使用局部变量来交换堆栈上的项。

DSTORE tmp
GETSTATIC ...
DLOAD tmp
nue99wik

nue99wik4#

使用序列dup2x2,pop2。
从堆栈上的XXYY开始,dup2x2给您YYXXYY,pop2留给您YYXX。

twh00eeo

twh00eeo5#

调用org.objectweb.asm.commons.GeneratorAdapter.swap(类型,类型),它是这样实现的:

public void swap(final Type prev, final Type type) {
    if (type.getSize() == 1) {
        if (prev.getSize() == 1) {
            swap(); // same as dupX1(), pop();
        } else {
            dupX2();
            pop();
        }
    } else {
        if (prev.getSize() == 1) {
            dup2X1();
            pop2();
        } else {
            dup2X2();
            pop2();
        }
    }
}
wqsoz72f

wqsoz72f6#

我今天遇到了同样的问题。我觉得局部变量可以这样绕过:
1.价值-〉
获取静态
1.值-〉参考-〉
重复_X2
1.参考-〉值-〉参考-〉
流行音乐
1.参考-〉值-〉

m0rkklqb

m0rkklqb7#

我会确保堆栈按照它需要的顺序加载,而不需要交换。在优化代码方面,我建议您尝试生成尽可能接近javac生成的代码,因为这是JVM已经调整优化的内容。
如果这不可能,您可以将值存储在局部变量中,推送ref并重新加载值。

相关问题