我继续研究方法仿真并在传递指令 ILOAD 时获得实际值(value)。之后Holger's help with Interpreter
在 main()
方法中添加带有局部变量的新操作后,我坚持使用 merge(V a, V b)
方法,在扩展 Interpreter
时必须覆盖该方法。
@Override
public LocalValue merge(LocalValue valueA, LocalValue valueB) {
if (Objects.equals(valueA, valueB)) return valueA;
else return new LocalValue(basicInterpreter.merge(valueA.type, valueB.type), null);
}
但是这似乎写得不正确。我可以尝试不同的逻辑变量返回什么,但不了解,在什么情况下值可以合并,我找不到。我试图在 javadocs 和 asm-4 教程中找不到有用的信息。那么,我需要返回什么,时间:
- 一个值为 null,另一个值为非
- 两个值都不为 null,类型相同,但对象不同(例如 0 和 5)
- 两个值都不为 null,不同类型
基本解释器:
private BasicInterpreter basicInterpreter = new BasicInterpreter();
本地值:
public static class LocalValue implements Value {
Object value;
BasicValue type;
public LocalValue(BasicValue type, Object value) {
this.value = value;
this.type = type;
}
@Override public int getSize() {return type.getSize();}
@Override public String toString() {return value == null ? "null" : value.toString();}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof LocalValue)) return false;
LocalValue otherV = (LocalValue) obj;
return Objects.equals(otherV.type, type) && Objects.equals(otherV.value, value);
}
}
最佳答案
当可以通过不同的代码路径到达指令时(例如,当您有条件、循环或异常处理程序时),需要合并值。
因此,当值相同时,无论采用哪条代码路径,都可以保留它,否则该值不再是可预测的常量。因此,在我的代码中,null
用于表示未知值,当值不同时,它总是返回 null
。
所以当你有这样的代码时
void foo(int arg) {
int i = 1;
int j = arg%2==0? i: arg;
}
arg
、i
的值和操作数堆栈上的值在分配给 j
之前合并。 arg
确实已经具有不可预测的值,i
在每个代码路径中具有值 1
,但要分配给 j
的操作数堆栈上的值具有不同的值,1
或“未知”,具体取决于所采用的代码路径。
如果您愿意,您可以决定维护一组可能的值,但是当其中一个可能的值是“未知”时,合并冷的结果可以是任何值,因此是“未知”。
关于java - ASM 在解释器上合并两个值对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48816547/