RFR: 8205908: Unnecessarily strong memory barriers in ParNewGeneration::copy_to_survivor_space

Michihiro Horie HORIE at jp.ibm.com
Wed Jun 27 00:22:39 UTC 2018


Dear all,

Would you please review the following change?
Bug: https://bugs.openjdk.java.net/browse/JDK-8205908
Webrev: http://cr.openjdk.java.net/~mhorie/8205908/webrev.00/


[Current implementation]
ParNewGeneration::copy_to_survivor_space tries to move live objects to a
different location. There are two patterns on how to copy an object
depending on whether there is space to allocate new_obj in to-space or not.
If a thread cannot find space to allocate new_obj in to-space, the thread
first executes the CAS with a dummy forwarding pointer "ClaimedForwardPtr",
which is a sentinel to mark an object as claimed. After succeeding in the
CAS, a thread can copy the new_obj in the old space. Here, suppose thread A
succeeds in the CAS, while thread B fails in the CAS. When thread A
finishes the copy, it replaces the dummy forwarding pointer with a real
forwarding pointer. After thread B fails in the CAS, thread B returns the
forwardee after waiting for the copy of the forwardee is completed. This is
observable by checking the dummy forwarding pointer is replaced with a real
forwarding pointer by thread A. In contrast, if a thread can find space to
allocate new_obj in to-space, the thread first copies the new_obj and then
executes the CAS with the new_obj. If a thread fails in the CAS, it
deallocates the copied new_obj and returns the forwardee.

Procedure of ParNewGeneration::copy_to_survivor_space : ([L****] represents
the line number in src/hotspot/share/gc/cms/parNewGeneration.cpp)
1. Try to each allocate space for new_obj in to-space [L.1110]
2. If fail in the allocation in to-space [L1117]
    2.1. Execute the CAS with the dummy forwarding pointer [L1122] ——— (A)
    2.2. If fail in the CAS, return the forwardee via real_forwardee()
[L1123]
    2.3. If succeed in the CAS [L1128]
          2.3.1. If promotion is allowed, copy new_obj in the old area
[L1129]
          2.3.2. If promotion is not allowed, forward to obj itself [L1133]
    2.4. Set new_obj as forwardee [L1142]
3. If succeed in the allocation in to-space [L1144]
    3.1. Copy new_obj [L1146]
    3.2. Execute the CAS with new_obj [L1148] ——— (B)
4. Dereference the new_obj for logging. Each new_obj copied by each thread
at step 3.1 is used instead of forwardee() [L1159]
5. If succeed in either CAS (A) or CAS (B), return new_obj [L1163]
6. If fail in CAS (B), get the forwardee via real_forwardee(). Unallocate
new_obj in to-space [L1193]
7. Return forwardee [L1203]

For reference, real_forwardee() is as shown below:
oop ParNewGeneration::real_forwardee(oop obj) {
    oop forward_ptr = obj->forwardee();
    if (forward_ptr != ClaimedForwardPtr) {
        return forward_ptr;
    } else {
        // manually inlined for readability.
        oop forward_ptr = obj->forwardee();
        while (forward_ptr == ClaimedForwardPtr) {
            waste_some_time();
            forward_ptr = obj->forwardee();
        }
        return forward_ptr;
    }
}

Regarding the CAS (A),
There is no copy before the CAS.
Dereferencing the forwardee must be allowed after obtaining the forwardee.

Regarding the CAS (B),
There is a copy before the CAS.
Dereferencing the forwardee must be allowed after obtaining the forwardee.


[Observation on the current implementation]
No fence is necessary before and after the CAS (A).
Release barrier is necessary before the CAS (B).
The forwardee_acquire() must be used instead of forwardee() in
real_forwardee().


[Performance measurement]
The critical-jOPS of SPECjbb2015 improved by 12% with this change.


Best regards,
--
Michihiro,
IBM Research - Tokyo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-gc-dev/attachments/20180627/12be8604/attachment.htm>


More information about the hotspot-gc-dev mailing list