RFR: 8351565: Implement JEP 502: Stable Values (Preview) [v53]

Viktor Klang vklang at openjdk.org
Thu Apr 10 13:02:59 UTC 2025


On Thu, 10 Apr 2025 10:26:36 GMT, Per Minborg <pminborg at openjdk.org> wrote:

>> Implement JEP 502.
>> 
>> The PR passes tier1-tier3 tests.
>
> Per Minborg has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Improve docs as per comments

src/java.base/share/classes/java/lang/StableValue.java line 93:

> 91:  * <p>
> 92:  * In order to guarantee that, even under races, only one instance of {@code Logger} is
> 93:  * evee created, the {@linkplain #orElseSet(Supplier) orElseSet()} method can be used

Typo:

Suggestion:

 * ever created, the {@linkplain #orElseSet(Supplier) orElseSet()} method can be used

src/java.base/share/classes/java/lang/StableValue.java line 94:

> 92:  * In order to guarantee that, even under races, only one instance of {@code Logger} is
> 93:  * evee created, the {@linkplain #orElseSet(Supplier) orElseSet()} method can be used
> 94:  * instead, where the content is atomically and lazily computed via a

Suggestion:

 * instead, where the content is lazily computed, and atomically set, via a

src/java.base/share/classes/java/lang/StableValue.java line 120:

> 118:  * evaluates and sets the content; the content is then returned to the client. In other
> 119:  * words, {@code orElseSet()} guarantees that a stable value's content is <em>set</em>
> 120:  * before it is used.

Suggestion:

 * before it is returned.

src/java.base/share/classes/java/lang/StableValue.java line 131:

> 129:  * Stable values provide the foundation for higher-level functional abstractions. A
> 130:  * <em>stable supplier</em> is a supplier that computes a value and then caches it into
> 131:  * a backing stable value storage for later use. A stable supplier is created via the

Suggestion:

 * a backing stable value storage for subsequent use. A stable supplier is created via the

src/java.base/share/classes/java/lang/StableValue.java line 133:

> 131:  * a backing stable value storage for later use. A stable supplier is created via the
> 132:  * {@linkplain StableValue#supplier(Supplier) StableValue.supplier()} factory, by
> 133:  * providing an original {@linkplain Supplier} which is invoked when the stable supplier

Suggestion:

 * providing an underlying {@linkplain Supplier} which is invoked when the stable supplier

src/java.base/share/classes/java/lang/StableValue.java line 169:

> 167:  *     private static final int SIZE = 6;
> 168:  *     private static final IntFunction<Integer> ORIGINAL_POWER_OF_TWO =
> 169:  *             v -> 1 << v;

Suggestion:

 *         v -> 1 << v;

src/java.base/share/classes/java/lang/StableValue.java line 173:

> 171:  *     private static final IntFunction<Integer> POWER_OF_TWO =
> 172:  *             // @link substring="intFunction" target="#intFunction(int,IntFunction)" :
> 173:  *             StableValue.intFunction(SIZE, ORIGINAL_POWER_OF_TWO);

Suggestion:

 *         // @link substring="intFunction" target="#intFunction(int,IntFunction)" :
 *         StableValue.intFunction(SIZE, ORIGINAL_POWER_OF_TWO);

src/java.base/share/classes/java/lang/StableValue.java line 180:

> 178:  * }
> 179:  *
> 180:  * int pwr4 = PowerOf2Util.powerOfTwo(4);   // May eventually constant fold to 16 at runtime

Suggestion:

 * int result = PowerOf2Util.powerOfTwo(4);   // May eventually constant fold to 16 at runtime

src/java.base/share/classes/java/lang/StableValue.java line 208:

> 206:  *     private static final Function<Integer, Integer> LOG2 =
> 207:  *             // @link substring="function" target="#function(Set,Function)" :
> 208:  *             StableValue.function(KEYS, ORIGINAL_LOG2);

Suggestion:

 *     private static final Set<Integer> KEYS =
 *         Set.of(1, 2, 4, 8, 16, 32);
 *     private static final UnaryOperator<Integer> ORIGINAL_LOG2 =
 *         i -> 31 - Integer.numberOfLeadingZeros(i);
 *
 *     private static final Function<Integer, Integer> LOG2 =
 *         // @link substring="function" target="#function(Set,Function)" :
 *         StableValue.function(KEYS, ORIGINAL_LOG2);

src/java.base/share/classes/java/lang/StableValue.java line 216:

> 214:  * }
> 215:  *
> 216:  * int log16 = Log2Util.log2(16);   // May eventually constant fold to 4 at runtime

Suggestion:

 * int result = Log2Util.log2(16);   // May eventually constant fold to 4 at runtime

src/java.base/share/classes/java/lang/StableValue.java line 240:

> 238:  *     private static final List<Integer> POWER_OF_TWO =
> 239:  *             // @link substring="list" target="#list(int,IntFunction)" :
> 240:  *             StableValue.list(SIZE, ORIGINAL_POWER_OF_TWO);

Suggestion:

 *             v -> 1 << v;
 *
 *     private static final List<Integer> POWER_OF_TWO =
 *         // @link substring="list" target="#list(int,IntFunction)" :
 *         StableValue.list(SIZE, ORIGINAL_POWER_OF_TWO);

src/java.base/share/classes/java/lang/StableValue.java line 247:

> 245:  * }
> 246:  *
> 247:  * int pwr4 = PowerOf2Util.powerOfTwo(4);   // May eventually constant fold to 16 at runtime

Suggestion:

 * int result = PowerOf2Util.powerOfTwo(4);   // May eventually constant fold to 16 at runtime

src/java.base/share/classes/java/lang/StableValue.java line 267:

> 265:  *     private static final Map<Integer, INTEGER> LOG2 =
> 266:  *             // @link substring="map" target="#map(Set,Function)" :
> 267:  *             StableValue.map(CACHED_KEYS, LOG2_ORIGINAL);

Suggestion:

 *         Set.of(1, 2, 4, 8, 16, 32);
 *     private static final UnaryOperator<Integer> LOG2_ORIGINAL =
 *         i -> 31 - Integer.numberOfLeadingZeros(i);
 *
 *     private static final Map<Integer, INTEGER> LOG2 =
 *         // @link substring="map" target="#map(Set,Function)" :
 *         StableValue.map(CACHED_KEYS, LOG2_ORIGINAL);

src/java.base/share/classes/java/lang/StableValue.java line 275:

> 273:  * }
> 274:  *
> 275:  * int log16 = Log2Util.log2(16);   // May eventually constant fold to 4 at runtime

