Unsafe.storeFence produces a floating fence
Andrew Haley
aph at redhat.com
Fri Nov 18 15:45:53 UTC 2016
Here's a jcstress test:
public class ShortFencedTest {
Shell shell;
public static class Shell {
short x;
public Shell() {
this.x = (short) 0xFFFF;
UnsafeHolder.U.storeFence();
}
}
@Actor
public void actor1() {
shell = new Shell();
}
@Actor
public void actor2(ShortResult1 r) {
Shell sh = shell;
r.r1 = (sh == null) ? 42 : sh.x;
}
}
the problem is that the call to storeFence() floats above the store to
this.x in Shell(). In fact, it even floats past the object creation.
Here's the generated assembly code for actor1. The storeFence has floated past
the creation of the object, all the way to the entry point of actor1:
[Verified Entry Point]
0x0000007fa5593900: nop
0x0000007fa5593904: sub x8, sp, #0x4, lsl #12
0x0000007fa5593908: str xzr, [x8]
0x0000007fa559390c: sub sp, sp, #0x30
0x0000007fa5593910: stp x29, x30, [sp,#32]
0x0000007fa5593914: dmb ish ;*invokevirtual storeFence {reexecute=0 rethrow=0 return_oop=0}
; - sun.misc.Unsafe::storeFence at 3 (line 1215)
; - org.openjdk.jcstress.tests.init.primitives.fenced.ShortFencedTest$Shell::<init>@12 (line 47)
; - org.openjdk.jcstress.tests.init.primitives.fenced.ShortFencedTest::actor1 at 5 (line 53)
0x0000007fa5593918: orr x0, xzr, #0x60
0x0000007fa559391c: ldr x2, [x28,x0]
0x0000007fa5593920: orr x3, xzr, #0x70
0x0000007fa5593924: ldr x3, [x28,x3]
0x0000007fa5593928: add x4, x2, #0x10
0x0000007fa559392c: cmp x4, x3
0x0000007fa5593930: b.hi 0x0000007fa55939bc
0x0000007fa5593934: str x4, [x28,x0]
0x0000007fa5593938: orr x0, xzr, #0x180
0x0000007fa559393c: nop
0x0000007fa5593940: mov x0, xzr
0x0000007fa5593944: orr x3, xzr, #0x1
0x0000007fa5593948: str x3, [x2,x0]
0x0000007fa559394c: orr x0, xzr, #0x8
0x0000007fa5593950: mov x3, #0xd0000 // #851968
; {metadata('org/openjdk/jcstress/tests/init/primitives/fenced/ShortFencedTest$Shell')}
0x0000007fa5593954: movk x3, #0x83f8
0x0000007fa5593958: str w3, [x2,x0]
0x0000007fa559395c: orr x0, xzr, #0xc
0x0000007fa5593960: str wzr, [x2,x0]
0x0000007fa5593964: dmb ish
0x0000007fa5593968: mov x0, x2
0x0000007fa559396c: orr x2, xzr, #0xc
0x0000007fa5593970: orr x3, xzr, #0xffff
0x0000007fa5593974: strh w3, [x0,x2]
0x0000007fa5593978: orr x2, xzr, #0xc
0x0000007fa559397c: lsr x0, x0, #3
0x0000007fa5593980: str w0, [x1,x2] ;*putfield shell {reexecute=0 rethrow=0 return_oop=0}
; - org.openjdk.jcstress.tests.init.primitives.fenced.ShortFencedTest::actor1 at 8 (line 53)
0x0000007fa5593984: lsr x1, x1, #9
0x0000007fa5593988: mov x0, #0xf000 // #61440
0x0000007fa559398c: movk x0, #0xafe5, lsl #16
0x0000007fa5593990: movk x0, #0x7f, lsl #32
0x0000007fa5593994: add x1, x1, x0
0x0000007fa5593998: mov x0, xzr
0x0000007fa559399c: strb wzr, [x1,x0]
0x0000007fa55939a0: ldp x29, x30, [sp,#32]
0x0000007fa55939a4: add sp, sp, #0x30
0x0000007fa55939a8: mov x8, #0x5000 // #20480
; {poll_return}
0x0000007fa55939ac: movk x8, #0xb4fd, lsl #16
0x0000007fa55939b0: movk x8, #0x7f, lsl #32
0x0000007fa55939b4: ldr wzr, [x8] ; {poll_return}
0x0000007fa55939b8: ret ;*return {reexecute=0 rethrow=0 return_oop=0}
; - org.openjdk.jcstress.tests.init.primitives.fenced.ShortFencedTest::actor1 at 11 (line 54)
UnsafeFencePlugin looks like:
public static class UnsafeFencePlugin implements InvocationPlugin {
private final int barriers;
public UnsafeFencePlugin(int barriers) {
this.barriers = barriers;
}
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe) {
// Emits a null-check for the otherwise unused receiver
unsafe.get();
b.add(new MembarNode(barriers));
return true;
}
}
MembarNode is a FixedWithNextNode, but in this case it's simply added to the
graph.
I'd love to have an opportunity to fix this bug, but I'd like some guidance.
Andrew.
More information about the graal-dev
mailing list