3

我正在使用 ASM 开发 Java 检测引擎,并且存在评估堆栈顶部具有特定的情况,我想在现有value之前插入一个ref(这是getstatic的结果) 。即考虑只有一个的堆栈: ,然后在getstatic我希望堆栈变成这样: 。value ->ref, value ->

要执行此行为,我必须插入以下字节码:getsaticswap。使用 ASM,我会做类似的事情(考虑mv类型MethodVisitor):

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

问题是交换字节码不支持longdouble值。所以上面的代码对于单字类型是可以的,但是对于longdouble类型就不行了。

是否有任何简单的解决方案来解决longdouble类型的这个问题并且不需要辅助本地值?

4

6 回答 6

5

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

于 2012-07-05T13:54:41.960 回答
3

在这里,您有一个 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);
    }
}
于 2012-07-06T09:31:18.260 回答
2

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

DSTORE tmp
GETSTATIC ...
DLOAD tmp
于 2012-07-05T08:25:40.033 回答
1

使用序列 dup2x2,pop2。

从堆栈上的 XXYY 开始,dup2x2 为您提供 YYXXYY,而 pop2 则为您提供 YYXX。

于 2012-07-05T10:00:49.380 回答
0

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

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();
        }
    }
}
于 2014-04-17T17:02:46.787 回答
-1

我会确保堆栈按它需要的顺序加载,而不需要交换。在优化代码方面,我建议您尝试生成尽可能接近生成的代码,javac因为这是 JVM 已调整优化的内容。

如果这是不可能的,您可以将值存储在局部变量中,推送ref并重新加载值。

于 2012-07-05T08:17:44.927 回答