Suggestion:

 * int result = Log2Util.log2(16);   // May eventually constant fold to 4 at runtime

src/java.base/share/classes/java/lang/StableValue.java line 318:

> 316:  * <p>
> 317:  * Here is another example where a more complex dependency graph is created in which
> 318:  * integers in the Fibonacci delta series are lazily computed:

I'd probably reword this to: "Another example, which has a more complex dependency graph, is computing the Fibonacci sequence:"

src/java.base/share/classes/java/lang/StableValue.java line 327:

> 325:  *
> 326:  *     private static final IntFunction<Integer> FIB =
> 327:  *             StableValue.intFunction(MAX_SIZE_INT, Fibonacci::fib);

Suggestion:

 *         StableValue.intFunction(MAX_SIZE_INT, Fibonacci::fib);

src/java.base/share/classes/java/lang/StableValue.java line 357:

> 355:  *
> 356:  * If there are circular dependencies in a dependency graph, a stable value will
> 357:  * eventually throw an {@linkplain IllegalStateException} upon referencing elements in

Suggestion:

 * eventually throw an {@linkplain IllegalStateException} upon detecting

src/java.base/share/classes/java/lang/StableValue.java line 491:

> 489:      *
> 490:      * {@snippet lang=java:
> 491:      * Value witness = stable.orElseSet(Value::new);

Suggestion:

     * Value v = stable.orElseSet(Value::new);

src/java.base/share/classes/java/lang/StableValue.java line 565:

> 563:      * the returned supplier's {@linkplain Supplier#get() get()} method.
> 564:      * <p>
> 565:      * The provided {@code original} supplier is guaranteed to be successfully invoked

Personally I prefer "underlying" over "original".

src/java.base/share/classes/java/lang/StableValue.java line 582:

> 580:     static <T> Supplier<T> supplier(Supplier<? extends T> original) {
> 581:         Objects.requireNonNull(original);
> 582:         return StableSupplier.of(original);

I guess if `original` is a StableSupplier then we could just return that?

src/java.base/share/classes/java/lang/StableValue.java line 614:

> 612:      * @throws IllegalArgumentException if the provided {@code size} is negative.
> 613:      */
> 614:     static <R> IntFunction<R> intFunction(int size,

Does an intFunction of size 0 make sense?

test/jdk/java/lang/StableValue/StableFunctionTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for StableFunctionTest methods

Suggestion:

 * @summary Basic tests for StableFunction methods

test/jdk/java/lang/StableValue/StableIntFunctionTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for StableIntFunctionTest methods

Suggestion:

 * @summary Basic tests for StableIntFunction methods

test/jdk/java/lang/StableValue/StableListTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for LazyList methods

Suggestion:

 * @summary Basic tests for StableList methods

test/jdk/java/lang/StableValue/StableMapTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for LazyMap methods

Suggestion:

 * @summary Basic tests for StableMap methods

test/jdk/java/lang/StableValue/StableSupplierTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for StableSupplierTest methods

Suggestion:

 * @summary Basic tests for StableSupplier methods

test/jdk/java/lang/StableValue/StableValueFactoriesTest.java line 25:

> 23: 
> 24: /* @test
> 25:  * @summary Basic tests for StableValueFactoriesTest implementations

Suggestion:

 * @summary Basic tests for StableValue factory implementations

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

PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037168882
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037169961
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037172243
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037174262
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037174898
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037177853
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037178275
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037179545
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037180933
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037181796
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037193456
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037194051
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037195527
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037195700
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037202304
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037229765
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037234988
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037250964
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037256596
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037258059
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037261762
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037279107
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037278760
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037278239
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037279632
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037280278
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r2037282580


More information about the core-libs-dev mailing list