/*
 * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020, 2025, Red Hat Inc.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang;

import java.util.NoSuchElementException;
import java.util.Objects;
import java.lang.ref.Reference;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructureViolationException;
import java.util.function.Supplier;
import jdk.internal.access.JavaUtilConcurrentTLRAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Hidden;
import jdk.internal.vm.ScopedValueContainer;

/**
 * A value that may be safely and efficiently shared to methods without using method
 * parameters.
 *
 * <p> In the Java programming language, data is usually passed to a method by means of a
 * method parameter. The data may need to be passed through a sequence of many methods to
 * get to the method that makes use of the data. Every method in the sequence of calls
 * needs to declare the parameter and every method has access to the data.
 * {@code ScopedValue} provides a means to pass data to a faraway method (typically a
 * <em>callback</em>) without using method parameters. In effect, a {@code ScopedValue}
 * is an <em>implicit method parameter</em>. It is "as if" every method in a sequence of
 * calls has an additional parameter. None of the methods declare the parameter and only
 * the methods that have access to the {@code ScopedValue} object can access its value
 * (the data). {@code ScopedValue} makes it possible to securely pass data from a
 * <em>caller</em> to a faraway <em>callee</em> through a sequence of intermediate methods
 * that do not declare a parameter for the data and have no access to the data.
 *
 * <p> The {@code ScopedValue} API works by executing a method with a {@code ScopedValue}
 * object <em>bound</em> to some value for the bounded period of execution of a method.
 * The method may invoke another method, which in turn may invoke another. The unfolding
 * execution of the methods define a <em>dynamic scope</em>. Code in these methods with
 * access to the {@code ScopedValue} object may read its value. The {@code ScopedValue}
 * object reverts to being <em>unbound</em> when the original method completes normally or
 * with an exception. The {@code ScopedValue} API supports executing a {@link Runnable},
 * or {@link CallableOp} with a {@code ScopedValue} bound to a value.
 *
 * <p> Consider the following example with a scoped value "{@code NAME}" bound to the value
 * "{@code duke}" for the execution of a {@code Runnable}'s {@code run} method.
 * The {@code run} method, in turn, invokes a method {@code doSomething}.
 *
 *
 * {@snippet lang=java :
 *     // @link substring="newInstance" target="#newInstance" :
 *     private static final ScopedValue<String> NAME = ScopedValue.newInstance();
 *
 *     // @link substring="run" target="Carrier#run(Runnable)" :
 *     ScopedValue.where(NAME, "duke").run(() -> doSomething());
 * }
 * Code executed directly or indirectly by {@code doSomething}, with access to the field
 * {@code NAME}, can invoke {@code NAME.get()} to read the value "{@code duke}". {@code
 * NAME} is bound while executing the {@code run} method. It reverts to being unbound when
 * the {@code run} method completes.
 *
 * <p> The example using {@code run} invokes a method that does not return a result.
 * The {@link Carrier#call(CallableOp) call} method can be used
 * to invoke a method that returns a result.
 * {@code ScopedValue} defines the {@link #where(ScopedValue, Object)} method
 * for cases where multiple mappings (of {@code ScopedValue} to value) are accumulated
 * in advance of calling a method with all {@code ScopedValue}s bound to their value.
 *
 * <h2>Bindings are per-thread</h2>
 *
 * A {@code ScopedValue} binding to a value is per-thread. Invoking {@code run}
 * executes a method with a {@code ScopedValue} bound to a value for the current thread.
 * The {@link #get() get} method returns the value bound for the current thread.
 *
 * <p> In the example, if code executed by one thread invokes this:
 * {@snippet lang=java :
 *     ScopedValue.where(NAME, "duke1").run(() -> doSomething());
 * }
 * and code executed by another thread invokes:
 * {@snippet lang=java :
 *     ScopedValue.where(NAME, "duke2").run(() -> doSomething());
 * }
 * then code in {@code doSomething} (or any method that it calls) invoking {@code NAME.get()}
 * will read the value "{@code duke1}" or "{@code duke2}", depending on which thread is
 * executing.
 *
 * <h2>Scoped values as capabilities</h2>
 *
 * A {@code ScopedValue} object should be treated as a <em>capability</em> or a key to
 * access its value when the {@code ScopedValue} is bound. Secure usage depends on access
 * control (see <cite>The Java Virtual Machine Specification</cite>, Section {@jvms 5.4.4})
 * and taking care to not share the {@code ScopedValue} object. In many cases, a {@code
 * ScopedValue} will be declared in a {@code final} and {@code static} field so that it
 * is only accessible to code in a single class (or nest).
 *
 * <h2><a id="rebind">Rebinding</a></h2>
 *
 * The {@code ScopedValue} API allows a new binding to be established for <em>nested
 * dynamic scopes</em>. This is known as <em>rebinding</em>. A {@code ScopedValue} that
 * is bound to a value may be bound to a new value for the bounded execution of a new
 * method. The unfolding execution of code executed by that method defines the nested
 * dynamic scope. When the method completes, the value of the {@code ScopedValue} reverts
 * to its previous value.
 *
 * <p> In the above example, suppose that code executed by {@code doSomething} binds
 * {@code NAME} to a new value with:
 * {@snippet lang=java :
 *     ScopedValue.where(NAME, "duchess").run(() -> doMore());
 * }
 * Code executed directly or indirectly by {@code doMore()} that invokes {@code
 * NAME.get()} will read the value "{@code duchess}". When {@code doMore()} completes
 * then the value of {@code NAME} reverts to "{@code duke}".
 *
 * <h2><a id="inheritance">Inheritance</a></h2>
 *
 * {@code ScopedValue} supports sharing across threads. This sharing is limited to
 * structured cases where child threads are started and terminate within the bounded
 * period of execution by a parent thread. When using a {@link StructuredTaskScope},
 * scoped value bindings are <em>captured</em> when creating a {@code StructuredTaskScope}
 * and inherited by all threads started in that task scope with the
 * {@link StructuredTaskScope#fork(java.util.concurrent.Callable) fork} method.
 *
 * <p> A {@code ScopedValue} that is shared across threads requires that the value be an
 * immutable object or for all access to the value to be appropriately synchronized.
 *
 * <p> In the following example, the {@code ScopedValue} {@code NAME} is bound to the
 * value "{@code duke}" for the execution of a runnable operation. The code in the {@code
 * run} method creates a {@code StructuredTaskScope} that forks three tasks. Code executed
 * directly or indirectly by these threads running {@code childTask1()}, {@code childTask2()},
 * and {@code childTask3()} that invokes {@code NAME.get()} will read the value
 * "{@code duke}".
 *
 * {@snippet lang=java :
 *     private static final ScopedValue<String> NAME = ScopedValue.newInstance();

 *     ScopedValue.where(NAME, "duke").run(() -> {
 *         // @link substring="open" target="StructuredTaskScope#open()" :
 *         try (var scope = StructuredTaskScope.open()) {
 *
 *              // @link substring="fork" target="StructuredTaskScope#fork(java.util.concurrent.Callable)" :
 *              scope.fork(() -> childTask1());
 *              scope.fork(() -> childTask2());
 *              scope.fork(() -> childTask3());
 *
 *              // @link substring="join" target="StructuredTaskScope#join()" :
 *              scope.join();
 *
 *              ..
 *          }
 *     });
 * }
 *
 * <p> Unless otherwise specified, passing a {@code null} argument to a method in this
 * class will cause a {@link NullPointerException} to be thrown.
 *
 * @apiNote
 * A {@code ScopedValue} should be preferred over a {@link ThreadLocal} for cases where
 * the goal is "one-way transmission" of data without using method parameters.  While a
 * {@code ThreadLocal} can be used to pass data to a method without using method parameters,
 * it does suffer from a number of issues:
 * <ol>
 *   <li> {@code ThreadLocal} does not prevent code in a faraway callee from {@linkplain
 *   ThreadLocal#set(Object) setting} a new value.
 *   <li> A {@code ThreadLocal} has an unbounded lifetime and thus continues to have a value
 *   after a method completes, unless explicitly {@linkplain ThreadLocal#remove() removed}.
 *   <li> {@linkplain InheritableThreadLocal Inheritance} is expensive - the map of
 *   thread-locals to values must be copied when creating each child thread.
 * </ol>
 *
 * @implNote
 * Scoped values are designed to be used in fairly small
 * numbers. {@link #get} initially performs a search through enclosing
 * scopes to find a scoped value's innermost binding. It
 * then caches the result of the search in a small thread-local
 * cache. Subsequent invocations of {@link #get} for that scoped value
 * will almost always be very fast. However, if a program has many
 * scoped values that it uses cyclically, the cache hit rate
 * will be low and performance will be poor. This design allows
 * scoped-value inheritance by {@link StructuredTaskScope} threads to
 * be very fast: in essence, no more than copying a pointer, and
 * leaving a scoped-value binding also requires little more than
 * updating a pointer.
 *
 * <p>Because the scoped-value per-thread cache is small, clients
 * should minimize the number of bound scoped values in use. For
 * example, if it is necessary to pass a number of values in this way,
 * it makes sense to create a record class to hold those values, and
 * then bind a single {@code ScopedValue} to an instance of that record.
 *
 * <p>For this release, the reference implementation
 * provides some system properties to tune the performance of scoped
 * values.
 *
 * <p>The system property {@code java.lang.ScopedValue.cacheSize}
 * controls the size of the (per-thread) scoped-value cache. This cache is crucial
 * for the performance of scoped values. If it is too small,
 * the runtime library will repeatedly need to scan for each
 * {@link #get}. If it is too large, memory will be unnecessarily
 * consumed. The default scoped-value cache size is 16 entries. It may
 * be varied from 2 to 16 entries in size. {@code ScopedValue.cacheSize}
 * must be an integer power of 2.
 *
 * <p>For example, you could use {@code -Djava.lang.ScopedValue.cacheSize=8}.
 *
 * <p>The other system property is {@code jdk.preserveScopedValueCache}.
 * This property determines whether the per-thread scoped-value
 * cache is preserved when a virtual thread is blocked. By default
 * this property is set to {@code true}, meaning that every virtual
 * thread preserves its scoped-value cache when blocked. Like {@code
 * ScopedValue.cacheSize}, this is a space versus speed trade-off: in
 * situations where many virtual threads are blocked most of the time,
 * setting this property to {@code false} might result in a useful
 * memory saving, but each virtual thread's scoped-value cache would
 * have to be regenerated after a blocking operation.
 *
 * @param <T> the type of the value
 * @since 25
 */
