[9] RFR(L) 8013267 : move MemberNameTable from native code to Java heap, use to intern MemberNames

Peter Levart peter.levart at gmail.com
Mon Nov 3 16:42:30 UTC 2014


On 11/03/2014 05:16 PM, Peter Levart wrote:
> On 11/03/2014 01:49 PM, David Chase wrote:
>> On 2014-11-02, at 10:49 PM, David Holmes <david.holmes at oracle.com> 
>> wrote:
>>>> The change is to load the volatile size for the loop bound; this 
>>>> stops the stores
>>>> in the loop from moving earlier, right?
>>> Treating volatile accesses like memory barriers is playing a bit 
>>> fast-and-loose with the spec+implementation. The basic 
>>> happens-before relationship for volatiles states that if a volatile 
>>> read sees a value X, then the volatile write that wrote X 
>>> happened-before the read [1]. But in this code there are no checks 
>>> of the values of the volatile fields. Instead you are relying on a 
>>> volatile read "acting like acquire()" and a volatile write "acting 
>>> like release()".
>>>
>>> That said you are trying to "synchronize" the hotspot code with the 
>>> JDK code so you have stepped outside the JMM in any case and 
>>> reasoning about what is and is not allowed is somewhat moot - unless 
>>> the hotspot code always uses Java-style accesses to the Java-level 
>>> variables.
>> My main concern is that the compiler is inhibited from any peculiar 
>> code motion; I assume that taking a safe point has a bit of barrier 
>> built into it anyway, especially given that the worry case is 
>> safepoint + JVMTI.
>>
>> Given the worry, what’s the best way to spell “barrier” here?
>> I could synchronize on classData (it would be a recursive lock in the 
>> current version of the code)
>>    synchronized (this) { size++; }
>> or I could synchronize on elementData (no longer used for a lock 
>> elsewhere, so always uncontended)
>>    synchronized (elementData) { size++; }
>> or is there some Unsafe thing that would be better?
>>
>> (core-libs-dev — there will be another webrev coming.  This is a 
>> runtime+jdk patch.)
>>
>> David
>
> Hi David,
>
> You're worried that writes moving array elements up for one slot would 
> bubble up before write of size = size+1, right? If that happens, VM 
> could skip an existing (last) element and not update it.
>
> It seems that Unsafe.storeFence() between size++ and moving of 
> elements could do, as the javadoc for it says:
>
>     /**
>      * Ensures lack of reordering of stores before the fence
>      * with loads or stores after the fence.
>      * @since 1.8
>      */
>     public native void storeFence();

You might need a storeFence() between each two writes into the array 
too. Your moving loop is the following:

2544                 for (int i = oldCapacity; i > index; i--) {
2545                     // pre: element_data[i] is duplicated at [i+1]
2546                     element_data[i] = element_data[i - 1];
2547                     // post: element_data[i-1] is duplicated at [i]
2548                 }


If we start unrolling, it becomes:

w1: element_data[old_capacity - 0] = element_data[old_capacity - 1];
w2: element_data[old_capacity - 1] = element_data[old_capacity - 2];
w3: element_data[old_capacity - 2] = element_data[old_capacity - 3];
...

Can compiler reorder w2 and w3 (just writes - not the whole statements)? 
Say that it reads a chunk of elements into the registers and then writes 
them out, but in different order, and a check for safepoint comes inside 
this chunk of writes... This is hypothetical, but it could do it without 
breaking the local semantics...

Peter

>
>
> Regards, Peter
>
>
>
>>
>>> BTW the Java side of this needs to be reviewed on 
>>> core-libs-dev at openjdk.java.net
>>>
>>> David H.
>>>
>>> [1] 
>>> http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.4
>>>
>>>
>>>> David
>




More information about the core-libs-dev mailing list