I will say that this helps the volatile reference problem we all face,
but I know Jochen and I are still looking for a way to completely get
rid of our soft/weak proxy/metaclass wrappers :( I'm this || close to
hacking Maxine to have an additional mutable reference on all objects
just so I can see how it would play out...

On Fri, Oct 1, 2010 at 3:44 AM, John Rose <john.r.r...@oracle.com> wrote:
> I had a chance to sit down with Rich at JavaOne to discuss this.  (Thanks 
> Rich!)
>
> The key problem is caching the result of a partial evaluation.  (For example, 
> an expected method dispatch at a call site, or a metaclass which summarizes 
> the shape of a type.)  The cached value can be made "pure" (read-only) but it 
> is subject (at least potentially) to very slow change, once per "epoch".  
> Let's call such a slowly varying value a "stable value".
>
> (Compare "stationary values" Ian Rogers's paper for PPPJ'08.  What dynamic 
> language folks need is an epochal variation of this concept, a value which is 
> stationary most of the type and changes once in a blue moon.  Hence, "stable 
> value".)
>
> The typical dynamic language technique is to use a volatile variable to hold 
> the cached value.  The volatility ensures that once-per-epoch changes get 
> immediately picked up by threads.  The problem is that the volatile reference 
> defeats caching and inlining of all sorts.
>
> The JVM has better tricks.  It can cache and inline a vtable lookup if it can 
> prove (from class hierarchy analysis) that a method is not overridden.  The 
> invokedynamic instruction has similar capabilities.  If the epoch changes 
> (because a new overriding method is loaded), code needs to be edited or 
> discarded, and threads need to be interrupted.  This happens at a safepoint.
>
> Here's a sketch for a user-level hook to stable values:
>
> public class StableValue<T> {
>  /** Get the current value. */
>  public T getStableValue() {...}
>  /** Set the current value.  This may be costly. */
>  public void getStableValue(T x) {...}
>  /** Commit the current value.  Future calls to set() will throw. */
>  public void getStableValue() {...}
> }
>
> I'm going to abbreviate "getStableValue" as "get", etc., from here on.  It is 
> tempting to make an analogy with java.lang.ref.Reference, but I don't know if 
> that makes enough sense.  By using the full term "getStableValue" we can 
> contemplate mixing stable values into other types:
>  public class CallSite extends StableValue<MethodHandle> { ... }
>
> Anyway, the idea is that the JVM is encouraged (by the user) to perform 
> optimizations on the value returned by the get() call.  If it does so, it 
> must somehow watch for future calls to set().  The freeze() call (from the 
> user) informs the JVM that it can stop watching.  This should probably be a 
> system-defined class, because it may have private fields which participate in 
> the JVM's task of tracking dependencies.

It seems like it's in the family of Atomic* to me, and as you
mentioned in a followup email we need to make the set+freeze
operation (at minimum) be atomic. So why not just borrow the
AtomicReference API and have AtomicStableReference or
StableAtomicReference (and perhaps AtomicStable*) that also implement
getAndSet, incrementAndSet, incrementAndFreeze, and so on?

I also liked Doug Lea's "fences" API, though I guess that's off the
table for Java 7 now. It was certainly more flexible, since it allowed
us more freedom about which fields to use (and therefore we would not
have to change current impls...we just fence them), but it is perhaps
more invasive at a VM level.

> Of course, static variables in Java are somewhat amenable to this treatment 
> "automagically".  But the above abstraction guides the JVM much more clearly. 
>  I don't think we can retrofit this behavior onto normal Java variables.  (We 
> can with "static final" of course, but those guys can't evolve over the 
> epochs.)  It's better to be explicit here, I think.
>
> StableValue should be subclassable, in the same style as java.lang.ref 
> classes.  That will remove gratuitous indirections.  For example, a 
> StableHashTable could be built whose entries subclass StableValue, much like 
> a WeakHashTable.
>
> It should be possible to build lazy values on top of StableValues, by 
> overriding get() to check if the current value is null.  (Another reason to 
> subclass.)

compareAndSet?

> The StableValue.set call should perform the memory effects of a release (cf. 
> monitorexit) before the value is published.
>
> The StableValue.get call should perform the memory effects of an acquire (cf. 
> monitorenter) before the value is fetched, the *first* time any given thread 
> calls get() on a given StableValue.  Subsequent get() calls are "for free".  
> This is why a safepoint mechanism is needed, to force querying threads to 
> re-aquire relevant memory blocks.
>
> A StableValue can be "entangled" with optimized code if its value is folded 
> into the code.  If this happens, the JVM needs to keep track of the 
> StableValue so that it can adjust or discard the code the next time the value 
> changes.  The StableValue class probably needs invisible synthetic fields to 
> help it link into the JVM's data structures for tracking code dependencies.

One disadvantage this has from "fences" is that we will have to always
walk a reference to get to the StableValue object. Perhaps we can roll
in the optimization Tom R. came up with to fold away repeated accesses
of the same final field reference? Or will Hotspot see through the
field reference + StableValue.get and fold the whole thing together?

> The caching behavior of java.dyn.CallSite with respect to setTarget could 
> then be defined in terms of StableValue.  It will be "as if" the CallSite 
> held its current target in a StableValue.
>
> Class metadata (of type MyMD) can be stored in a 
> ClassValue<StableValue<MyMD>>.  For information on ClassValue, see:
>  http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-mlvm/java/dyn/ClassValue.html

Ah-ha, this is what I missed before. This definitely does help with
the Class/MetaClass relationship most of us will have to deal with, so
with this and StableValue we're really getting some powerful tools
here.

> -- John
>
> P.S. None of the above helps with the special case of getting invalidation 
> when types gain new subtypes.  There's another hook needed there, I think.  
> For example, ClassValues could be optionally made sensitive to class 
> hierarchy changes, so that they get recomputed if new subtypes are loaded.  
> Not sure if this is needed, though.

Now I get this statement as well. If a new subtype comes in you may or
may not want the parent's ClassValue to apply down-hierarchy. If you
don't want it to apply, you need a way to invalidate and re-prime
ClassValues for the super and subtype. Agreed...there's a mechanism of
some sort needed here, OR ClassValues could be limited to exactly one
type from one classloader, and we'll handle the overhead of binding
new types that enter the system.

- Charlie

-- 
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to jvm-langua...@googlegroups.com.
To unsubscribe from this group, send email to 
jvm-languages+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en.

Reply via email to