public final class ScopedValue<T> {
    private final int hash;

    @Override
    public int hashCode() { return hash; }

    /**
     * An immutable map from {@code ScopedValue} to values.
     *
     * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
     * or method in this class will cause a {@link NullPointerException} to be thrown.
     */
    static final class Snapshot {
        final Snapshot prev;
        final Carrier bindings;
        final int bitmask;

        private static final Object NIL = new Object();

        static final Snapshot EMPTY_SNAPSHOT = new Snapshot();

        Snapshot(Carrier bindings, Snapshot prev) {
            this.prev = prev;
            this.bindings = bindings;
            this.bitmask = bindings.bitmask | prev.bitmask;
        }

        protected Snapshot() {
            this.prev = null;
            this.bindings = null;
            this.bitmask = 0;
        }

        Object find(ScopedValue<?> key) {
            int bits = key.bitmask();
            for (Snapshot snapshot = this;
                 containsAll(snapshot.bitmask, bits);
                 snapshot = snapshot.prev) {
                for (Carrier carrier = snapshot.bindings;
                     carrier != null && containsAll(carrier.bitmask, bits);
                     carrier = carrier.prev) {
                    if (carrier.getKey() == key) {
                        Object value = carrier.get();
                        return value;
                    }
                }
            }
            return NIL;
        }
    }

