Hello, So I have joined this list many years later than the cool kids, because I have been reading the API docs and considering using SwitchPoint in a design, and I wanted to be sure I understand its properties before blowing too much time on it.
The questions I still had after the javadocs sent me on to the OpenJDK GitHub repo to look at the sources, where I saw that SwitchPoint uses MutableCallSite (as indeed its javadoc says "Simple implementations ... may"), so invalidateAll relies on MutableCallSite.syncAll for the magic to happen, and MutableCallSite.syncAll is ... interesting. It has a very long javadoc comment that begins by appearing to make some attractive promises: 1. effect is to force all future readers of each call site's target to accept the most recently stored value 2. may (may??) block until all readers have (somehow) decached all previous versions 3. reader threads may observe previous versions of the target until the syncAll call returns. (Does this mean they may not do so after the syncAll call returns? And if so, wouldn't that imply #2 is really something stronger than "may"?) 4. it "is likely to be expensive" (as the trade-off for having getTarget be as cheap as a plain read, and relying on magic to make the sync work). But the javadoc for syncAll doesn't end there; it forges ahead into Java Memory Model details, where the attractive early promises seem to get renegotiated a bit. In particular, the very first thing it says about "an arbitrary thread T (other than the current thread)" now starts with an "if": "If T executes a synchronization action A after the volatile write" ... *then* it must see the updated target. ... the promise now begins to seem ... a bit ... conditional. And indeed, the code of syncAll begins with the volatile write to STORE_BARRIER (really a lazySet, which these days is documented as the memory effects of setRelease). Then it calls getClass() on all of the call sites, perhaps only to generate the specified NPE for any null value, unless getClass() has some other effect I don't know about. And then after that loop, there seems to be the line with all the magic: // FIXME: NYI And that's all there is to the method. And I see that's the magic line in jdk17 [1] and all the way back to its appearance in jdk7 [2]. I see that I am not the first to notice that, and that the syncAll method has been commented out in Android with a note that it wasn't implemented. [3] (Which seems like it would break SwitchPoint, but then it looks like Android never imported SwitchPoint at all.) So by this point I am quite puzzled. I have spent the morning reviewing the archives of this list, back to the inception of MutableCallSite in late 2010. I read the initial design description by John Rose [4]. I see considerable discussion of using SwitchPoint, not least in the many JRuby posts by Charles Oliver Nutter. Presumably if SwitchPoint didn't reliably switch stuff, that would have been remarked on by now. So what am I missing? Has this emperor got clothes I'm just not seeing? Is part of the promised behavior actually being supplied by the VM or compiler, maybe by treating this class specially, in a way I do not see in the source? Is the key to simply assume that every other thread T someday "executes a synchronization action A" for unrelated reasons, and then sees the update? If so, is there some upper bound that can be stated for how long after syncAll returns that might be? Were the Android developers correct in removing syncAll for being unimplemented? Perhaps because it requires magical support from the VM that is not present in their VM? Or were they just trigger-happy, removing it only because they looked at the source and (like me) failed to convince themselves nothing was missing? If really nothing is missing, would it be worthwhile to remove the // FIXME: NYI in the source, just for the peace of mind of people (like me) who might be looking there to understand the behavior? Thanks for any light you can open my eyes to .... Regards, Chapman Flack [1] https://github.com/openjdk/jdk17u/blob/master/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java#L281 [2] https://github.com/openjdk/jdk7/blob/34cd7bc/jdk/src/share/classes/java/dyn/MutableCallSite.java#L203 [3] https://android.googlesource.com/platform/libcore/+/17162a1%5E!/ojluni/src/main/java/java/lang/invoke/MutableCallSite.java [4] https://groups.google.com/g/jvm-languages/c/nJ0-hPx0VnY _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net https://mail.openjdk.java.net/mailman/listinfo/mlvm-dev