RFR (M): 8184334: Generalizing Atomic with templates
erik.osterlund at oracle.com
Mon Jul 17 15:00:54 UTC 2017
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
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.
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.
> -> 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-dev