RFR: 8186838: Generalize Atomic::inc/dec with templates
Erik Österlund
erik.osterlund at oracle.com
Fri Sep 1 10:49:55 UTC 2017
Hi David,
The shared structure for all operations is the following:
An Atomic::something call creates a SomethingImpl function object that
performs some basic type checking and then forwards the call straight to
a PlatformSomething function object. This PlatformSomething object could
decide to do anything. But to make life easier, it may inherit from a
shared SomethingHelper function object with CRTP that calls back into
the PlatformSomething function object to emit inline assembly.
Hope this explanation helps understanding the intended structure of this
work.
Thanks,
/Erik
On 2017-09-01 12:34, David Holmes wrote:
> Hi Erik,
>
> I just wanted to add that I would expect the cmpxchg, add and inc,
> Atomic API's to all require similar basic structure for manipulating
> types/values etc, yet all three seem to have quite different
> structures that I find very confusing. I'm still at a loss to fathom
> the CRTP and the hoops we seemingly have to jump through just to add
> or subtract 1!!!
>
> Cheers,
> David
>
> On 1/09/2017 7:29 PM, Erik Österlund wrote:
>> Hi David,
>>
>> On 2017-09-01 02:49, David Holmes wrote:
>>> Hi Erik,
>>>
>>> Sorry but this one is really losing me.
>>>
>>> What is the role of Adjustment ??
>>
>> Adjustment represents the increment/decrement value as an
>> IntegralConstant - your template friend for passing around a constant
>> with both a specified type and value in templates. The type of the
>> increment/decrement is the type of the destination when the
>> destination is an integral type, otherwise if it is a pointer type,
>> the increment/decrement type is ptrdiff_t.
>>
>>> How are inc/dec anything but "using constant" ??
>>
>> I was also a bit torn on that name (I assume you are referring to
>> IncUsingConstant/DecUsingConstant). It was hard to find a name that
>> depicted what this platform helper does. I considered calling the
>> helper something with immediate in the name because it is really used
>> to embed the constant as immediate values in inline assembly today.
>> But then again that seemed too specific, as it is not completely
>> obvious platform specializations will use it in that way. One might
>> just want to specialize this to send it into some compiler
>> Atomic::inc intrinsic for example. Do you have any other preferred
>> names? Here are a few possible names for IncUsingConstant:
>>
>> IncUsingScaledConstant
>> IncUsingAdjustedConstant
>> IncUsingPlatformHelper
>>
>> Any favourites?
>>
>>> Why do we special case jshort??
>>
>> To be consistent with the special case of Atomic::add on jshort. Do
>> you want it removed?
>>
>>> This is indecipherable to normal people ;-)
>>>
>>> This()->template inc<I, Adjustment>(dest);
>>>
>>> For something as trivial as adding or subtracting 1 the template
>>> machinations here are just mind boggling!
>>
>> This uses the CRTP (Curiously Recurring Template Pattern) C++ idiom.
>> The idea is to devirtualize a virtual call by passing in the derived
>> type as a template parameter to a base class, and then let the base
>> class static_cast to the derived class to devirtualize the call. I
>> hope this explanation sheds some light on what is going on. The same
>> CRTP idiom was used in the Atomic::add implementation in a similar
>> fashion.
>>
>> I will add some comments describing this in the next round after
>> Coleen replies.
>>
>> Thanks for looking at this.
>>
>> /Erik
>>
>>>
>>> Cheers,
>>> David
>>>
>>> On 31/08/2017 10:45 PM, Erik Österlund wrote:
>>>> Hi everyone,
>>>>
>>>> Bug ID:
>>>> https://bugs.openjdk.java.net/browse/JDK-8186838
>>>>
>>>> Webrev:
>>>> http://cr.openjdk.java.net/~eosterlund/8186838/webrev.00/
>>>>
>>>> The time has come for the next step in generalizing Atomic with
>>>> templates. Today I will focus on Atomic::inc/dec.
>>>>
>>>> I have tried to mimic the new Kim style that seems to have been
>>>> universally accepted. Like Atomic::add and Atomic::cmpxchg, the
>>>> structure looks like this:
>>>>
>>>> Layer 1) Atomic::inc/dec calls an IncImpl()/DecImpl() function
>>>> object that performs some basic type checks.
>>>> Layer 2) IncImpl/DecImpl calls PlatformInc/PlatformDec that can
>>>> define the operation arbitrarily for a given platform. The default
>>>> implementation if not specialized for a platform is to call
>>>> Atomic::add. So only platforms that want to do something different
>>>> than that as an optimization have to provide a specialization.
>>>> Layer 3) Platforms that decide to specialize
>>>> PlatformInc/PlatformDec to be more optimized may inherit from a
>>>> helper class IncUsingConstant/DecUsingConstant. This helper helps
>>>> performing the necessary computation what the increment/decrement
>>>> should be after pointer scaling using CRTP. The
>>>> PlatformInc/PlatformDec operation then only needs to define an
>>>> inc/dec member function, and will then get all the context
>>>> information necessary to generate a more optimized implementation.
>>>> Easy peasy.
>>>>
>>>> It is worth noticing that the generalized Atomic::dec operation
>>>> assumes a two's complement integer machine and potentially sends
>>>> the unary negative of a potentially unsigned type to Atomic::add. I
>>>> have the following comments about this:
>>>> 1) We already assume in other code that two's complement integers
>>>> must be present.
>>>> 2) A machine that does not have two's complement integers may still
>>>> simply provide a specialization that solves the problem in a
>>>> different way.
>>>> 3) The alternative that does not make assumptions about that would
>>>> use the good old IntegerTypes::cast_to_signed metaprogramming
>>>> stuff, and I seem to recall we thought that was a bit too involved
>>>> and complicated.
>>>> This is the reason why I have chosen to use unary minus on the
>>>> potentially unsigned type in the shared helper code that sends the
>>>> decrement as an addend to Atomic::add.
>>>>
>>>> It would also be nice if somebody with access to PPC and s390
>>>> machines could try out the relevant changes there so I do not
>>>> accidentally break those platforms. I have blind-coded the addition
>>>> of the immediate values passed in to the inline assembly in a way
>>>> that I think looks like it should work.
>>>>
>>>> Testing:
>>>> RBT hs-tier3, JPRT --testset hotspot
>>>>
>>>> Thanks,
>>>> /Erik
>>
More information about the hotspot-dev
mailing list