I think I now have an answer, at least partial one.
The initial question makes an assumption that JVM specifically flushes something on entry/exit of synchronized blocks. But that's not necessary. Instead, JMM dictates that anything in one synchronized(X) happens-before releasing X, then that happens-before acquiring X in another thread, and that happens-before actions following it in that other thread in its synchronized(X). Hence, JVM does not need to introduce some special processing to inspect contents of synchronized blocks on entry/exit; it can just apply the limitations on caching/reordering coming from happens-before the same way that it applies any happens-before limitations anywhere else. It might be something that gets done once when doing JIT compilation - for example making sure something is not locally cached at all, instead of flushing caches on entry/exit of some code block.