RFR: 8330465: Stable Values and Collections (Internal) [v10]
ExE Boss
duke at openjdk.org
Thu May 16 10:39:09 UTC 2024
On Thu, 16 May 2024 09:01:22 GMT, Per Minborg <pminborg at openjdk.org> wrote:
>> # Stable Values & Collections (Internal)
>>
>> ## Summary
>> This PR proposes to introduce an internal _Stable Values & Collections_ API, which provides immutable value holders where elements are initialized _at most once_. Stable Values & Collections offer the performance and safety benefits of final fields while offering greater flexibility as to the timing of initialization.
>>
>> ## Goals
>> * Provide an easy and intuitive API to describe value holders that can change at most once.
>> * Decouple declaration from initialization without significant footprint or performance penalties.
>> * Reduce the amount of static initializer and/or field initialization code.
>> * Uphold integrity and consistency, even in a multi-threaded environment.
>>
>> For more details, see the draft JEP: https://openjdk.org/jeps/8312611
>>
>> ## Performance
>> Performance compared to instance variables using two `AtomicReference` and two protected by double-checked locking under concurrent access by all threads:
>>
>>
>> Benchmark Mode Cnt Score Error Units
>> StableBenchmark.atomic thrpt 10 259.478 ? 36.809 ops/us
>> StableBenchmark.dcl thrpt 10 225.710 ? 26.638 ops/us
>> StableBenchmark.stable thrpt 10 4382.478 ? 1151.472 ops/us <- StableValue significantly faster
>>
>>
>> Performance compared to static variables protected by `AtomicReference`, class-holder idiom holder, and double-checked locking (all threads):
>>
>>
>> Benchmark Mode Cnt Score Error Units
>> StableStaticBenchmark.atomic thrpt 10 6487.835 ? 385.639 ops/us
>> StableStaticBenchmark.dcl thrpt 10 6605.239 ? 210.610 ops/us
>> StableStaticBenchmark.stable thrpt 10 14338.239 ? 1426.874 ops/us
>> StableStaticBenchmark.staticCHI thrpt 10 13780.341 ? 1839.651 ops/us
>>
>>
>> Performance for stable lists (thread safe) in both instance and static contexts whereby we access a single value compared to `ArrayList` instances (which are not thread-safe) (all threads):
>>
>>
>> Benchmark Mode Cnt Score Error Units
>> StableListElementBenchmark.instanceArrayList thrpt 10 5812.992 ? 1169.730 ops/us
>> StableListElementBenchmark.instanceList thrpt 10 4818.643 ? 704.893 ops/us
>> StableListElementBenchmark...
>
> Per Minborg has updated the pull request incrementally with one additional commit since the last revision:
>
> Use byte for storing state and compute flags
src/java.base/share/classes/jdk/internal/lang/stable/StableAccess.java line 63:
> 61: Function<? super T, ? extends R> original) {
> 62: return new MemoizedFunction<>(stableMap, original);
> 63: }
Maybe also rename these?
Suggestion:
public static <T> Supplier<T> memoizedSupplier(StableValue<T> stable,
Supplier<? extends T> original) {
return new MemoizedSupplier<>(stable, original);
}
public static <R> IntFunction<R> memoizedIntFunction(List<StableValue<R>> stableList,
IntFunction<? extends R> original) {
return new MemoizedIntFunction<>(stableList, original);
}
public static <T, R> Function<T, R> memoizedFunction(Map<T, StableValue<R>> stableMap,
Function<? super T, ? extends R> original) {
return new MemoizedFunction<>(stableMap, original);
}
src/jdk.unsupported/share/classes/sun/misc/Unsafe.java line 729:
> 727: }
> 728: }
> 729: }
Given that the [`Class::forName(String, boolean, ClassLoader)`] method doesn’t care about whether the requested class is actually exported to the caller, it’s possible to do the following:
Suggestion:
final class Holder {
static final Class<?> TRUSTED_FIELD_TYPE;
static {
PrivilegedAction<ClassLoader> getPlatformClassLoader = ClassLoader::getPlatformClassLoader;
@SuppressWarnings("removal")
ClassLoader platformClassLoader = AccessController.doPrivileged(getPlatformClassLoader);
try {
TRUSTED_FIELD_TYPE = Class.forName("jdk.internal.lang.stable.TrustedFieldType",
false, platformClassLoader);
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
}
}
Class<?> declaringClass = f.getDeclaringClass();
if (declaringClass.isHidden()) {
throw new UnsupportedOperationException("can't get base address on a hidden class: " + f);
}
if (declaringClass.isRecord()) {
throw new UnsupportedOperationException("can't get base address on a record class: " + f);
}
Class<?> fieldType = f.getType();
if (Holder.TRUSTED_FIELD_TYPE.isAssignableFrom(fieldType)) {
throw new UnsupportedOperationException("can't get field offset for a field of type " + fieldType.getName() + ": " + f);
}
[`Class::forName(String, boolean, ClassLoader)`]: https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Class.html#forName(java.lang.String,boolean,java.lang.ClassLoader)
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/18794#discussion_r1603032451
PR Review Comment: https://git.openjdk.org/jdk/pull/18794#discussion_r1603089512
More information about the hotspot-compiler-dev
mailing list