    /**
     * A mapping of scoped values, as <em>keys</em>, to values.
     *
     * <p> A {@code Carrier} is used to accumulate mappings so that an operation (a {@link
     * Runnable} or {@link CallableOp}) can be executed with all scoped values in the
     * mapping bound to values. The following example runs an operation with {@code k1}
     * bound (or rebound) to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
     * {@snippet lang=java :
     *     // @link substring="where" target="#where(ScopedValue, Object)" :
     *     ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
     * }
     *
     * <p> A {@code Carrier} is immutable and thread-safe. The {@link
     * #where(ScopedValue, Object) where} method returns a new {@code Carrier} object,
     * it does not mutate an existing mapping.
     *
     * <p> Unless otherwise specified, passing a {@code null} argument to a method in
     * this class will cause a {@link NullPointerException} to be thrown.
     *
     * @since 25
     */
    public static final class Carrier {
        // Bit masks: a 1 in position n indicates that this set of bound values
        // hits that slot in the cache.
        final int bitmask;
        final ScopedValue<?> key;
        final Object value;
        final Carrier prev;

        Carrier(ScopedValue<?> key, Object value, Carrier prev) {
            this.key = key;
            this.value = value;
            this.prev = prev;
            int bits = key.bitmask();
            if (prev != null) {
                bits |= prev.bitmask;
            }
            this.bitmask = bits;
        }

        /**
         * Add a binding to this map, returning a new Carrier instance.
         */
        private static <T> Carrier where(ScopedValue<T> key, T value, Carrier prev) {
            return new Carrier(key, value, prev);
        }

        /**
         * Returns a new {@code Carrier} with the mappings from this carrier plus a
         * new mapping from {@code key} to {@code value}. If this carrier already has a
         * mapping for the scoped value {@code key} then it will map to the new
         * {@code value}. The current carrier is immutable, so it is not changed by this
         * method.
         *
         * @param key the {@code ScopedValue} key
         * @param value the value, can be {@code null}
         * @param <T> the type of the value
         * @return a new {@code Carrier} with the mappings from this carrier plus the new mapping
         */
        public <T> Carrier where(ScopedValue<T> key, T value) {
            return where(key, value, this);
        }

        /*
         * Return a new set consisting of a single binding.
         */
        static <T> Carrier of(ScopedValue<T> key, T value) {
            return where(key, value, null);
        }

        Object get() {
            return value;
        }

        ScopedValue<?> getKey() {
            return key;
        }

        /**
         * Returns the value of a {@link ScopedValue} in this mapping.
         *
         * @param key the {@code ScopedValue} key
         * @param <T> the type of the value
         * @return the value
         * @throws NoSuchElementException if the key is not present in this mapping
         */
        @SuppressWarnings("unchecked")
        public <T> T get(ScopedValue<T> key) {
            var bits = key.bitmask();
            for (Carrier carrier = this;
                 carrier != null && containsAll(carrier.bitmask, bits);
                 carrier = carrier.prev) {
                if (carrier.getKey() == key) {
                    Object value = carrier.get();
                    return (T) value;
                }
            }
            throw new NoSuchElementException("No mapping present");
        }

        /**
         * Calls a value-returning operation with each scoped value in this mapping bound
         * to its value in the current thread.
         * When the operation completes (normally or with an exception), each scoped value
         * in the mapping will revert to being unbound, or revert to its previous value
         * when previously bound, in the current thread. If {@code op} completes with an
         * exception then it propagated by this method.
         *
         * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
         * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
         * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
         * as a <em>structure violation</em> when the operation completes (normally or with an
         * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
         * is closed and {@link StructureViolationException} is thrown.
         *
         * @param op the operation to run
         * @param <R> the type of the result of the operation
         * @param <X> type of the exception thrown by the operation
         * @return the result
         * @throws StructureViolationException if a structure violation is detected
         * @throws X if {@code op} completes with an exception
         */
        public <R, X extends Throwable> R call(CallableOp<? extends R, X> op) throws X {
            Objects.requireNonNull(op);
            Cache.invalidate(bitmask);
            var prevSnapshot = scopedValueBindings();
            var newSnapshot = new Snapshot(this, prevSnapshot);
            return runWith(newSnapshot, op);
        }

        /**
         * Execute the action with a set of ScopedValue bindings.
         *
         * The VM recognizes this method as special, so any changes to the
         * name or signature require corresponding changes in
         * JVM_FindScopedValueBindings().
         */
        @Hidden
        @ForceInline
        private <R, X extends Throwable> R runWith(Snapshot newSnapshot, CallableOp<R, X> op) {
            try {
                Thread.setScopedValueBindings(newSnapshot);
                Thread.ensureMaterializedForStackWalk(newSnapshot);
                return ScopedValueContainer.call(op);
            } finally {
                Reference.reachabilityFence(newSnapshot);
                Thread.setScopedValueBindings(newSnapshot.prev);
                Cache.invalidate(bitmask);
            }
        }

        /**
         * Runs an operation with each scoped value in this mapping bound to its value
         * in the current thread.
         * When the operation completes (normally or with an exception), each scoped value
         * in the mapping will revert to being unbound, or revert to its previous value
         * when previously bound, in the current thread. If {@code op} completes with an
         * exception then it propagated by this method.
         *
         * <p> Scoped values are intended to be used in a <em>structured manner</em>. If code
         * invoked directly or indirectly by the operation creates a {@link StructuredTaskScope}
         * but does not {@linkplain StructuredTaskScope#close() close} it, then it is detected
         * as a <em>structure violation</em> when the operation completes (normally or with an
         * exception). In that case, the underlying construct of the {@code StructuredTaskScope}
         * is closed and {@link StructureViolationException} is thrown.
         *
         * @param op the operation to run
         * @throws StructureViolationException if a structure violation is detected
         */
        public void run(Runnable op) {
            Objects.requireNonNull(op);
            Cache.invalidate(bitmask);
            var prevSnapshot = scopedValueBindings();
            var newSnapshot = new Snapshot(this, prevSnapshot);
            runWith(newSnapshot, op);
        }

