<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">On 10 Aug 2022, at 7:38, Dan Heidinga wrote:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">Thanks for writing this up, John.</p>
<p dir="auto">This matches my thinking overall. Looking for confirmation on one
<br>
point below related to synchronized blocks & non-atomic values.</p>
<p dir="auto">On Wed, Jul 13, 2022 at 11:32 PM John Rose <john.r.rose@oracle.com> wrote:</p>
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">So, let’s talk about the Java Memory Model and consequent JVM support for flattenable types.</p>
</blockquote></blockquote><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">…</p>
</blockquote></blockquote><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">One thing to observe in passing is that when a method like C::next runs, it has a value this which is on the stack, not in heap. This means that there can be no races on the fields of this during the execution of any method. So as the body of any C method executes, the fields this.array and this.index cannot change. This is as one would expect from final fields. But it’s true even if the original copy of this is being concurrently trashed by racing writes. This means the JIT cannot treat race-prone heap containers as spilled copies of this, to be reloaded at leisure.</p>
</blockquote><p dir="auto">Agreed. A field (V.*F) must be "sticky" after having been read and so
<br>
we can't re-read from the heap containers.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Yet another way of saying this is that the JMM Read event that picked up some field value from the heap has a single, unambiguous value (as a bundle of scalar values, of course). Races come from consulting multiple JMM Reads, not from any possible variation in a single JMM Read. The value of a single JMM Read event can and must be modeled (by the JIT) as a bit pattern to be stored in registers or in spill slots, not a heap location subject to any extra JMM Read events. This is not new; the JIT never re-reads a field value that was already read by a <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">getfield</code> instruction, unless there is a second <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">getfield</code> instruction.</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">It has to pick up any and all fields that it might need just once per field needed in an inlined method call. It might kill dead stores, of course. If the class of this is atomic, it must use an atomic to pick up this.*F* (or the parts needed) at one time; otherwise it can pick up the needed parts of this.*F* as needed, but at most once per part.</p>
</blockquote><p dir="auto">I think this is right but I'm still slightly uncomfortable with
<br>
picking up the "needed parts of this.*F* as needed" as it can greatly
<br>
expand the race window in user code in ways that aren't obvious from
<br>
the source code. Since this only applies to racy programs, the
<br>
correct answer for the programmer - regardless of the size of the
<br>
window - is to properly synchronize the access.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Yes. I guess my point is that a race from two back-to-back reads (of adjacent locations, say) is not qualitatively different from a race from the same two reads separated by other stuff. The two scenarios will show the same kinds of races, just at different rates (probabilities).</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">In this model, when do the reads of fields actually occur for
<br>
synchronized blocks? In the following code, all C.val fields used
<br>
after the block must be read during the synchronized block, correct?</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Correct. The JMM sees just one Read event that is trapped in the block by bracketing synchronization events. It doesn’t matter (for this point) that the value of the Read consists of two scalars (array/index). The value must be sampled between the block brackets.</p>
<p dir="auto">Looking closer, the Read event decomposes to two scalar sub-Reads. Those might happen in separate hardware instructions, or a single non-atomic hardware instruction. In such a case, a non-synchronized Write event in another thread, using a non-atomic sequence of instructions, could cause a race. (Same as with <code style="margin: 0; padding: 0 0.4em; border-radius: 3px; background-color: #F7F7F7;">long</code> tearing in today’s Java.)</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">static C.val sharedVal = ....;</p>
<p dir="auto">C.val myVal;
<br>
synchronized(someLock) {
<br>
myVal = sharedVal;
<br>
}
<br>
... myVal.array ...
<br>
... myVal.index</p>
<p dir="auto">Assuming all the subsequent field reads through myVal are guaranteed
<br>
to have been privatized by the end of the synchronized block, then I
<br>
think the model makes sense and sounds right to me.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Thanks for giving it a close look!</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">@Tobi, have the rest of the OpenJ9 JIT developers weighed in on this model yet?</p>
</blockquote><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">…</p>
</blockquote></blockquote></div>
<div class="markdown" style="white-space: normal;">
</div></div></body>
</html>