RFR (M): 8184334: Generalizing Atomic with templates

Erik Österlund erik.osterlund at oracle.com
Mon Jul 17 15:00:54 UTC 2017


Hi Andrew,

I am glad that it seems to work. Thank you for reviewing.

As for the over engineered casting mechanism, the IntegerTypes class in 
metaprogramming/integerTypes.hpp has lots of commentary about what the 
different casting mechanisms do. Hope that helps.

To explain the reasoning, I will go through an example. Let's take 
atomic::cmpxchg.
Each platform has a specialization for different supported cmpxchg 
implementations in terms of int32_t and int64_t.
Since the Atomic::cmpxchg parameter now takes a generic primitive type 
T, we need to cast T without changing its binary representation, and 
without losing type safety, into *exactly* those intX_t types. If even 
slightly different in any way, the specializations will not match.

So for example, we need to be able to perform the following conversions:
1) Floating point to integer without changing bit representaiton. It 
seems like the only way of doing this without violating the C++03 
standard is to use memcpy. (no, the union trick in e.g. jfloat_cast is 
not standards compliant)
2) Pointer to integer
3) Anything with not matching CV qualifiers to matching CV qualifiers
4) Integer of wrong signedness to matching signedness
5) Integer with same signedness but declared differently, e.g. signed 
char is not the same as char, and will miss that specialization. For 
example on Solaris, int8_t is char, but jbyte is signed char, and those 
types are different. Sometimes even intptr_t is neither int32_t or 
int64_t as I have seen on clang.

Due to these issues, the IntegerTypes class was created to solve the 
casting problems in one single place while remaining type safe. So it 
solves the problem of canonicalizing primitive types and casting them 
into exactly the same canonical integer type that can be safely passed 
into code that specializes on that canonical integer type, without 
changing the bit pattern or slipping in type safety.

By solving this general casting problem problem in IntegerTypes, it 
turned the casting issues in Atomic into trivial non-problems, and 
hopefully can be used elsewhere in hotspot. For example the jfloat_cast 
with friend functions are not standards compliant and can now use 
IntegerTypes instead, for that mindblowingly seemless casting experience.

I hope this explanation makes sense.

Thanks,
/Erik

On 2017-07-17 16:21, Andrew Haley wrote:
> On 14/07/17 17:28, Erik Österlund wrote:
>> As for oracle-external ports, I would appreciate if port maintainers
>> could check if it seems to make sense. I have done my best to try to
>> make the appropriate changes where needed.
> It seems to, but it looks over-engineered.  We're relying on the C++
> compiler to get rid of all of the casts and calls, but it's always
> better not to write code we don't want to execute.  So, could you add
> a little commentary explaining what all this SignedType stuff does?  I
> guess it must be necessary or you wouldn't have written it, but I
> don't know why.
>
> Monitor::TryFast
> ->  Atomic::cmpxchg_ptr
>    ->  Atomic::cmpxchg<long, long, long>
>      ->  Atomic::specialized_cmpxchg<long>
>        ->  generic_cmpxchg<long>
>          ->  __sync_val_compare_and_swap
>
> I wonder if it's intended to avoid undefine behaviour by always
> guaranteeing that we store a signed type, but on the other hand
> cmpxchg_ptr doesn't much seem to worry about handing a void** as an
> intptr_t*, so it can't be that, and besides we compile with
> -fno-strict-aliasing (or it equivalent on other machines).
>



More information about the hotspot-runtime-dev mailing list