[concurrency-interest] Here's why Atomic*FieldReference access checking is broken

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Oct 8 10:28:03 EDT 2014


>> Peter, in term of implementation, you can use the fact that you can patch
>> the class when you call defineAnonymous class, so you can insert the
>> offset and the class,
>> without using a thread local which is really a hack.
>
> Yeah, I said it's a hack. But I don't know any other easy way. The
> constant patches requires me to parse or generate the bytecode to
> compute the index of the constant pool entry. In my hack, as you can
> see, I use javac in ahead-of-time mode to "generate" the bytecode...
FTR, ClassWriter.newConst() is the way to get the index of constant pool 
entry.

This is how constant pool patches are used for j.l.i.LambdaForms:

java.lang.invoke.InvokerBytecodeGenerator:
     String constantPlaceholder(Object arg) {
         String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++;
         // insert placeholder in CP and remember the patch
         int index = cw.newConst((Object) cpPlaceholder);
         cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, 
arg));
         return cpPlaceholder;
     }

     Object[] cpPatches(byte[] classFile) {
         int size = getConstantPoolSize(classFile);
         Object[] res = new Object[size];
         for (CpPatch p : cpPatches.values()) {
	    res[p.index] = p.value;
         }
         return res;
     }

UNSAFE.defineAnonymousClass(HOST_CLASS, classBytes, cpPatches(classBytes));

Best regards,
Vladimir Ivanov

>
>>
>> There is another way to do exactly the same things, make ccClass
>> constant foldable for
>> the JIT without asking to load a bunch of classes. The implementation
>> of the Updater
>> can be moved into java.lang.invoke and use the annotation @Stable, in
>> that case,
>> the field ccCache will be considered as constant if the updater is
>> constant itself,
>> this trick doesn't come from me but from Paul Sandoz which currently
>> works on
>> this area as Doug mention.
>
> Thanks for sharing, Remi.
> I wondered what those @Stable annotations meant. I thought they were
> just fancy documentation. It's a pity that this is reserved for
> java.lang.invoke package use only. The annotation could be public, but
> be effective only on system classes like @CallerSensitive for example...
>
> Regards, Peter
>
>>
>> cheers,
>> Rémi
>>
>> On 10/08/2014 12:23 PM, √iktor Ҡlang wrote:
>>> Hi Peter,
>>>
>>> can you quantify: " is almost no additional runtime overhead."?
>>>
>>> On Wed, Oct 8, 2014 at 11:38 AM, Peter Levart <peter.levart at gmail.com
>>> <mailto:peter.levart at gmail.com>> wrote:
>>>
>>>     On 10/05/2014 10:44 PM, Peter Levart wrote:
>>>
>>>         The 3rd report shows a result of experimental
>>>         AtomicIntegerFieldUpdater implementation which loads new
>>>         VM-anonymous class for each new instance which allows VM
>>>         compiler to specialize code for a particular field. Such
>>>         implementation is nearly as fast as Java field access. This is
>>>         just a proof of concept. A little hack-ish, doesn't include
>>>         the fix for the overly restrictive protected access yet, but
>>>         here it is if anyone is interested:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/AtomicFieldUpdater.AccessChecks/AnonClassPerInstance/AtomicIntegerFieldUpdater.java
>>> <http://cr.openjdk.java.net/%7Eplevart/jdk9-dev/AtomicFieldUpdater.AccessChecks/AnonClassPerInstance/AtomicIntegerFieldUpdater.java>
>>>
>>>
>>>
>>>     Hi,
>>>
>>>     I experimented further with this.
>>>
>>>     It seems that making 'offset' a static final field is not
>>>     necessary to get optimal performance out of specialized
>>>     one-class-per-instance Atomic*FieldUpdater. Only the 'cclass'
>>>     field used in check matters. So 'offset' can be pushed up to
>>>     abstract Atomic*FieldUpdaterImpl as a final instance field. Now
>>>     that specialized subclass of Atomic*FieldUpdaterImpl is only
>>>     'cclass' specific, it can be shared among instances that use the
>>>     same 'cclass'. That means only one VM-anonymous subclass per
>>>     target class (or subclass/caller of target class when protected
>>>     access is involved). The VM-anonymous subclass is cached using
>>>     ClassValue:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/AtomicFieldUpdater.AccessChecks/AnonClassPerCclass/AtomicIntegerFieldUpdater.java
>>> <http://cr.openjdk.java.net/%7Eplevart/jdk9-dev/AtomicFieldUpdater.AccessChecks/AnonClassPerCclass/AtomicIntegerFieldUpdater.java>
>>>
>>>     I seems that with such Atomic*FieldUpdater there is no compelling
>>>     reason to use Unsafe directly as there is almost no additional
>>>     runtime overhead. The only method that is about 30% slower than
>>>     Java counterpart is get(), but there's hardly a reason to use it
>>>     instead of simple Java volatile field read.
>>>
>>>     Regards, Peter
>>>
>>>
>>>     _______________________________________________
>>>     Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> <mailto:Concurrency-interest at cs.oswego.edu>
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>>>
>>>
>>>
>>> --
>>> Cheers,
>>>>>>
>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>>
>>
>>
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>


More information about the Concurrency-interest mailing list