Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8019968

Reference CAS induces GC store barrier even on failure

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • 9
    • hotspot
    • b81
    • x86
    • generic

        Stumbled upon this while reading the disassembly.

        If we have the CAS against the reference, i.e.:

        AtomicReference<Object> ref = ...;
        Object newObject = ...;

        void m() {
            Object cur;
            do {
                cur = ref.get();
            } while (!ref.compareAndSet(cur, newObject));
        }

        ...then HotSpot pessimistically emits the GC store barrier even if CAS had failed. While this does not necessarily violate correctness with the current implementation, this might have the adverse effect on contended performance. We will certainly retry the CAS, but having the auxiliary actions before the retry can significantly lower our chances of succeeding (i.e. some other thread can steal the cache line under our feet).

        This is what disassembly shows on Linux x86_64, JDK 8b94:

        ; load ref, null checks, load value
          0x00007f712fbeb24c: mov 0xc(%rbx),%edx
          0x00007f712fbeb24f: test %edx,%edx
          0x00007f712fbeb251: je 0x00007f712fbeb31c
          0x00007f712fbeb257: lea (%r12,%rdx,8),%rdi
          0x00007f712fbeb25b: lea 0xc(%r12,%rdx,8),%r13
          0x00007f712fbeb260: mov 0x0(%r13),%eax

        ; CAS
          0x00007f712fbeb264: lock cmpxchg %ecx,0x0(%r13)

        ; check the result into r11:
          0x00007f712fbeb26a: sete %r11b
          0x00007f712fbeb26e: movzbl %r11b,%r11d

        ; !!! card mark !!!
          0x00007f712fbeb272: mov %r13,%r10
          0x00007f712fbeb275: shr $0x9,%r10
          0x00007f712fbeb279: mov %r12b,(%rsi,%r10,1)

        ; CAS successful?
          0x00007f712fbeb27d: test %r11d,%r11d

        ; ... then <return>
          0x00007f712fbeb280: je 0x00007f712fbeb330

        ; load isDone, operations++, safepoint poll, isDone check, back branch
          0x00007f712fbeb286: movzbl 0x8c(%r8),%r10d
          0x00007f712fbeb28e: add $0x1,%rbp
          0x00007f712fbeb292: test %eax,0xa71fd68(%rip)
          0x00007f712fbeb298: test %r10d,%r10d
          0x00007f712fbeb29b: je 0x00007f712fbeb24c


        For the reference, doing AtomicLong instead:

        ; load ref, load value
          0x00007ff2cbe1994e: mov 0x10(%rbx),%r10d
          0x00007ff2cbe19952: mov 0x10(%r12,%r10,8),%rax

        ; CAS
          0x00007ff2cbe19957: lock cmpxchg %r8,0x10(%r12,%r10,8) ; CAS

        ; check result into %r9
          0x00007ff2cbe1995e: sete %r9b
          0x00007ff2cbe19962: movzbl %r9b,%r9d

        ; CAS successful?
          0x00007ff2cbe19966: test %r9d,%r9d

        ; then <return>
          0x00007ff2cbe19969: je 0x00007ff2cbe19a00

        ; load isDone, operations++, safepoint poll, isDone check, back branch
          0x00007ff2cbe1996f: movzbl 0x8c(%r14),%r11d
          0x00007ff2cbe19977: add $0x1,%rbp
          0x00007ff2cbe1997b: test %eax,0xa6d867f(%rip)
          0x00007ff2cbe19981: test %r11d,%r11d
          0x00007ff2cbe19984: je 0x00007ff2cbe1994e

              shade Aleksey Shipilev
              shade Aleksey Shipilev
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: