JDK-8178495 : Bug in the align_size_up_ macro
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 9,10
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-04-11
  • Updated: 2017-08-25
  • Resolved: 2017-07-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10
10 b21Fixed
Related Reports
Relates :  
Description
The following:
 align_size_up_((uintptr_t)0x512345678ULL, (int8_t) 16);
 align_size_up_((uintptr_t)0x512345678ULL, (int16_t) 16);
 align_size_up_((uintptr_t)0x512345678ULL, (int32_t) 16);
 align_size_up_((uintptr_t)0x512345678ULL, (int64_t) 16);

 align_size_up_((uintptr_t)0x512345678ULL, (uint8_t) 16);
 align_size_up_((uintptr_t)0x512345678ULL, (uint16_t)16);
 align_size_up_((uintptr_t)0x512345678ULL, (uint32_t)16);
 align_size_up_((uintptr_t)0x512345678ULL, (uint64_t)16);

Gives this output:
 0x512345680
 0x512345680
 0x512345680
 0x512345680

 0x512345680
 0x512345680
  0x12345680
 0x512345680

So, align_size_up_((uintptr_t)0x512345678ULL, (uint32_t)16) returns an unexpected, truncated value.

This happens because in this macro:
#define align_size_up_(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1))

~((alignment) - 1) returns 0x00000000FFFFFFF0 instead of 0xFFFFFFFFFFFFFFF0

This isn't a problem for the 64-bit types, and maybe more non-obvious is that it doesn't happen for types 8-bit and 16-bit types.

For the 8-bit and 16-bit types, the (alignment - 1) is promoted to a signed int, when it later is used in the & expression it is signed extended into a signed 64-bit value.

When the type is an unsigned 32-bit integer, it isn't promoted to a signed int, and therefore it is not singed extended to 64 bits, but instead zero extended to 64 bits.

This bug is currently not affecting the code base, since the inline align functions promote all integers to intptr_t, before passing them down to the align macros. However, when/if JDK-8178489 is pushed the macro is actually used with 32 bits unsigned ints.