[9] RFR(S): 8005873: JRuby test_respond_to.rb asserts with: MT-unsafe modification of inline cache

Remi Forax forax at univ-mlv.fr
Wed May 14 20:23:51 UTC 2014


On 05/14/2014 03:15 PM, Vladimir Ivanov wrote:
>
> On 5/14/14 4:12 PM, Paul Sandoz wrote:
>>
>> On May 14, 2014, at 12:47 PM, Vladimir Ivanov 
>> <vladimir.x.ivanov at oracle.com> wrote:
>>
>>> Tobias, I agree with your evaluation.
>>>
>>
>> V. tricky one to track down!
>>
>>  From @Stable:
>>
>>   * It is (currently) undefined what happens if a field annotated as 
>> stable
>>   * is given a third value.  In practice, if the JVM relies on this 
>> annotation
>>   * to promote a field reference to a constant, it may be that the 
>> Java memory
>>   * model would appear to be broken, if such a constant (the second 
>> value of the field)
>>   * is used as the value of the field even after the field value has 
>> changed.
>>
>> I dunno if that was a contributing factor in this case.
> No, @Stable doesn't contribute to the problem.
>
>>
>>> My only concern is that @Stable doesn't work for 
>>> AtomicReferenceArray, so JIT doesn't see what is stored in the array.
>>
>> Yes, stability needs to be associated with the array elements.
>>
>>
>>> Maybe use a lock instead?
>>>
>>
>> Or perhaps use Unsafe.CAS directly within setCachedLambdaForm?
> Yes, Unsafe is another option here. But since cache updates should be 
> rare, Unsafe is an overkill here IMO - locking should be fine.

I don't get it, AtomicReferenceArray.CAS implementation uses Unsafe.CAS

>
>>
>> Also, as a consequence of using AtomicReferenceArray the following 
>> change may result in a memory barrier on some architectures:
>>
>>       public LambdaForm cachedLambdaForm(int which) {
>> -        return lambdaForms[which];
>>
>> +        return lambdaForms.get(which);
>>       }
>>
>> since lambdaForms.get will call Unsafe.getObjectVolatile.
> MTF.cachedLambaForm isn't on a fast path, so it shouldn't be a problem.
>
>> Separately, i think code that calls setCachedLambdaForm needs to be 
>> double checked to ensure that the return value is used. For example, 
>> in MethodHandleImpl.makeGuardWithCatchForm i see:
>>
>> basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
>>          return lform;
>>
>> which i think needs to be:
>>
>>          return 
>> basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
> Good catch! MTF.setCachedLambdaForm usages should be fixed as well.

IMO, forms can be a classical Java array,

*   final @Stable_LambdaForm[]_  lambdaForms;*


setCachedLambdaForm can use Unsafe.compareAndSwapObject

*   // Make sure cache entry is set only once*
*   if (UNSAFE.compareAndSwap(***lambdaForms*, which, null, form)) {*
*       return form;*
*   }
   **return cachedLambdaForm(which);*


and cachedLambdaForm can try to use the stable value,
if the stable value is not null, it's ok, otherwise we can use 
getVolatileObject

   public LambdaForm cachedLambdaForm(int which) {
     LambdaForm form = lambdaForms[which];
     if (form != null) {
       return form;
     }
     return UNSAFE.getObjectVolatile(lambdaForms, which);
   }


cheers,
Rémi

>
> Best regards,
> Vladimir Ivanov
>
>>
>> Paul.
>>
>>
>>
>>



More information about the hotspot-dev mailing list