Observe the following program written in Java (complete runnable version follows, but the important part of the program is in the snippet a little bit further below):
This is what I think is happening (keep in mind I'm not familiar with HotSpot):
0xf36c9fd0: mov 0x6c(%ecx),%ebp ; vfoo
0xf36c9fd3: test %ebp,%ebp ; vfoo is null?
0xf36c9fd5: je 0xf36c9ff7 ; throw NullPointerException (I guess)
0xf36c9fd7: movl $0x1,0x8(%ebp) ; vfoo.x = 1
0xf36c9fde: mov 0x68(%ecx),%ebp ; sz
0xf36c9fe1: inc %ebx ; i++
0xf36c9fe2: test %edi,0xf7725000 ; safepoint on end of loop
0xf36c9fe8: cmp %ebp,%ebx ; i < sz?
0xf36c9fea: jl 0xf36c9fd0
0xf3771ad0: mov 0x6c(%ecx),%ebp ; vfoo
0xf3771ad3: test %ebp,%ebp ; vfoo is null?
0xf3771ad5: je 0xf3771b09 ; throw NullPointerException (I guess)
0xf3771ad7: movl $0x1,0x8(%ebp) ; vfoo.x = 1
0xf3771ade: mov 0x6c(%ecx),%ebp ; \
0xf3771ae1: mov %ebp,0x70(%ecx) ; / bar = vfoo
0xf3771ae4: mov 0x68(%ecx),%edi ; sz
0xf3771ae7: inc %ebx ; i++
0xf3771ae8: mov %ecx,%eax ;
0xf3771aea: shr $0x9,%eax ; ??? \ Probably replaced later
0xf3771aed: movb $0x0,-0x3113c300(%eax) ; ??? / by some barrier code?
0xf3771af4: test %edi,0xf77ce000 ; safepoint
0xf3771afa: cmp %edi,%ebx ; i < sz ?
0xf3771afc: jl 0xf3771ad0 ;
The reason I think the above code stands in for a barrier is that when taking the NullPointerException, the scalable version has a XCHG
, which acts as a barrier, while the non-scalable version has a NOP there.
The rationale would be that there needs to be a happens-before ordering between the initial load of vfoo
and joining the thread. In the volatile case, the barrier would be inside the loop, so it wouldn't need to be elsewhere. What I don't understand is why XCHG
isn't used inside the loop. Maybe runtime detection of MFENCE support?