        /**
         * Execute the action with a set of {@code ScopedValue} bindings.
         *
         * The VM recognizes this method as special, so any changes to the
         * name or signature require corresponding changes in
         * JVM_FindScopedValueBindings().
         */
        @Hidden
        @ForceInline
        private void runWith(Snapshot newSnapshot, Runnable op) {
            try {
                Thread.setScopedValueBindings(newSnapshot);
                Thread.ensureMaterializedForStackWalk(newSnapshot);
                ScopedValueContainer.run(op);
            } finally {
                Reference.reachabilityFence(newSnapshot);
                Thread.setScopedValueBindings(newSnapshot.prev);
                Cache.invalidate(bitmask);
            }
        }
    }

    /**
     * An operation that returns a result and may throw an exception.
     *
     * @param <T> result type of the operation
     * @param <X> type of the exception thrown by the operation
     * @since 25
     */
    @FunctionalInterface
    public interface CallableOp<T, X extends Throwable> {
        /**
         * Executes this operation.
         * @return the result, can be null
         * @throws X if the operation completes with an exception
         */
        T call() throws X;
    }

    /**
     * Creates a new {@code Carrier} with a single mapping of a {@code ScopedValue}
     * <em>key</em> to a value. The {@code Carrier} can be used to accumulate mappings so
     * that an operation can be executed with all scoped values in the mapping bound to
     * values. The following example runs an operation with {@code k1} bound (or rebound)
     * to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}.
     * {@snippet lang=java :
     *     // @link substring="run" target="Carrier#run(Runnable)" :
     *     ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... );
     * }
     *
     * @param key the {@code ScopedValue} key
     * @param value the value, can be {@code null}
     * @param <T> the type of the value
     * @return a new {@code Carrier} with a single mapping
     */
    public static <T> Carrier where(ScopedValue<T> key, T value) {
        return Carrier.of(key, value);
    }

    private ScopedValue() {
        this.hash = generateKey();
    }

    /**
     * Creates a scoped value that is initially unbound for all threads.
     *
     * @param <T> the type of the value
     * @return a new {@code ScopedValue}
     */
    public static <T> ScopedValue<T> newInstance() {
        return new ScopedValue<T>();
    }

    /**
     * {@return the value of the scoped value if bound in the current thread}
     *
     * @throws NoSuchElementException if the scoped value is not bound
     */
    @ForceInline
    @SuppressWarnings("unchecked")
    public T get() {
        Object[] objects;
        if ((objects = scopedValueCache()) != null) {
            // This code should perhaps be in class Cache. We do it
            // here because the generated code is small and fast and
            // we really want it to be inlined in the caller.
            int n = (hash & Cache.SLOT_MASK) * 2;
            if (objects[n] == this) {
                return (T)objects[n + 1];
            }
            n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2;
            if (objects[n] == this) {
                return (T)objects[n + 1];
            }
        }
        return slowGet();
    }

    @SuppressWarnings("unchecked")
    private T slowGet() {
        Object value = scopedValueBindings().find(this);
        if (value == Snapshot.NIL) {
            throw new NoSuchElementException("ScopedValue not bound");
        }
        Cache.put(this, value);
        return (T)value;
    }

    /**
     * Return the value of the scoped value or NIL if not bound.
     * Consult the cache, and only if the value is not found there
     * search the list of bindings. Update the cache if the binding
     * was found.
     */
    private Object findBinding() {
        Object[] objects = scopedValueCache();
        if (objects != null) {
            int n = (hash & Cache.SLOT_MASK) * 2;
            if (objects[n] == this) {
                return objects[n + 1];
            }
            n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2;
            if (objects[n] == this) {
                return objects[n + 1];
            }
        }
        Object value = scopedValueBindings().find(this);
        boolean found = (value != Snapshot.NIL);
        if (found)  Cache.put(this, value);
        return value;
    }

