RFR (M): 8184334: Generalizing Atomic with templates

Andrew Haley aph at redhat.com
Tue Jul 18 09:57:56 UTC 2017


On 18/07/17 10:38, Erik Österlund wrote:

>> ------------------------------------------------------------------------
>> 3.10, Lvalues and rvalues
>>
>> If a program attempts to access the stored value of an object through
>> a glvalue of other than one of the following types the behavior is
>> undefined:
>>
>> — the dynamic type of the object,
>>
>> — a cv-qualified version of the dynamic type of the object,
>>
>> — a type similar (as defined in 4.4) to the dynamic type of the object,
>>
>> — a type that is the signed or unsigned type corresponding to the
>>    dynamic type of the object,
>>
>> — a type that is the signed or unsigned type corresponding to a
>>    cv-qualified version of the dynamic type of the object,
>>
>> — an aggregate or union type that includes one of the aforementioned
>>    types among its elements or non- static data members (including,
>>    recursively, an element or non-static data member of a subaggregate
>>    or contained union),
>>
>> — a type that is a (possibly cv-qualified) base class type of the
>>    dynamic type of the object,
>>
>> — a char or unsigned char type.
>> ------------------------------------------------------------------------
>>
>> You only have permission to convert pointers to intptr_t and back: you
>> do not have permission to access the stored value of a pointer an an
>> intptr_t.
> 
> I would say the scenario you describe goes under "the dynamic type of 
> the object" or "a type that is the signed or unsigned type corresponding 
> to the dynamic type of the object",

OK.

> in the quoted section 3.10 of the standard, depending on specific
> use case.  The problem that type aliasing is aimed at is if you
> store an A* and then load it as a B*, then the dynamic type is A*,
> yet it is loaded as B*, where B is not compatible with A.

Precisely.  That is what is happening in this case.  A is, say, void*
and B is intptr_t.  void* is not compatible with intptr_t.

> This is invariant of whether the value of the store is indirectly
> performed through intptr_t or loaded indirectly through intptr_t, as
> the dynamic type of the stored value is still A*.

Exactly so.  The stored object is an A*.  We're accessing it as an
intptr_t.  A* and intptr_t are not compatible types.  This is true
even if the intptr_t was the result of casting from an A*.  The
compiler doesn't necessarily know that the intptr_t was originally an
A*: they might even be in separate compilation units.  The compiler is
entitled to assume that the object in memory of type A* does not alias
with any value of type intptr_t.

> If you now perform a store of A* through Atomic that casts the pointer 
> to intptr_t, and stores it, then the dynamic type is still A*.

This isn't how it works.  (BTW, in case it helps understand where I'm
coming from, although I am not the greatest expert in this area, I am
familiar with GCC's alias analysis because I am a GCC author.)

> In summary, my point is that as long as the performed stores and loads 
> in Atomic preserves the bit representation of whatever pointer was 
> passed in, the dynamic type of that pointer is unchanged, invariantly of 
> casting it to/from intptr_t, and hence the aliasing is allowed.

That is incorrect.  Rules about aliasing are nothing to do with the
bit representation.

Let me reiterate: you may cast from any pointer type to intptr_t.  You
may not access a pointer in memory as though it were an intptr_t.

-- 
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671


More information about the hotspot-runtime-dev mailing list