On Wed, 15 May 2024 18:45:16 GMT, ExE Boss <d...@openjdk.org> wrote: >> src/java.base/share/classes/jdk/internal/lang/stable/StableValueImpl.java >> line 104: >> >>> 102: // Optimistically try plain semantics first >>> 103: final V v = value; >>> 104: if (v != null) { >> >> If `value == null && state == NULL`, can the path still be constant folded? >> I doubt it because `value` in this case may not be promoted to constant. > > Maybe the `state == NULL` check should be moved before `v != null`, as the > **JIT** doesn’t constant‑fold `null` [`@Stable`] values: > https://github.com/openjdk/jdk/blob/8a4315f833f3700075d65fae6bc566011c837c07/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java#L41-L44 > > https://github.com/openjdk/jdk/blob/8a4315f833f3700075d65fae6bc566011c837c07/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java#L64-L71 > > [`@Stable`]: > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java
It seems reasonable to assume `null` values are not constant-folded. For straight-out-of-the-box usage, there is no apparent significant difference as indicated by a new benchmark I just added: Benchmark Mode Cnt Score Error Units StableStaticBenchmark.atomic thrpt 10 5729.683 ? 502.023 ops/us StableStaticBenchmark.dcl thrpt 10 6069.222 ? 951.784 ops/us StableStaticBenchmark.dclHolder thrpt 10 5502.102 ? 1630.627 ops/us StableStaticBenchmark.stable thrpt 10 12737.158 ? 1746.456 ops/us <- Non-null benchmark StableStaticBenchmark.stableHolder thrpt 10 12053.978 ? 1421.527 ops/us StableStaticBenchmark.stableList thrpt 10 12443.870 ? 2084.607 ops/us StableStaticBenchmark.stableNull thrpt 10 13164.232 ? 591.284 ops/us <- Added null benchmark StableStaticBenchmark.stableRecordHolder thrpt 10 13638.893 ? 1250.895 ops/us StableStaticBenchmark.staticCHI thrpt 10 13639.220 ? 1190.922 ops/us If the `null` value participates in a much larger constant-folding tree, there might be a significant difference. I was afraid moving the order would have detrimental effects on instance performance but that does not seem to be the case: Checking value first: Benchmark Mode Cnt Score Error Units StableBenchmark.atomic thrpt 10 246.460 ? 75.417 ops/us StableBenchmark.dcl thrpt 10 243.481 ? 35.021 ops/us StableBenchmark.stable thrpt 10 4977.693 ? 675.926 ops/us <- Non-null StableBenchmark.stableHoldingList thrpt 10 3614.460 ? 275.140 ops/us StableBenchmark.stableList thrpt 10 3328.155 ? 898.202 ops/us StableBenchmark.stableListStored thrpt 10 3842.174 ? 535.902 ops/us StableBenchmark.stableNull thrpt 10 6217.737 ? 840.376 ops/us <- null StableBenchmark.supplier thrpt 10 9369.934 ? 1449.182 ops/us Checking null first: Benchmark Mode Cnt Score Error Units StableBenchmark.atomic thrpt 10 275.952 ? 39.480 ops/us StableBenchmark.dcl thrpt 10 252.697 ? 18.645 ops/us StableBenchmark.stable thrpt 10 5211.552 ? 315.307 ops/us <- Non-null StableBenchmark.stableHoldingList thrpt 10 3764.202 ? 224.325 ops/us StableBenchmark.stableList thrpt 10 3689.870 ? 419.858 ops/us StableBenchmark.stableListStored thrpt 10 3676.182 ? 938.485 ops/us StableBenchmark.stableNull thrpt 10 6046.935 ? 1512.391 ops/us <- null StableBenchmark.supplier thrpt 10 9202.202 ? 1479.950 ops/us So, swapping order seems to be the right move. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/18794#discussion_r1602719002