--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-05-06 15:58:52.391326434 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-05-06 15:58:51.991323873 +0200 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.replacements; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; @@ -38,6 +39,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -51,6 +53,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorSuccOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -574,6 +577,32 @@ traceObject(trace, "-lock{inflated:simple}", object, false); counters.unlockInflatedSimple.inc(); return true; + } else { + int succOffset = objectMonitorSuccOffset(INJECTED_VMCONFIG); + Word succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(FREQUENT_PROBABILITY, succ.isNonNull())) { + // There may be a thread spinning on this monitor. Temporarily setting + // the monitor owner to null, and hope that the other thread will grab it. + monitor.writeWord(ownerOffset, zero()); + memoryBarrier(STORE_STORE | STORE_LOAD); + succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(NOT_FREQUENT_PROBABILITY, succ.isNonNull())) { + // We manage to release the monitor before the other running thread even + // notices. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } else { + // Either the monitor is grabbed by a spinning thread, or the spinning + // thread parks. Now we attempt to reset the owner of the monitor. + if (probability(FREQUENT_PROBABILITY, !monitor.logicCompareAndSwapWord(ownerOffset, zero(), thread, OBJECT_MONITOR_OWNER_LOCATION))) { + // The monitor is stolen. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } + } + } } } counters.unlockStubInflated.inc(); @@ -692,6 +721,7 @@ public final SnippetCounter unlockStub; public final SnippetCounter unlockStubInflated; public final SnippetCounter unlockInflatedSimple; + public final SnippetCounter unlockInflatedTransfer; public Counters(SnippetCounter.Group.Factory factory) { SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); @@ -716,6 +746,7 @@ unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + unlockInflatedTransfer = new SnippetCounter(exit, "unlock{inflated:transfer}", "unlocked an object monitor in the presence of ObjectMonitor::_succ"); } }