[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 20:09:29 UTC 2014
Hi David,
I was thinking about the fact that java.lang.invoke code is leaking into
java.lang.Class. Perhaps, If you don't mind rewriting the code, a better
code structure would be, if j.l.Class changes only consisted of adding a
simple:
+ // A reference to canonicalizing cache of java.lang.invoke.MemberName(s)
+ // for members declared by class represented by this Class object
+ private transient volatile Object memberNameData;
...and nothing else. All the logic could live in MemberName itself
(together with Unsafe machinery for accessing/cas-ing Class.memberNameData).
Now to an idea about implementation. Since VM code is not doing any
binary-search and only linearly scans the array when it has to update
MemberNames, the code could be changed to scan a linked-list of
MemberName(s) instead. You could add a field to MemberName:
class MemberName {
...
// next MemberName in chain of interned MemberNames for particular
declaring class
private MemberName next;
Have a volatile field in MemberNameData (or ClassData - whatever you
call it):
class MemberNameData {
...
// a chain of interned MemberName(s) for particular declaring class
// accessed by VM when it has to modify them in-place
private volatile MemberName memberNames;
MemberName add(Class<?> klass, int index, MemberName mn, int
redefined_count) {
mn.next = memberNames;
memberNames = mn;
if (jla.getClassRedefinedCount(klass) == redefined_count) { //
no changes to class
...
... code to update array of sorted MemberName(s) with new 'mn'
...
return mn;
}
// lost race, undo insertion
memberNames = mn.next;
return null;
}
This way all the worries about ordering of writes into array and/or size
are gone. The array is still used to quickly search for an element, but
VM only scans the linked-list.
What do you think of this?
Regards, Peter
On 11/03/2014 05:36 PM, David Chase wrote:
>>> 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?
>> 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.
> exactly, with the restriction that it would be compiler-induced bubbling, not architectural.
> Which is both better, and worse — I don’t have to worry about crazy hardware, but the rules
> of java/jvm "memory model" are not as thoroughly defined as those for java itself.
>
> I added a method to Atomic (.storeFence() ). New webrev to come after I rebuild and retest.
>
> Thanks much,
>
> David
>
>> 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();
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20141103/10f939c3/attachment-0001.html>
More information about the hotspot-compiler-dev
mailing list