2013-03-11 52 views
5

我用Java寫了一個非常愚蠢的測試類:印刷Java的熱點JIT的彙編代碼

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熱點JIT(客戶端VM建設23.7-B01)生成的代碼。我用了「-XX:+ PrintAssembly」選項,並從http://classparser.blogspot.dk/2010/03/hsdis-i386dll.html

這裏hsdis-i386.dll是生成的代碼的有趣的部分(我跳過了新對象的初始化編輯:代碼爲子方法)。顯然,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指令。

+0

如果您爲'assembly'標記問題,您可能會得到更好的答案。 – assylias 2013-03-11 11:46:28

+0

對我來說,這個彙編代碼沒有意義。我懷疑這是HotSpot生成的實際可執行代碼。 – NPE 2013-03-11 12:15:02

+3

我懷疑你的反彙編程序無法正確解釋機器碼。在較新的x86 CPU上,'LDS'的操作碼是'0xc5',但也可以是[2字節VEX前綴](http://wiki.osdev.org/X86-64_Instruction_Encoding#VEX.2FXOP_opcodes)。 – Michael 2013-03-11 12:22:16

回答

6

我再次。我使用最新的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 
+0

看起來*很多*更有道理(+1) – NPE 2013-03-12 09:16:42

+0

確實:)我編寫了一個簡單的光線跟蹤器,很高興看到JIT如何工作,這要歸功於此功能。像Vector3這樣的類是完全內聯的,因爲它們沒有子類。 SSE2擴展被用作一種「超級FPU」。有點令人失望:在Vector3的構造函數中,JIT代碼總是首先將this.x,this.y,this.z設置爲0.0,即使在「new Vector3(xv.x,yv.y,zv.z) 」。三個不需要的內存訪問,每個訪問8個字節。 – trunklop 2013-03-12 09:33:51

+0

太棒了。花時間發佈答案做得很好。 – NPE 2013-03-12 09:43:55