- Loading...
...
...
ObjectMonitor T-deflate
T-enter +-----------------------+ --------------------------------------
---------------- | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)
owner contended | count=-max_jint | :
atomic inc count +-----------------------+ prev = cmpxchg(-max_jint, &count, 0)
if (count <= 0 && owner if (prev == 0 &&
== DEFLATER_MARKER) { owner == DEFLATER_MARKER) {
restore header restore object header
retry enter finish the deflation
} }
ObjectMonitor T-deflate
T-enter +-----------------------+ ----------------------------------------
---------------- | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)
owner contended | count=1 | :
atomic inc count +-----------------------+ prev = cmpxchg(-max_jint, &count, 0)
if (count > 0) if (prev != 0 ||
do contended owner != DEFLATER_MARKER)
enter work bailout on deflation (nothing to undo)
...
...
...
T-hash ObjectMonitor T-deflate
---------------------- +-----------------------+ --------------------------------------
save_om_ptr() { | owner=NULL | cmpxchg(DEFLATER_MARKER, &owner, NULL)
: | count=0 |
atomic inc ref_count | ref_count=0 |
+-----------------------+
T-hash ObjectMonitor T-deflate
---------------------- +-----------------------+ --------------------------------------
save_om_ptr() { | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)
: | count=0 | if (waiters != 0 or ref_count != 0) {
atomic inc ref_count | ref_count=1 | }
+-----------------------+ prev = cmpxchg(-max_jint, &count, 0)
T-hash ObjectMonitor T-deflate
------------------------ +-----------------------+ --------------------------------------
save_om_ptr() { | owner=DEFLATER_MARKER | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc ref_count | count=-max_jint | if (waiters != 0 or ref_count != 0) {
if (owner == | ref_count=0 1 | }
DEFLATER_MARKER) { +-----------------------+ prev = cmpxchg(-max_jint, &count, 0)
atomic dec ref_count count || if (prev == 0 &&
return false to to \/ owner == DEFLATER_MARKER) {
cause a retry restore header
} finish the deflation
}
T-hash ObjectMonitor T-deflate
------------------------ retry +-----------------------+ ----------------------------------------
save_om_ptr() { | owner=NULL | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc ref_count | count=0 | if (waiters != 0 or ref_count != 0) {
if (owner == restore object header
} | owner=DEFLATER_MARKER | finish the deflation
| count=-max_jint | }
| ref_count=1 | cmpxchg(NULL, &owner, DEFLATER_MARKER)
DEFLATER_MARKER) { 0 |
+-----------------------+ return false to cause a retry
} }
if (object no longer prev = cmpxchg(-max_jint, &count, 0)
has a monitor or
is a different
monitor) {
If T-hash wins the race, then the ref_count will cause T-deflate to bail out on deflating the monitor which is what this diagram shows; ref_count is not mentioned in any of the previous examples for simplicity.
T-hash ObjectMonitor T-deflate
------------------------ +-----------------------+ ----------------------------------------
save_om_ptr() { | header=dmw_no_hash | cmpxchg(DEFLATER_MARKER, &owner, NULL)
atomic inc ref_count | owner=DEFLATER_MARKER | if (waiters != 0 or ref_count != 0) {
if (owner == | count=0 | cmpxchg(NULL, &owner, DEFLATER_MARKER)
DEFLATER_MARKER) { | ref_count=1 | bailout on deflation
} +-----------------------+ }
if (object no longer || prev = cmpxchg(-max_jint, &count, 0)
has a monitor or \/
is a different +-----------------------+
monitor) { | header=dmw_no_hash |
atomic dec ref_count | owner=NULL |
return false to | count=0 |
cause a retry | ref_count=1 |
} +-----------------------+
save om_ptr in the ||
ObjectMonitorHandle \/
} +-----------------------+
if save_om_ptr() { | header=dmw_hash |
if no hash | owner=NULL |
gen hash & merge | count=0 |
hash = hash(header) | ref_count=1 |
} +-----------------------+
atomic dec ref_count
return false to
cause a retry
}
save om_ptr in the
ObjectMonitorHandle
}
If T-hash wins the first race, then the ref_count will cause T-deflate to bail out on deflating the monitor; ref_count is not mentioned in any of the previous examples for simplicity. If T-deflate wins the race, then T-hash will retry which will bring us to the second race.
In the second T-hash versus T-deflate race, T-deflate is trying to restore the object's header/mark from the ObjectMonitor*'s header/dmw field and T-hash is trying to read a stable mark value from the object's header/mark that will allow it to get/set a hash code. When T-hash reads a stable mark value:
...
return hash...
Please note that in Carsten's original prototype, there was another race in ObjectSynchronizer::FastHashCode() when the object's monitor had to be inflated. The setting of the hash code in the ObjectMonitor's header/dmw could race with T-deflate. That race is resolved in this version by the use of an ObjectMonitorHandle in the call to ObjectSynchronizer::inflate(). The ObjectMonitor* returned by ObjectMonitorHandle.om_ptr() has a non-zero ref_count so no additional races with T-deflate are possible.
...