[aarch64] assert(is_power_of_2(x)) failed: x must be a power of 2: 0xffffffff80000000
Schmidt, Lutz
lutz.schmidt at sap.com
Tue Feb 25 14:52:07 UTC 2020
On 25.02.20, 10:16, "Andrew Haley" <aph at redhat.com> wrote:
On 2/24/20 4:27 PM, Schmidt, Lutz wrote:
>
> > A possible fix would include:
> > - make is_power_of_2() and exact_log_2() sign-aware.
> > - call is_power_of_2() and exact_log_2() with arguments of proper
> > type (juint in this case).
>
> Or fix exact_log2(jint) by specializing it appropriately.
>
> Yes, by treating the jint argument as unsigned.
OK, I'll look at that. However, studying the code, we have at least
one more problem, and it's a dangerous one.
template <typename T>
bool is_power_of_2_t(T x) {
return (x != T(0)) && ((x & (x - 1)) == T(0));
}
// long version of is_power_of_2
inline bool is_power_of_2_long(jlong x) {
return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits));
}
These overflow when x is the largest negative integer. This is
Undefined Behaviour, so we have to fix it somehow. We'd do much better
converting to an unsigned type and then performing the calculation on
that. Maybe we should provide just one definition of this function,
casting its argument to uint64_t.
Isn't it such that unsigned arithmetic on today's processors differs from signed arithmetic only by interpretation of the MSB (unsigned: most significant bit, signed: sign bit), and possibly by indication of overflow?
No matter how (signed or unsigned) you calculate (0x8000_0000 - 1), you will always get 0x7fff_ffff as result. That behavior makes is_power_of_2((jint)0x8000_0000)) return "true".
Viewed from close to the hardware, there is no UB. It is introduced by a higher level in the stack. Up there, you don't want to know too much about H/W characteristics. On the other hand, don't the upper levels rely on integers being stored in 2's complement format? With all the arithmetic implications, where the signed/unsigned equivalence is one of?
All the confusion/unexpected behavior originates from the mixed interpretation (signed/unsigned) of operands and, as a consequence, unexpected/unwanted sign extensions.
UB problems keep occurring. It'd be good to test HotSpot changes with
-fsanitize=undefined, but we still have so much UB in HotSpot that
it's impractical to do so because there's so much noise.
That's a compelling dream!
--
Andrew Haley (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
More information about the hotspot-compiler-dev
mailing list