RFR: 8142334: Improve lazy initialization of java.lang.invoke

Peter Levart peter.levart at gmail.com
Thu Nov 12 18:08:43 UTC 2015


Hi Claes,

It might be ok as you say, but then I don't understand the need to
pre-resolve() NamedFunctions in original code. Do you?

Regards, Peter
On Nov 12, 2015 6:44 PM, "Claes Redestad" <claes.redestad at oracle.com> wrote:

> Hi,
>
> On 2015-11-12 17:26, Peter Levart wrote:
>
>> Hi Claes,
>>
>> I have one concern...
>>
>>  645     private static NamedFunction getConstantFunction(int idx) {
>>  646         NamedFunction function = FUNCTIONS[idx];
>>  647         if (function != null) {
>>  648             return function;
>>  649         }
>>  650         return setCachedFunction(idx, makeConstantFunction(idx));
>>  651     }
>>  652
>>  653     private static synchronized NamedFunction setCachedFunction(int
>> idx, final NamedFunction function) {
>>  654         // Simulate a CAS, to avoid racy duplication of results.
>>  655         NamedFunction prev = FUNCTIONS[idx];
>>  656         if (prev != null) {
>>  657             return prev;
>>  658         }
>>  659         FUNCTIONS[idx] = function;
>>  660         function.resolve();
>>  661         return function;
>>  662     }
>>
>>
>> Above is a classical double-checked locking idiom, but it is not using
>> volatile variable to publish the NamedFunction instance. I wonder if this
>> is safe. Even if the FUNCTIONS[idx] slot was a volatile variable,  you
>> would publish new instance before resolving it. Is it OK to publish
>> unresolved NamedFunction(s)? There is a NamedFunction.resolvedHandle()
>> instance method that makes sure NamedFunction is resolved before returning
>> a MethodHandle, but there are also usages of dereferencing
>> NamedFunction.resolvedHandle field directly in code. Are you sure that such
>> unresolved or almost resolved instance of NamedFunction is never used in
>> such places where NamedFunction.resolvedHandle field is dereferenced
>> directly?
>>
>> In original code those NamedFunctions were resolved in static initializer
>> so they were published properly.
>>
>
> I think we're relying on the fact that relevant field, member, is final
> and thus will be published correctly.
>
> resolvedHandle will be set to null in the constructor we're using anyhow:
>
>         NamedFunction(Method method) {
>             this(new MemberName(method));
>         }
> ...
>         NamedFunction(MemberName member) {
>             this.member = member;
>             this.resolvedHandle = null;
>         }
>
> I inquired myself about the rationale for using of DCL without volatile
> elsewhere in the java.lang.invoke code and was pointed to this earlier
> discussion that shed light on the assumptions and caveats:
> http://mail.openjdk.java.net/pipermail/hotspot-dev/2014-May/013902.html
>
> So, all in all, I think the partially unsafe publication is actually safe
> for our purposes here.
>
> Thanks!
>
> /Claes
>



More information about the core-libs-dev mailing list