[concurrency-interest] a volatile bug?

Vitaly Davidovich vitalyd at gmail.com
Wed May 16 16:34:17 EDT 2012


I looked at the assembly on SO again (the pastebin link) and it seems to be
correct actually: after 'a' is cmp'ed against zero, 'b' is read from
memory.  But now someone is saying there that it sometimes generates the
correct assembly and other times not - very strange.
0x025bd2b9: cmp $0x0,%edx

30. 0x025bd2bc: je 0x025bd2a8 ;

32. 0x025bd2be: mov $0x147062e8,%edx ; {oop('test/TestVolatile')}

33. 0x025bd2c3: mov 0x1c4(%edx),%edx ;*getstatic b

34. ; - test.TestVolatile::run at 10 (line 17)

35. 0x025bd2c9: cmp $0x0,%edx

Sent from my phone
On May 16, 2012 3:55 PM, "Aleksey Shipilev" <aleksey.shipilev at gmail.com>
wrote:

> Update. GVN is clearly under suspicion -XX:-UseGlobalValueNumbering
> mitigates the bug in my setup. Digging through C1 codebase to see
> rules for volatiles.
>
> -Aleksey.
>
> On Wed, May 16, 2012 at 11:23 PM, Aleksey Shipilev
> <aleksey.shipilev at gmail.com> wrote:
> > All right, here's what is on the table.
> >
> > This bug is reproduced for me on Linux i686 with:
> > java version "1.7.0_04"
> > Java(TM) SE Runtime Environment (build 1.7.0_04-b20)
> > Java HotSpot(TM) Client VM (build 23.0-b21, mixed mode)
> >
> > It reproduces immediately only with -client.
> > Both -server and -Xint do NOT reproduce the bug.
> > The code is there in original SO post
> >
> http://stackoverflow.com/questions/10620680/why-volatile-in-java-5-doesnt-synchronize-cached-copies-of-variables-with-main
> >
> > C1 seems to miscompile run(), and indeed does CSE for local:
> >
> >  # {method} 'run' '()V' in 'Test$1'
> > [Verified Entry Point]
> >  0xb4a91e80: mov    %eax,-0x4000(%esp)
> >  0xb4a91e87: push   %ebp
> >  0xb4a91e88: sub    $0x18,%esp         ;*invokestatic access$000
> >                                        ; - Test$1::run at 0 (line 11)
> >  0xb4a91e8b: mov    $0xa09c4270,%edx   ;   {oop(a 'java/lang/Class' =
> 'Test')}
> >>>>>>>  0xb4a91e90: mov    0x74(%edx),%edx    ;*getstatic b <<<<<----
> loads $b to %edx
> >                                        ; - Test::access$000 at 0 (line 1)
> >                                        ; - Test$1::run at 0 (line 11)
> >  0xb4a91e93: jmp    0xb4a91e9e         ; OopMap{off=40}
> >                                        ;*goto
> >                                        ; - Test$1::run at 10 (line 13)
> >  0xb4a91e98: test   %eax,0xb77a9100    ;*goto
> >                                        ; - Test$1::run at 10 (line 13)
> >                                        ;   {poll}
> >  0xb4a91e9e: mov    $0xa09c4270,%ecx   ;   {oop(a 'java/lang/Class' =
> 'Test')}
> >>>>>>  0xb4a91ea3: mov    0x70(%ecx),%ecx    ;*getstatic a  <<<<<
> volatile read for $a
> >                                        ; - Test::access$100 at 0 (line 1)
> >                                        ; - Test$1::run at 4 (line 13)
> >  0xb4a91ea6: cmp    $0x0,%ecx     // <---- $a is at %ecx
> >  0xb4a91ea9: je     0xb4a91e98         ;*ifne
> >                                        ; - Test$1::run at 7 (line 13)
> >  >>>> 0xb4a91eab: cmp    $0x0,%edx     // <<<<<<---- $b is cached in
> %edx here
> >  0xb4a91eae: jne    0xb4a91ed8         ;*ifne
> >                                        ; - Test$1::run at 16 (line 17)
> >  0xb4a91eb4: nopl   0x0(%eax)
> >  0xb4a91eb8: jmp    0xb4a91f0e         ;   {no_reloc}
> >  0xb4a91ebd: xchg   %ax,%ax
> >  0xb4a91ec0: jmp    0xb4a91f28         ; implicit exception:
> > dispatches to 0xb4a91f18
> >  0xb4a91ec5: nop                       ;*getstatic out
> >                                        ; - Test$1::run at 19 (line 18)
> >  0xb4a91ec6: cmp    (%ecx),%eax        ; implicit exception:
> > dispatches to 0xb4a91f32
> >  0xb4a91ec8: mov    $0xa09c6488,%edx   ;*invokevirtual println
> >                                        ; - Test$1::run at 24 (line 18)
> >                                        ;   {oop("error")}
> >
> >
> > Thanks,
> > Aleksey.
> >
> > On Wed, May 16, 2012 at 11:12 PM, Vitaly Davidovich <vitalyd at gmail.com>
> wrote:
> >> It can be a compiler (mis)optimization that causes this, and not x86
> memory
> >> ordering.
> >>
> >> Someone posted the assembly output in the comments on SO and it does
> seem
> >> like there's a place that loads 'b' from the stack rather than memory.
> >> Hans' theory of CSE sounds plausible - can someone repro this without
> that
> >> "int tt = b;" line?
> >>
> >> Adding hotspot compiler guys in case they want to chime in.
> >>
> >> Sent from my phone
> >>
> >> On May 16, 2012 3:07 PM, "Aleksey Shipilev" <aleksey.shipilev at gmail.com
> >
> >> wrote:
> >>>
> >>> On Wed, May 16, 2012 at 10:40 PM, Boehm, Hans <hans.boehm at hp.com>
> wrote:
> >>> > A JDK bug AND a serious test suite omission?
> >>>
> >>> Stress tests would probably JIT-compile the code in question. See
> below.
> >>>
> >>> > But is the problem real?  Can it be reproduced on a mainstream JVM?
> >>>
> >>> Same question.
> >>>
> >>> > Note that the example in the original posting also read b before the
> >>> > loop,
> >>> > so naïve common subexpression elimination would cause the bug.
> >>> >  Hopefully
> >>> > nobody does CSE in cases like this.
> >>>
> >>> FWIW, the test case in SO would probably not hit any compilation
> >>> threshold in HotSpot, so it could be executed in interpreter. Then,
> >>> assuming the interpreter does not reorder Java code, and assuming
> >>> original SO poster runs Windows, and hence x86, and hence has TSO,
> >>> this bug seems very unlikely. I would be surprised if it actually
> >>> *can* be reproduced. That makes the whole story rather interesting.
> >>>
> >>> -Aleksey.
> >>>
> >>> _______________________________________________
> >>> Concurrency-interest mailing list
> >>> Concurrency-interest at cs.oswego.edu
> >>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20120516/a006b643/attachment-0001.html>


More information about the Concurrency-interest mailing list