    /**
     * {@return {@code true} if this scoped value is bound in the current thread}
     */
    public boolean isBound() {
        Object obj = findBinding();
        return obj != Snapshot.NIL;
    }

    /**
     * Returns the value of this scoped value if bound in the current thread, otherwise
     * returns {@code other}.
     *
     * @param other the value to return if not bound
     * @return the value of the scoped value if bound, otherwise {@code other}
     */
    public T orElse(T other) {
        Objects.requireNonNull(other);
        Object obj = findBinding();
        if (obj != Snapshot.NIL) {
            @SuppressWarnings("unchecked")
            T value = (T) obj;
            return value;
        } else {
            return other;
        }
    }

    /**
     * Returns the value of this scoped value if bound in the current thread, otherwise
     * throws an exception produced by the exception supplying function.
     *
     * @param <X> the type of the exception that may be thrown
     * @param exceptionSupplier the supplying function that produces the exception to throw
     * @return the value of the scoped value if bound in the current thread
     * @throws X if the scoped value is not bound in the current thread
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        Objects.requireNonNull(exceptionSupplier);
        Object obj = findBinding();
        if (obj != Snapshot.NIL) {
            @SuppressWarnings("unchecked")
            T value = (T) obj;
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    private static Object[] scopedValueCache() {
        return Thread.scopedValueCache();
    }

    private static void setScopedValueCache(Object[] cache) {
        Thread.setScopedValueCache(cache);
    }

    // Special value to indicate this is a newly-created Thread
    // Note that his must match the declaration in j.l.Thread.
    private static final Object NEW_THREAD_BINDINGS = Thread.class;

    private static Snapshot scopedValueBindings() {
        // Bindings can be in one of four states:
        //
        // 1: class Thread: this is a new Thread instance, and no
        // scoped values have ever been bound in this Thread, and neither
        // have any scoped value bindings been inherited from a parent.
        // 2: EmptySnapshot.SINGLETON: This is effectively an empty binding.
        // 3: A Snapshot instance: this contains one or more scoped value
        // bindings.
        // 4: null: there may be some bindings in this Thread, but we don't know
        // where they are. We must invoke Thread.findScopedValueBindings() to walk
        // the stack to find them.

        Object bindings = Thread.scopedValueBindings();
        if (bindings == NEW_THREAD_BINDINGS) {
            // This must be a new thread
            return Snapshot.EMPTY_SNAPSHOT;
        }
        if (bindings == null) {
            // Search the stack
            bindings = Thread.findScopedValueBindings();
            if (bindings == NEW_THREAD_BINDINGS || bindings == null) {
                // We've walked the stack without finding anything.
                bindings = Snapshot.EMPTY_SNAPSHOT;
            }
            Thread.setScopedValueBindings(bindings);
        }
        assert (bindings != null);
        return (Snapshot) bindings;
    }

    private static int nextKey = 0xf0f0_f0f0;

    // A Marsaglia xor-shift generator used to generate hashes. This one has full period, so
    // it generates 2**32 - 1 hashes before it repeats. We're going to use the lowest n bits
    // and the next n bits as cache indexes, so we make sure that those indexes map
    // to different slots in the cache.
    private static synchronized int generateKey() {
        int x = nextKey;
        do {
            x ^= x >>> 12;
            x ^= x << 9;
            x ^= x >>> 23;
        } while (Cache.primarySlot(x) == Cache.secondarySlot(x));
        return (nextKey = x);
    }

    /**
     * Return a bit mask that may be used to determine if this ScopedValue is
     * bound in the current context. Each Carrier holds a bit mask which is
     * the OR of all the bit masks of the bound ScopedValues.
     * @return the bitmask
     */
    int bitmask() {
        return (1 << Cache.primaryIndex(this)) | (1 << (Cache.secondaryIndex(this) + Cache.TABLE_SIZE));
    }

    // Return true iff bitmask, considered as a set of bits, contains all
    // of the bits in targetBits.
    static boolean containsAll(int bitmask, int targetBits) {
        return (bitmask & targetBits) == targetBits;
    }

    // A small fixed-size key-value cache. When a scoped value's get() method
    // is invoked, we record the result of the lookup in this per-thread cache
    // for fast access in future.
    private static final class Cache {
        static final int INDEX_BITS = 4;  // Must be a power of 2
        static final int TABLE_SIZE = 1 << INDEX_BITS;
        static final int TABLE_MASK = TABLE_SIZE - 1;
        static final int PRIMARY_MASK = (1 << TABLE_SIZE) - 1;

