Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Editorial pass on "Hashcodes and Object Header Interference" section.

...

If we have a race between a T-deflate thread and a thread trying to get/set a hashcode (T-hash), then the first race is between the ObjectMonitorHandle.save_om_ptr(obj, mark) call in T-hash and deflation protocol in T-deflate.

Note: ref_count is not mentioned in any of the previous sections for simplicity.

...

    T-hash                  ObjectMonitor              T-deflate
    ----------------------  +-----------------------+  ----------------------------------------
    save_om_ptr() {         | owner=NULL            |  deflate_monitor_using_JT() {
      :                     | contentions=0         | 1> cmpxchg(DEFLATER_MARKER, &owner, NULL)
        1> atomic inc ref_count  | ref_count=0           |
                            +-----------------------+
    • The data fields are at their starting values.
    • T-deflate is about to execute cmpxchg().
    • T-hash is about to increment ref_count.
    • The "1>" markers are showing where each thread is at for the ObjectMonitor box.

Racing Threads

    T-hash                  ObjectMonitor              T-deflate
    ----------------------  +-----------------------+  --------------------------------------------
    save_om_ptr() {         | owner=DEFLATER_MARKER | deflate_monitor_using_JT() {
      :   | contentions=0  |  cmpxchg(DEFLATER_MARKER, &owner, NULL)
      atomic   1> atomic inc ref_count  | ref_count=0           |  1> if (waiters != 0 || ref_count != 0) {
                            +-----------------------+  }
prev = cmpxchg(-max_jint, &contentions, 0)
    • T-deflate has set the owner field to DEFLATER_MARKER.
    • T-deflate is about to check the waiters and ref_count fields.
    • T-hash is about to inc the ref_count field (T-hash has made no progress).
    • The "1>" markers are showing where each thread is at for the ObjectMonitor box.

T-deflate Wins

If T-deflate wins the race, then T-hash will have to retry until the object and/or ObjectMonitor are stable.

...

    • T-deflate made it past the first ref_count check before T-hash incremented it.
    • T-deflate set the contentions field to -max_jint and T-enter incremented the ref_count field.
    • The first ObjectMonitor box is showing the fields at this point and the "1>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-hash observes "owner == DEFLATER_MARKER && contentions <= 0" so it decrements ref_count and returns false to cause a retry.
    • If T-deflate sees "prev == 0 && owner == DEFLATER_MARKER && ref_count == 0" , then so it has won the race so it .
    • T-deflate restores obj header (not shown) and finishes the deflation.
    • The second ObjectMonitor box is showing the fields at this point and the "2>" markers are showing where each thread is at for that ObjectMonitor box..
    • T-deflate finishes the deflation work.
    • T-hash returns false to cause a retry and when When T-hash retries:
      • if it observes "owner == DEFLATER_MARKER && contentions <= 0" it will retry again.
      • if it observes the restored object header:
        • if the object's header does not have a hash, then generate a hash and merge it with the object's header.
        • Otherwise, extract the hash from the object's header and return it.

...

If T-hash wins the race, then the ref_count will cause T-deflate to bail out on deflating the monitor.

Note: header is not mentioned in any of the previous sections for simplicity.

...

    • T-hash has incremented ref_count before T-deflate made it past that check.
    • The first ObjectMonitor box is showing the fields at this point and the "1>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-deflate bails out on deflation, but first it tries to restore the owner field:
      • The return value of cmpxchg() is not checked here.
      • If T-deflate cannot restore the owner field to NULL, then another thread has managed to enter the monitor (or enter and exit the monitor) and we don't want to overwrite that information.
    • T-hash observes:
      • "owner == DEFLATER_MARKER && contentions == 0" or
      • "owner == NULL && contentions == 0" so it does not cause a retry.
    • T-hash verifies that the object still has a monitor and that monitor still refers to our current ObjectMonitor.
    • The second ObjectMonitor box is showing the fields at this point and the "2>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-hash saves the ObjectMonitor* in the ObjectMonitorHandle (not shown) and returns to the caller.
    • if save_om_ptr() returns true since the ObjectMonitor is safe:
      • if ObjectMonitor's 'header/dmw' field does not have a hash, then generate a hash and merge it with the 'header/dmw' field.
      • Otherwise, extract the hash from the ObjectMonitor's 'header/dmw' field.
    • The third ObjectMonitor box is showing the fields at this point and the "3>" marker is showing where T-hash is at for that ObjectMonitor box.
    • T-hash decrements the ref_count field.
    • T-hash returns the hash value.

...

    • T-deflate made it past the first ref_count check before T-hash incremented it.
    • T-hash made it past the "owner == DEFLATER_MARKER && contentions <= 0" check before T-deflate updated contentions.
    • The first ObjectMonitor box is showing the fields at this point and the "1>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-deflate set sets the contentions field to -max_jint and is about the make the last of the protocol checks.
    • T-hash verifies that the object still has a monitor and that monitor still refers to our current ObjectMonitor.
    • The second ObjectMonitor box is showing the fields at this point and the "2>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-deflate sees that "ref_count != 0" and bails out on deflation but it has to restore some data if possible:
      • The return value of cmpxchg() is not checked here.
      • If T-deflate cannot restore the owner field to NULL, then another thread has managed to enter the monitor (or enter and exit the monitor) and we don't want to overwrite that information.
      • Add back max_jint to restore the contentions field to its proper value (which may not be the same as when we started).
    • T-hash verifies that the object still has a monitor and that monitor still refers to our current ObjectMonitor.saves the ObjectMonitor* in the ObjectMonitorHandle (not shown) and returns to the caller.
    • if save_om_ptr() returns true since the ObjectMonitor is safe:
      • if ObjectMonitor's 'header/dmw' field does not have a hash, then generate a hash and merge it with the 'header/dmw' field.
      • Otherwise, extract the hash from the ObjectMonitor's 'header/dmw' field.
    • The third ObjectMonitor box is showing the fields at this point and the "3>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-hash decrements the ref_count field.
    • T-hash returns the hash value.

...

    • T-deflate made it past the first ref_count check before T-hash incremented it.
    • T-deflate set the contentions field to -max_jint and T-enter incremented the ref_count field.
    • The first ObjectMonitor box is showing the fields at this point and the "1>" markers are showing where each thread is at for that ObjectMonitor box.
    • T-hash observes "owner == DEFLATER_MARKER && contentions <= 0" and starts to bail out.
    • T-deflate sees "ref_count != 0" and bails out on deflation but it has to restore some data if possible:
      • The return value of cmpxchg() is not checked here.
      • If T-deflate cannot restore the owner field to NULL, then another thread has managed to enter the monitor (or enter and exit the monitor) and we don't want to overwrite that information.
      • Add back max_jint to restore the contentions field to its proper value (which may not be the same as when we started).
    •  T-hash decrements ref_count and returns false to cause a retry.
    • The second ObjectMonitor box is showing the fields at this point and the "2>" markers are showing where each thread is at for that ObjectMonitor box.
    • When T-hash returns false to cause a retry and when T-hash retries:
      • the object's header will still refer to the ObjectMonitor (i.e., not deflated)
      • it will observe "owner != DEFLATER_MARKER"
        • if the ObjectMonitor's header/dmw does not have a hash, then generate a hash and merge it with the ObjectMonitor's header/dmw.
        • Otherwise, extract the hash from the ObjectMonitor's header/dmw and return it.

...