【发布时间】:2011-11-24 20:17:39
【问题描述】:
我正在编写一个编译器来使用 Jasmin assembler 将 Java 的子集编译为 Java 字节码
我在使用“l2d”指令(以及相关的指令 - 但我认为一旦我弄清楚为什么这个指令不起作用,它们都会起作用)。
指令参考:
http://cs.au.dk/~mis/dOvs/jvmspec/ref-_l2d.html
我正在编译的代码是:
{
double d = 10L;
}
所以本质上我试图反映 javac 在原始数值类型之间进行隐式类型转换的方式。
输出的 Jasmin 汇编代码为:
.source test3.jml
.class Test3
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
.limit stack 10
.limit locals 100
ldc2_w 10 ;Load constant numerical value 10
l2d ;Convert left hand side to match the type of the right
dstore 0 ;Store top of stack in 0 (d)
.end method
.end method之前的三行重要。
';' 后面的文字是评论。
我尝试运行编译后的代码时得到的确切错误是:
Exception in thread "main" java.lang.VerifyError:(class: Test3, method: main signature: ([java/lang/String;)V) Attempt to split long or double on the stack
Could not find the main class: Test3. Program will exit.
我认为这一定与 long 和 double 占用堆栈上的 2 个插槽和 2 个局部变量(解释为 here)这一事实有关,但它仍然让我感到困惑。
【问题讨论】:
-
为什么不使用真正的java编译器编译它,看看它用javap生成了什么?
-
应该是
dstore_0而不是dstore 0不是吗? -
好主意。我现在刚试过。问题是 javac 似乎做了很多编译时优化;它设法避免需要完全使用“l2d”。基本上,它意识到'='右侧的内容将用作双精度数,因此它一直将其视为双精度数。即使我做了类似'double x = 10F + 12F + 10;'之类的事情,它也会在编译时将整个表达式评估为'32D'。优化超出了我的项目范围。
-
Voo,显然两者都可以。来自参考:“'dstore_
' 在功能上等同于'dstore ',尽管它通常更有效并且在字节码中占用的字节更少。”因此,我确实打算更改这些,但我怀疑这是导致此问题的原因。
标签: java compiler-construction assembly jvm jasmin