        // The number of elements in the cache array, and a bit mask used to
        // select elements from it.
        private static final int CACHE_TABLE_SIZE, SLOT_MASK;
        // The largest cache we allow. Must be a power of 2 and greater than
        // or equal to 2.
        private static final int MAX_CACHE_SIZE = 16;

        static {
            final String propertyName = "java.lang.ScopedValue.cacheSize";
            var sizeString = System.getProperty(propertyName, "16");
            var cacheSize = Integer.valueOf(sizeString);
            if (cacheSize < 2 || cacheSize > MAX_CACHE_SIZE) {
                cacheSize = MAX_CACHE_SIZE;
                System.err.println(propertyName + " is out of range: is " + sizeString);
            }
            if ((cacheSize & (cacheSize - 1)) != 0) {  // a power of 2
                cacheSize = MAX_CACHE_SIZE;
                System.err.println(propertyName + " must be an integer power of 2: is " + sizeString);
            }
            CACHE_TABLE_SIZE = cacheSize;
            SLOT_MASK = cacheSize - 1;
        }

        static int primaryIndex(ScopedValue<?> key) {
            return key.hash & TABLE_MASK;
        }

        static int secondaryIndex(ScopedValue<?> key) {
            return (key.hash >> INDEX_BITS) & TABLE_MASK;
        }

        private static int primarySlot(ScopedValue<?> key) {
            return key.hashCode() & SLOT_MASK;
        }

        private static int secondarySlot(ScopedValue<?> key) {
            return (key.hash >> INDEX_BITS) & SLOT_MASK;
        }

        static int primarySlot(int hash) {
            return hash & SLOT_MASK;
        }

        static int secondarySlot(int hash) {
            return (hash >> INDEX_BITS) & SLOT_MASK;
        }

        static void put(ScopedValue<?> key, Object value) {
            Object[] theCache = scopedValueCache();
            if (theCache == null) {
                theCache = new Object[CACHE_TABLE_SIZE * 2];
                setScopedValueCache(theCache);
            }
            // Update the cache to replace one entry with the value we just looked up.
            // Each value can be in one of two possible places in the cache.
            // Pick a victim at (pseudo-)random.
            int k1 = primarySlot(key);
            int k2 = secondarySlot(key);
            var usePrimaryIndex = chooseVictim();
            int victim = usePrimaryIndex ? k1 : k2;
            int other = usePrimaryIndex ? k2 : k1;
            setKeyAndObjectAt(victim, key, value);
            if (getKey(theCache, other) == key) {
                setKeyAndObjectAt(other, key, value);
            }
        }

        private static void setKeyAndObjectAt(int n, Object key, Object value) {
            var cache = scopedValueCache();
            cache[n * 2] = key;
            cache[n * 2 + 1] = value;
        }

        private static void setKeyAndObjectAt(Object[] cache, int n, Object key, Object value) {
            cache[n * 2] = key;
            cache[n * 2 + 1] = value;
        }

        private static Object getKey(Object[] objs, int n) {
            return objs[n * 2];
        }

        private static void setKey(Object[] objs, int n, Object key) {
            objs[n * 2] = key;
        }

        private static final JavaUtilConcurrentTLRAccess THREAD_LOCAL_RANDOM_ACCESS
                = SharedSecrets.getJavaUtilConcurrentTLRAccess();

        // Return either true or false, at pseudo-random, with a bias towards true.
        // This chooses either the primary or secondary cache slot, but the
        // primary slot is approximately twice as likely to be chosen as the
        // secondary one.
        private static boolean chooseVictim() {
            int r = THREAD_LOCAL_RANDOM_ACCESS.nextSecondaryThreadLocalRandomSeed();
            return (r & 15) >= 5;
        }

        // Null a set of cache entries, indicated by the 1-bits given
        static void invalidate(int toClearBits) {
            toClearBits = (toClearBits >>> TABLE_SIZE) | (toClearBits & PRIMARY_MASK);
            Object[] objects;
            if ((objects = scopedValueCache()) != null) {
                for (int bits = toClearBits; bits != 0; ) {
                    int index = Integer.numberOfTrailingZeros(bits);
                    setKeyAndObjectAt(objects, index & SLOT_MASK, null, null);
                    bits &= ~1 << index;
                }
            }
        }
    }
}
