On Tue, 30 Jun 2026 15:58:10 GMT, Jorn Vernee <[email protected]> wrote:

> Unsafe was changed recently through: 
> https://github.com/openjdk/jdk/pull/31249 to no longer treat any non-zero 
> byte read as a `boolean` through Unsafe as `true`, but only treat the 
> 'canonical' representation, where only the least significant bit in the byte 
> is set, as `true`.
> 
> This change inadvertently leaked out through the memory access var handles. A 
> user can write a `byte` into a memory segment (on or off-heap), and then read 
> it back as a `boolean`, making this behavior change observable. Since the 
> fallback linker depends on the previous behavior in the implementation, the 
> tier5 test from the title was failing. But, there is really a gap in testing 
> here, and we can observe the difference in behavior when just using the 
> memory access parts of the API as well.
> 
> It is important that the normalization of boolean values is the same in all 
> these scenarios:
> - Normalizing a value returned from native code by a downcall
> - Normalizing an argument passed by native code to an upcall stub
> - Normalizing a value read from a memory segment using a var handle or the 
> MemorySegment::get accessor
> 
> To that end, this patch tweaks the memory segment var handles for boolean 
> access to restore the old normalization behavior. I've also added the missing 
> testing for this case.
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

make/common/modules/GensrcStreamPreProcessing.gmk line 119:

> 117: # Return integer type with same size as the type
> 118: Conv_memtype = \
> 119:   $(if $(filter float, $1), int, $(if $(filter double, $1), long, $(if 
> $(filter boolean, $1), byte, $1)))

I've tweaked this so that `byte` is now the 'raw type' for `boolean`. This is 
only used for the memory segment var handles, since the other handle types 
don't support boolean.

src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template
 line 146:

> 144:     static $rawType$ convEndian(boolean big, $type$ v) {
> 145:         return (byte) (v ? 1 : 0);
> 146:     }

This is used by the setters. Technically we could keep using setBoolean* for 
this, but this would complicate the code shape significantly, since then we 
have essentially a different type for get/set.

src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template
 line 427:

> 425:         SegmentVarHandle handle = (SegmentVarHandle)ob;
> 426:         AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, 
> false);
> 427: #if[!byte]

I went through these to check if something needed to be changed, but these 
accessors are not supported for `byte` in the first place (everything in the 
`#if[AtomicAdd]` and `#if[BitWise]` blocks), i.e. `#if[byte]` is never true 
here, so I've gone ahead and cleaned up these redundant ifs.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/31727#discussion_r3500133677
PR Review Comment: https://git.openjdk.org/jdk/pull/31727#discussion_r3500164776
PR Review Comment: https://git.openjdk.org/jdk/pull/31727#discussion_r3500150022

Reply via email to