On Thu, 21 May 2026 21:42:49 GMT, Vladimir Ivanov <[email protected]> wrote:

> On bytecode level booleans are represented as ints and HotSpot JVM normalizes 
> boolean values on memory accesses. It unconditionally applies normalization 
> on boolean stores, but trusts on-heap boolean locations to hold normalized 
> values. Normalization is applied on loads for off-heap and mismatched unsafe 
> accesses .  
> 
> There are 2 normalization procedures used: (1) cast int to byte and test it 
> against zero; and (2) truncation to least-significant bit.  Truncation is 
> preferred (due to performance considerations), but JNI mandates testing 
> against zero and, historically, `#1` was used for off-heap unsafe accesses as 
> well. It complicated the implementation (leading to subtle bugs) and 
> introduced divergence in behavior at runtime (depending on execution mode and 
> JIT-compilation peculiarities). 
> 
> The fix uses truncation uniformly across all execution modes. It simplifies 
> implementation and eliminates possible divergence in behavior between 
> execution modes. Also, it drastically simplifies future Unsafe API 
> refactorings.
> 
> There's one scenario left when it's possible to observe non-normalized 
> values: when mismatched access pollutes the Java heap with a bogus boolean 
> value, but then the value is read with a well-typed boolean access.
> 
> Testing: hs-tier1 - hs-tier6
>  
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

test/hotspot/jtreg/compiler/unsafe/UnsafeBooleanTest.java line 122:

> 120:             runTestsOn(prepare(name + " putBoolean", 
> TEST_PUT_BOOLEAN_MH, base, offset), value, true);
> 121:             runTestsOn(prepare(name + " getBoolean", 
> TEST_GET_BOOLEAN_MH, base, offset), value, false);
> 122:         }

Do you mean to prepare all the tests multiple times, once per input value? 
Seems like a lot of duplication.  The preparation is insensitive to the input 
value (the int with the boolean bit).  This means that you are asking for a 
fresh warmed-up nmethod for each test case TIMES each each individual input 
value.

Sketch of integrated perturbation of low bits plus test prep hoisting:


Test[] getTests = prepare(…);
Test[] putTests = prepare(…);
Test[] allTests = prepare(…);
for (int input : INPUTS) { // { 0, 2, 4, -1, … min and max values }
  for (int toggle : TOGGLES) {  // { 0, 1, 0xFF }
    int value = input ^ toggle;
    System.out.printf(…);
    runTestsOn(getTests, …);
    runTestsOn(putTests, …);
    runTestsOn(allTests, …);
  }
}

test/hotspot/jtreg/compiler/unsafe/UnsafeBooleanTest.java line 133:

> 131:     static void runTest(Test t, int value, boolean normalizedOnStore) {
> 132:         int expected = ((byte) value) & 1;
> 133:         for (int iter = 0; iter < 20_000; iter++) {

This warmup is performed on each input value.  If you hoist the test 
preparation, consider doing warmup loops elsewhere.  But of course after the 
first input value triggers warmup, any further attempts to warm up will just go 
faster, if you reuse the test lambda.

test/hotspot/jtreg/compiler/unsafe/UnsafeBooleanTest.java line 145:

> 143:                 }
> 144:             } catch (Throwable e) {
> 145:                 if (reportError(t, value)) {

The printf here looks like a bad cut-and-paste.  Handing `e.getMessage()` to 
the `"0x%02x"` format is going to cause a secondary error.  Suggest `"(throw 
%s)"` instead. Maybe inject a temporary defect to test this path.

test/hotspot/jtreg/compiler/unsafe/UnsafeBooleanTest.java line 161:

> 159:                             !isBooleanSetter ? "testGetBoolean" :
> 160:                                                "testAllBoolean";
> 161:         MethodType mt = MethodType.methodType(int.class, Unsafe.class, 
> Object.class, long.class, int.class);

Good use of the ClassFile API!  This reads better than a JASM file.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293567241
PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293568350
PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293573027
PR Review Comment: https://git.openjdk.org/jdk/pull/31249#discussion_r3293570181

Reply via email to