理解Java热点JIT为浮动测试生成的代码

时间:2014-11-07 22:32:47

标签: java assembly jit disassembly jvm-hotspot

我注意到我的一个数字运算程序中的一些无辜查找if语句会显着降低执行速度(JRE 1.8.25,64位Hotspot build 25.25-b02,Intel 64位CPU)。

我检查了JIT编译器生成的代码,看起来有点奇怪。这是一个简单的函数来说明问题:

private float test(float a,float b) {
    float c=a+b;
    if(c<0) {
        return -1;
    }
    return 0;
}

这是生成代码的有趣部分:

...
0x2bd17ae: vaddss  xmm0,xmm0,xmm1
0x2bd17b2: vxorps  xmm1,xmm1,xmm1
0x2bd17b6: vucomiss xmm0,xmm1
0x2bd17ba: mov     esi,1h
0x2bd17bf: jp      2bd17d8h
0x2bd17c5: jnbe    2bd17d8h
0x2bd17cb: mov     esi,0h
0x2bd17d0: je      2bd17d8h
0x2bd17d6: dec     esi               ;*fcmpg
0x2bd17d8: cmp     esi,0h
0x2bd17db: mov     rsi,57448760h     ; {metadata(method data for {method} ...}
0x2bd17e5: mov     rdi,108h
0x2bd17ef: jnl     2bd17ffh
0x2bd17f5: mov     rdi,118h
0x2bd17ff: mov     rbx,qword ptr [rsi+rdi]
0x2bd1803: lea     rbx,[rbx+1h]
0x2bd1807: mov     qword ptr [rsi+rdi],rbx
0x2bd180b: jnl     2bd1c1fh          ;*ifge
...
// straightforward code for "return -1f" and "return 0f" follows
...

从0x2bd17ba到0x2bd1807的代码对我来说没有多大意义。为什么会这样?知道它的作用吗?

编辑:考虑一下,它可能是JIT编译器添加的一些代码来收集运行时统计信息(只是猜测因为元数据&#39;注释)。但问题是:为什么会这样?我已经将该方法调用了数百万次,因此我认为代码应该已达到最终的优化形式。

1 个答案:

答案 0 :(得分:1)

(v)ucomiss设置标志如下:

unordered    zf,pf,cf = 111
greater      zf,pf,cf = 000
less than    zf,pf,cf = 001
equal        zf,pf,cf = 100

所以这段代码:

    mov     esi,1h
    jp      label  ; if unordered, or
    jnbe    label  ; if greater than, keep it at 1
    mov     esi,0h
    je      label  ; if equal, make 0
    dec     esi    ; otherwise -1
label:

制作esi = 1(如果无序或更高),esi = 0(如果相等),esi = -1(如果更小)

然后它将esi与0进行比较,标记为&#34; ifge&#34;确实检查&#34;如果大于或等于&#34; (通过检查esi不小于0来排序,也包括无序的情况),所以&#34;否则&#34;分支的一部分。

从0x2bd17db到0x2bd1807的部分有条件地增加两个计数器,一个或另一个,具体取决于分支采用的方式。所以它是某种形式的分析。也许以后会用于优化,但我不知道(不过你还会用它做什么)。

他们可以做到:

vaddss  xmm0,xmm0,xmm1
vxorps  xmm1,xmm1,xmm1
vcmpss  xmm0,xmm1,1
vandps  xmm0,xmm0,[rel negative_one]
ret

没有分析,但是没有分支,所以无需分析。