Ask for a patch review: CallSite.target is not volatile

Rémi Forax forax at univ-mlv.fr
Thu Sep 18 16:40:34 PDT 2008


John Rose a écrit :
> On Sep 13, 2008, at 7:27 AM, Rémi Forax wrote:
>
>   
>> currently CallSite.target is not volatile, so if an invokedynamic  
>> bootstrap
>> method calls setTarget() in one thread, other threads may not see the
>> new target.
>>
>> Proposed changes :
>>  - make target volatile
>>  - use unsafe.putOrdered to set the field in a more lightweight way.
>>     
>
> Hmm...  The EDR is ambiguous about this, and needs to be tightened  
> up.  It does say that the bulk invalidation API is intended to  
> provide a global interlock, and gives some freedom to the propagation  
> of setTarget effects.  What the EDR says about "next call" refers to  
> a global ordering that doesn't really exist in the JVM apart from  
> synchronization.
>   
yop, i have seen that. I'm currently not able to provide
that requirement for the backport.
> Native JVM implementations don't require target to be explicitly  
> volatile.  In fact, individual threads need the freedom to cache the  
> target, e.g., as a loop invariant for a fast-path version of a loop.   
> The important thing to optimize here is the speed of *reading* the  
> target field.  Writes can be as slow as we want (I use a native  
> method call).
>   
The problem is if a new class is loaded by another thread,
I may want to change the target for any other threads.
If you cache the target, it will not change when a new class is discovered.
i.e the target will change in RAM but not in the local cache.

ConcurrentLinkedQueue<Data> queue=...

thread1:
for(Data data:queue) {
   // invokedynamic call using data
}


thread2:
queue.add(new DataSubClass());
// here the classloader load DataSubClass and
// defeat the optimisation done at
// invokedynamic call site.


> All this is independent of whether the code says "volatile" or not on  
> the field, but it may be better not to mark it volatile, since that  
> seems to make a guarantee about propagation of setTarget effects.
>
> Note that the JVM reads the target field in a specialized way, not  
> necessarily through a bytecode.  Also, the writes to the target field  
> go through an accessor, so once again, the volatility of the field  
> does not necessarily matter. 
not agree, if the accessor is inlined, target can be not reloaded from 
the RAM.
>  Except to the backport.  For the  
> backport, I guess the volatile bit is needed.  So, yes, that's a good  
> change.
>   
Yes.
> Maybe the right thing to do is move target into a mixin-style  
> superclass, java.dyn.impl.CS, and have it be volatile in the backport.
>   
I'am not sure you can avoid the volatile read.
> This takes me to the second proposed change.
>
>   
>>  - change alls field visibility from protected to private because :
>>     1) protected fields appear in the JavaDoc,
>>         so another implementation of CallSite (like the one currently
>> use by the backport)
>>         is not allowed.
>>     2) caller, name and type are final so caller(), name() and type()
>>         can be used instead.
>>         subclasses can override checkTarget() to do nothing, in that
>>         case setTarget() is equivalent to change the target field.
>>         So I see no reason to declare this fields protected.
>>     
>
> I want the CallSite to be usable two ways:
> 1. created by the JVM to reify invokedynamic instructions
> 2. creatable by Java code to simulate invokedynamic sites interpretively
>
> Therefore, it's important to allow Java code to make its own flavor  
> of CallSite.  Hence the protected methods & fields.
>
> This could also be done with a CallSite interface, but it seems  
> easier to me (and to other JVM vendors I think) to make it a concrete  
> class.
>
> Therefore, let's keep the protected stuff for now, unless we decide  
> to make CallSite into an interface.
>   
You don't need protected field if you have accessors. And currently
those accessors exist.
> I want to factor the 292 API into common classes, including the  
> public ones, and non-standard implementation-specific classes, one  
> version for each kind of JVM and one for the backport.  The  
> java.dyn.impl package contains the implementation-specific classes.   
> (This name will change to go outside of the java.* hierarchy.)  When  
> a public type needs to mix in fields or methods, it does so via  
> inheritance from an implementation superclass.  Switching between  
> backport and native implementations will therefore require  
> adjustments to boot class path or the installed rt.jar.
>   
Why not use a static final field, like the anonk code already does ?
and detect at runtime if there is a native impl or if the backport
must be used.
> Why use mixins?  Although such pluggable implementations are more  
> often done via delegation or subclassing, the performance  
> requirements of method handles requires a more aggressive (less  
> flexible) pattern of single-inheritance mixins.
>   
I think a static final field is a better option.
> -- John
>   
Rémi



More information about the mlvm-dev mailing list