【问题标题】:printing Java hotspot JIT assembly code打印 Java 热点 JIT 汇编代码
【发布时间】:2013-02-26 13:33:37
【问题描述】:

我用Java写了一个非常愚蠢的测试类:

public class Vector3 {
   public double x,y,z ;

   public Vector3(double x, double y, double z) {
       this.x=x ; this.y=y ; this.z=z ;
   }

   public Vector3 subst(Vector3 v) {
      return new Vector3(x-v.x,y-v.y,z-v.z) ;
   }
}

然后我想看看 Java Hotspot JIT 生成的代码(Client VM build 23.7-b01)。我使用了“-XX:+PrintAssembly”选项和来自http://classparser.blogspot.dk/2010/03/hsdis-i386dll.html的hsdis-i386.dll

这里是生成代码的有趣部分(我跳过了新对象的初始化。编辑:subst 方法的代码)。显然,ebx 是“this”指针,edx 是指向参数的指针。

lds    edi,(bad)
sti    
adc    BYTE PTR [ebx+8],al  ;*getfield x
mov    edx,DWORD PTR [esp+56]
lds    edi,(bad)          ; implicit exception: dispatches to 0x02611f2d
sti    
adc    BYTE PTR [edx+8],cl  ;*getfield x
lds    edi,(bad)
sti    
adc    BYTE PTR [ebx+16],dl  ;*getfield y
lds    edi,(bad)
sti    
adc    BYTE PTR [edx+16],bl  ;*getfield y
lds    edi,(bad)
sti    
adc    BYTE PTR [ebx+24],ah  ;*getfield z
lds    edi,(bad)
sti    
adc    BYTE PTR [edx+24],ch  ;*getfield z
lds    edi,(bad)
sti    
pop    esp
rol    ebp,0xfb
adc    DWORD PTR [eax+8],eax  ;*putfield x
lds    ebp,(bad)
jmp    0x02611f66
rol    ebp,cl
sti    
adc    DWORD PTR [eax+16],edx  ;*putfield y
lds    ebx,(bad)
fistp  DWORD PTR [ebp-59]
sti    
adc    DWORD PTR [eax+24],esp  ;*putfield z

老实说,我对 x86 汇编不是很熟悉,但你觉得这段代码有意义吗?像“adc BYTE PTR [edx+8],cl”这样的奇怪指令在做什么?我会期待一些 FPU 指令。

【问题讨论】:

  • 如果您标记您的问题assembly,您可能会得到更好的答案。
  • 对我来说,这个汇编代码毫无意义。我怀疑这是 HotSpot 生成的实际可执行代码。
  • 我怀疑您的反汇编程序无法正确解释机器代码。 LDS 的操作码是 0xc5,但在较新的 x86 CPU 上也可能是 2-byte VEX prefix
  • 感谢您的回答。结论似乎是dll中使用的反汇编程序没有正确解码生成的代码。我将按照dropzone.nfshost.com/hsdis.htm 的说明尝试自己构建 dll
  • 请您对自己找到的解决方案做出回答并接受,以便人们立即看到这个问题已解决。它将帮助可能遇到类似问题的其他人。

标签: java assembly jit disassembly jvm-hotspot


【解决方案1】:

又是我。我使用最新的 binutils 2.23 构建了 hsdis-i386.dll。感谢http://dropzone.nfshost.com/hsdis.htm 中的说明,这比我预期的要容易 (至少对于x86版本。64位版本编译但立即停止JVM,没有任何错误消息)

现在的输出看起来好多了:

vmovsd xmm0,QWORD PTR [ebx+0x8]  ;*getfield x
mov    edx,DWORD PTR [esp+0x40]
vmovsd xmm1,QWORD PTR [edx+0x8]  ;*getfield x
vmovsd xmm2,QWORD PTR [ebx+0x10] ;*getfield y
vmovsd xmm3,QWORD PTR [edx+0x10] ;*getfield y
vmovsd xmm4,QWORD PTR [ebx+0x18] ;*getfield z
vmovsd xmm5,QWORD PTR [edx+0x18] ;*getfield z
vsubsd xmm0,xmm0,xmm1
vmovsd QWORD PTR [eax+0x8],xmm0  ;*putfield x
vsubsd xmm2,xmm2,xmm3
vmovsd QWORD PTR [eax+0x10],xmm2 ;*putfield y
vsubsd xmm4,xmm4,xmm5
vmovsd QWORD PTR [eax+0x18],xmm4 ;*putfield z

【讨论】:

  • 这看起来很多更合理(+1)
  • 确实 :) 我编写了一个简单的光线追踪器,很高兴看到 JIT 是如何工作的,这要归功于此功能。像 Vector3 这样的类是完全内联的,因为它们没有子类。 SSE2 扩展被用作一种“超级 FPU”。有点令人失望:在 Vector3 的构造函数中,JIT 代码总是首先将 this.x,this.y,this.z 设置为 0.0,即使在 "new Vector3(xv.x,yv.y,zv.z) ”。三个不需要的内存访问,每个访问 8 个字节。
猜你喜欢
  • 2021-02-24
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 2017-04-30
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多