【问题标题】:Jasmin Assembler: 'l2d' Instruction Giving "java.lang.VerifyError: ... Attempt to split long or double on the stack"Jasmin 汇编程序:'l2d' 指令给出“java.lang.VerifyError: ... 尝试在堆栈上拆分 long 或 double”
【发布时间】: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


【解决方案1】:

Java 虚拟机使用局部变量来传递参数,因此在您的代码中,索引为 0 的局部变量将是 String[] 类型。我对 Jasmine 不太熟悉,不知道是否必须在使用前声明其他局部变量,但是您可以尝试将 double 存储到索引 1 中吗?

【讨论】:

  • 有趣,虽然 Jasmin 的工作方式似乎不太一样,因为我可以编写等效的代码来将 int 转换为 float 并且它工作正常,例如浮动 f = 10;编译为:'ldc 10' 然后 'i2f' 然后 'fstore 0' 程序运行良好。
  • 它可能仍然相关,因为字符串数组引用只使用一个堆栈槽,而双精度则需要两个。
猜你喜欢
  • 2011-10-06
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 2017-08-01
  • 2011-07-08
  • 2012-11-23
相关资源
最近更新 更多