RFR(S): 8150921: Update Unsafe getters/setters to use double-register variants
Mikael Vidstedt
mikael.vidstedt at oracle.com
Fri May 6 21:40:13 UTC 2016
On 5/5/2016 2:56 PM, David Holmes wrote:
> Hi Mikael,
>
> On 6/05/2016 4:35 AM, Mikael Vidstedt wrote:
>>
>> Updated webrevs here:
>>
>> jdk:
>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.03/jdk/webrev/
>> hotspot:
>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.03/hotspot/webrev/
>>
>>
>>
>> Incremental from webrev.02:
>>
>> jdk:
>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.03.incr/jdk/webrev/
>>
>>
>> hotspot:
>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.03.incr/hotspot/webrev/
>>
>
> Sorry I'm going to have to insist on a minor renaming as we are not
> getting or putting mutexes. How about get_jlong_locked/put_jlong_locked ?
>
> No need to see another webrev.
Ah, yes, fully agree. Will change before I push.
David/Paul/Aleksey/John - thanks for reviews and feedback!
Cheers,
Mikael
>
> Thanks,
> David
>
>>
>> Changes from webrev.02:
>>
>> - javadoc updates for getAddress/putAddress in line with Paul's feedback
>> (move the more descriptive comment to the double-register methods, with
>> an @see on the single-reg guys)
>> - updates to make MemoryAccess::get_mutex jlong specific
>>
>> Some additional comments inline..
>>
>> On 5/3/2016 10:07 PM, David Holmes wrote:
>>> On 4/05/2016 4:43 AM, Mikael Vidstedt wrote:
>>>>
>>>> Thank you very much for the review, some comments inline...
>>>>
>>>> On 5/3/2016 8:15 AM, Aleksey Shipilev wrote:
>>>>> On 05/03/2016 08:09 AM, Mikael Vidstedt wrote:
>>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8150921
>>>>>> Webrev (jdk):
>>>>>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.01/jdk/webrev/
>>>>>>
>>>>>>
>>>>>> Webrev (hotspot/):
>>>>>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.01/hotspot/webrev/
>>>>>>
>>>>>>
>>>>>>
>>>>> Nice move overall!
>>>>>
>>>>> unsafe.cpp:
>>>>>
>>>>> *) Why do we Handle-ize incoming object in CompareAnd*? Is this
>>>>> because
>>>>> we may acquire a mutex, and the object may be gone? Either way, I see
>>>>> you have dropped Handle from Unsafe_CompareAndSwapLong, but kept
>>>>> it in
>>>>> Unsafe_CompareAndExchangeLong -- why?
>>>>>
>>>>> *) Ditto for old {Get|Set}LongVolatile -- it used to Handle-ize
>>>>> before
>>>>> acquiring a mutex -- now we don't do that in MemoryAccess.
>>>>
>>>> My bad. As you say resolving the object should happen after the mutex
>>>> has been acquired (see long comment starting on line 377 for the
>>>> background). I have added back the Handle in CompareAndSwapLong and
>>>> moved the addr() call in the mutex methods of MemoryAccess. Thank you
>>>> for catching that!
>>>>
>>>>>
>>>>> vmSymbols.cpp:
>>>>>
>>>>> *) {get|put}Address_raw intrinsics used to be conditionalized under
>>>>> UseUnalignedAccesses. Baffles me why, because the old native code in
>>>>> Unsafe_{Get|Set}NativeAddress/unsafe.cpp would seem to fail with
>>>>> misaligned addresses. I wonder if the intent was to never fail, and
>>>>> then
>>>>> we should really use Unsafe.{get|put}Unaligned in new Unsafe.java
>>>>> {get|set}Address to dodge misalign faults?
>>>>
>>>> I also failed to see what the conditional intrinsification is
>>>> trying to
>>>> achieve given that the native code does nothing special for the
>>>> unaligned case. Unless I'm missing something the proposed change makes
>>>> it no worse, and will potentially improve performance a tad on the
>>>> pickier platforms. If anything we may want to consider introducing
>>>> methods for getAddressUnaligned and putAddressUnaligned as a separate
>>>> change.
>>>>
>>>>> library_call.cpp:
>>>>>
>>>>> *) What is the point for doing this check:
>>>>>
>>>>> 2372 if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
>>>>> 2373 heap_base_oop = base;
>>>>> 2374 }
>>>>>
>>>>> In old code heap_base_oop != top() only for heap ptrs, even if
>>>>> base is
>>>>> NULL. In new code, if base is NULL, then heap_base_oop is top(). It
>>>>> would seem that new code is better, because it clearly separates heap
>>>>> vs. native accesses, and it does not seem to break anything
>>>>> downstream.
>>>>> Was that the intent?
>>>>
>>>> Those three lines were actually donated to my by John Rose, so I'm
>>>> hoping he or somebody else more knowledgeable in C2 can provide some
>>>> helpful comments on the correctness and validity of that specific
>>>> change.
>>>>
>>>>
>>>> I also changed the normalize() methods to be private in the
>>>> MemoryAccess
>>>> class, and made the MemoryAccess class a StackObj.
>>>>
>>>> New webrev(s) here:
>>>>
>>>> jdk:
>>>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.02/jdk/webrev/
>>>>
>>>> hotspot:
>>>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.02/hotspot/webrev/
>>>>
>>>>
>>>
>>> src/share/vm/prims/unsafe.cpp
>>>
>>> I think this is a bit over-generalized:
>>>
>>> 254 template <typename T>
>>> 255 void put_mutex(T x) {
>>> 256 GuardUnsafeAccess guard(_thread, _obj);
>>> 257
>>> 258 MutexLockerEx mu(UnsafeJlong_lock,
>>> Mutex::_no_safepoint_check_flag);
>>> 259
>>> 260 T* p = (T*)addr();
>>> 261
>>> 262 Atomic::store(normalize(x), p);
>>> 263 }
>>>
>>> The UnsafeJlong lock is, as the name suggests, only intended for use
>>> with jlongs - we have no need of it for any other type. I don't think
>>> this needs to be a template method.
>>
>> Good point. I guess the method could be made to take the mutex as an
>> argument, or internally decide which mutex to use depending on the type,
>> but given that really only is used for jlong right now I made the
>> function jlong specific (without the template argument).
>>
>>> As noted before the lock could taken after calculating the address -
>>> to shorten the critical section.
>>>
>>> If you take care to ensure no uses of MemoryAccess transitively can
>>> hit a safepoint then you could store the oop directly rather than the
>>> jobject. That would avoid multiple calls to JNIHandles::resolve (in
>>> the GuardUnsafeAccess and addr() function).
>> Since the resolve call is really just dereferencing a pointer and the
>> data should already be in the L1 cache I'm not sure this is worth
>> optimizing a whole lot more, but if we really think it will actually
>> make a difference we can definitely store the raw oop instead. I chose
>> to leave it the way it is for now.
>>
>>>
>>> 405 if (VM_Version::supports_cx8()) {
>>> 406 return MemoryAccess(thread, obj,
>>> offset).get_volatile<jlong>();
>>>
>>> 407 } else {
>>> 408 return MemoryAccess(thread, obj, offset).get_mutex<jlong>();
>>>
>>> You could internalize the supports_cx8 check and the use of locking
>>> inside MemoryAccess.get_volatile<jlong> rather than having
>>> get_volatile and get_mutex. If you prefer to keep it this way then
>>> get_volatile_with_mutex would be a more appropriate name (and it
>>> doesn't need to be a template method as I said before).
>>
>> That's good, I like it! In the interest of drawing a line though I'm
>> going to choose to leave that for a future enhancement.
>>
>> Cheers,
>> Mikael
>>
>>>
>>> Can't comment on the rest of the compiler related stuff too much, but
>>> I didn't see anything obviously odd looking.
>>>
>>> Thanks,
>>> David
>>>
>>>>
>>>> Incremental from webrev.01:
>>>>
>>>> jdk: N/A (no changes)
>>>> hotspot:
>>>> http://cr.openjdk.java.net/~mikael/webrevs/8150921/webrev.02.incr/hotspot/webrev/
>>>>
>>>>
>>>>
>>>>
>>>> Cheers,
>>>> Mikael
>>>>
>>>>>
>>>>> Thanks,
>>>>> -Aleksey
>>>>>
>>>>>
>>>>
>>
More information about the hotspot-runtime-dev
mailing list