On Thu, 16 May 2024 09:01:22 GMT, Per Minborg <pminb...@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

Reply via email to