Hi Jeremy, Sorry for the late reply. Catching after some distractions and being away.
> On 22 Jan 2016, at 19:03, Jeremy Manson <jeremyman...@google.com> wrote: > > Couple of thoughts: > The Java Language Specification permits operations to be executed in orders > different than are apparent in program source code, subject to constraints > arising, for example, from the use of locks, volatile fields or VarHandles. > The static methods, fullFence, acquireFence, releaseFence, loadLoadFence > andstoreStoreFence, can also be used to impose constraints. Their > specifications are phrased in terms of the lack of "reorderings" -- > observable ordering effects that might otherwise occur if the fence were not > present. > > > There is no notion of reordering (per se) in the JLS; the fact that > reorderings can occur is just implied by the way programs can be observed to > behave. So, these fence operations don't map to anything non-implementation > dependent. I don't think it would be impossible to fix the spec to define > something that works the way you want (similar to the final field semantics), > but it isn't in there already. You might want to call that out (either by > saying this behavior is best effort implementation-dependent or by fixing the > spec). > Until we update the JMM spec, pushed out beyond 9, we are in a bit of a bind and have to hand wave a bit for both access mode methods and fences, both of which talk about reorderings (see getAcquire/setRelease for example). There is the following at the end, but it’s easy to loose sight of with all the other sections: * @apiNote * More precise phrasing of the specification of access mode methods and memory * fence methods may accompany future updates of the Java Language * Specification. I moved that up into the fences paragraph. * <p>In addition to supporting access to variables under various access modes, * a set of static methods, referred to as memory fence methods, is also * provided for fine-grained control of memory ordering. * * The Java Language Specification permits operations to be executed in * orders different than are apparent in program source code, subject to * constraints arising, for example, from the use of locks, {@code volatile} * fields or VarHandles. The static methods, {@link #fullFence fullFence}, * {@link #acquireFence acquireFence}, {@link #releaseFence releaseFence}, * {@link #loadLoadFence loadLoadFence} and {@link #storeStoreFence * storeStoreFence}, can also be used to impose constraints. Their * specifications, as is the case for certain access modes, are phrased in terms * of the lack of "reorderings" -- observable ordering effects that might * otherwise occur if the fence was not present. More precise phrasing of the * specification of access mode methods and memory fence methods may accompany * future updates of the Java Language Specification. I could append another sentence: Until then, such reordering behaviour is considered implementation-dependent on a best-effort basis. But perhaps the less we say the better? > If a VarHandle references a read-only variable (for example a final field) > then write, atomic update and numeric atomic update access modes are not > supported and corresponding methods throw UnsupportedOperationException. > > Are you sure you want to limit it in this way? There are an awful lot of > calls to setAccessible in the world of reflection. And writing to final > fields *does* map to something sensible in the spec. In fact, it would be > great to have something that wasn't quite such a blunt instrument as > setAccessible. Indeed, very much a blunt instrument. Note that setAccessible would otherwise be required to be called on the Field before being unreflected (either for unreflectVarHandle or, as is the case today, unreflectSetter/Getter). I don’t wanna widen the accessibility hole of this blunt instrument right now; it’s easy to widen rather than shrink later on if need be. The motivation behind this is we want to move towards a world "final really means final" and thus lots of nice optimisations may ensue. It may be a long and windy road to get there but we have some plans and are starting to work some routes towards that goal. > > getVolatile > public final Object getVolatile(Object... args) > Returns the value of a variable, with memory semantics of reading a volatile > variable. > > Reading *which* volatile variable? You probably mean that all getVolatiles > and setVolatiles provide semantics that behave as if the variable being > written / read was declared volatile in the first place, but it is worth > calling out. > /** * Returns the value of a variable, with memory semantics of reading as if * the variable was declared {@code volatile}. ... Object getVolatile(Object... args); /** * Sets the value of a variable to the {@code newValue}, with memory * semantics of setting as if the variable was declared {@code volatile}. … void setVolatile(Object... args); I also updated the plain accessors using similar “as if” language. > Nits: > The following nits are copied and translated from documentation on MethodHandle. > As is usual with virtual methods, source-level calls to access mode methods > compile to an invokevirtual instruction. More unusually, the compiler must > record the actual argument types, and may not perform method invocation > conversions on the arguments. Instead, it must push them on the stack > according to their own unconverted types. The VarHandle object itself is > pushed on the stack before the arguments. The compiler then calls the > VarHandle with a symbolic type descriptor which describes the argument and > return types. > > This is somewhat oddly worded. The compiler doesn't push arguments on a > stack or call anything - it generates instructions that do that. > I updated to: * As is usual with virtual methods, source-level calls to access mode methods * compile to an {@code invokevirtual} instruction. More unusually, the * compiler must record the actual argument types, and may not perform method * invocation conversions on the arguments. Instead, it must generate * instructions to push them on the stack according to their own unconverted * types. The VarHandle object itself will be pushed on the stack before the * arguments. The compiler then generates an {@code invokevirtual} instruction * that invokes the access mode method with a symbolic type descriptor which * describes the argument and return types. > The first time a invokevirtual instruction is executed it is linked, by > symbolically resolving the names in the instruction and verifying that the > method call is statically legal > > I keep trying not to call this out as a nit, but there should be no comma > between "linked" and "by”. Updated. In both cases I also updated the relevant areas in MethodHandle. Thanks, Paul.