Path: blob/master/src/java.base/share/classes/java/lang/ClassValue.java
41152 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.lang;2627import java.util.WeakHashMap;28import java.lang.ref.WeakReference;29import java.util.concurrent.atomic.AtomicInteger;3031import jdk.internal.misc.Unsafe;3233import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;34import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;3536/**37* Lazily associate a computed value with (potentially) every type.38* For example, if a dynamic language needs to construct a message dispatch39* table for each class encountered at a message send call site,40* it can use a {@code ClassValue} to cache information needed to41* perform the message send quickly, for each class encountered.42* @author John Rose, JSR 292 EG43* @since 1.744*/45public abstract class ClassValue<T> {46/**47* Sole constructor. (For invocation by subclass constructors, typically48* implicit.)49*/50protected ClassValue() {51}5253/**54* Computes the given class's derived value for this {@code ClassValue}.55* <p>56* This method will be invoked within the first thread that accesses57* the value with the {@link #get get} method.58* <p>59* Normally, this method is invoked at most once per class,60* but it may be invoked again if there has been a call to61* {@link #remove remove}.62* <p>63* If this method throws an exception, the corresponding call to {@code get}64* will terminate abnormally with that exception, and no class value will be recorded.65*66* @param type the type whose class value must be computed67* @return the newly computed value associated with this {@code ClassValue}, for the given class or interface68* @see #get69* @see #remove70*/71protected abstract T computeValue(Class<?> type);7273/**74* Returns the value for the given class.75* If no value has yet been computed, it is obtained by76* an invocation of the {@link #computeValue computeValue} method.77* <p>78* The actual installation of the value on the class79* is performed atomically.80* At that point, if several racing threads have81* computed values, one is chosen, and returned to82* all the racing threads.83* <p>84* The {@code type} parameter is typically a class, but it may be any type,85* such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.86* <p>87* In the absence of {@code remove} calls, a class value has a simple88* state diagram: uninitialized and initialized.89* When {@code remove} calls are made,90* the rules for value observation are more complex.91* See the documentation for {@link #remove remove} for more information.92*93* @param type the type whose class value must be computed or retrieved94* @return the current value associated with this {@code ClassValue}, for the given class or interface95* @throws NullPointerException if the argument is null96* @see #remove97* @see #computeValue98*/99public T get(Class<?> type) {100// non-racing this.hashCodeForCache : final int101Entry<?>[] cache;102Entry<T> e = probeHomeLocation(cache = getCacheCarefully(type), this);103// racing e : current value <=> stale value from current cache or from stale cache104// invariant: e is null or an Entry with readable Entry.version and Entry.value105if (match(e))106// invariant: No false positive matches. False negatives are OK if rare.107// The key fact that makes this work: if this.version == e.version,108// then this thread has a right to observe (final) e.value.109return e.value();110// The fast path can fail for any of these reasons:111// 1. no entry has been computed yet112// 2. hash code collision (before or after reduction mod cache.length)113// 3. an entry has been removed (either on this type or another)114// 4. the GC has somehow managed to delete e.version and clear the reference115return getFromBackup(cache, type);116}117118/**119* Removes the associated value for the given class.120* If this value is subsequently {@linkplain #get read} for the same class,121* its value will be reinitialized by invoking its {@link #computeValue computeValue} method.122* This may result in an additional invocation of the123* {@code computeValue} method for the given class.124* <p>125* In order to explain the interaction between {@code get} and {@code remove} calls,126* we must model the state transitions of a class value to take into account127* the alternation between uninitialized and initialized states.128* To do this, number these states sequentially from zero, and note that129* uninitialized (or removed) states are numbered with even numbers,130* while initialized (or re-initialized) states have odd numbers.131* <p>132* When a thread {@code T} removes a class value in state {@code 2N},133* nothing happens, since the class value is already uninitialized.134* Otherwise, the state is advanced atomically to {@code 2N+1}.135* <p>136* When a thread {@code T} queries a class value in state {@code 2N},137* the thread first attempts to initialize the class value to state {@code 2N+1}138* by invoking {@code computeValue} and installing the resulting value.139* <p>140* When {@code T} attempts to install the newly computed value,141* if the state is still at {@code 2N}, the class value will be initialized142* with the computed value, advancing it to state {@code 2N+1}.143* <p>144* Otherwise, whether the new state is even or odd,145* {@code T} will discard the newly computed value146* and retry the {@code get} operation.147* <p>148* Discarding and retrying is an important proviso,149* since otherwise {@code T} could potentially install150* a disastrously stale value. For example:151* <ul>152* <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}153* <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it154* <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time155* <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}156* <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}157* <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work158* <li> the previous actions of {@code T2} are repeated several times159* <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...160* <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>161* </ul>162* We can assume in the above scenario that {@code CV.computeValue} uses locks to properly163* observe the time-dependent states as it computes {@code V1}, etc.164* This does not remove the threat of a stale value, since there is a window of time165* between the return of {@code computeValue} in {@code T} and the installation166* of the new value. No user synchronization is possible during this time.167*168* @param type the type whose class value must be removed169* @throws NullPointerException if the argument is null170*/171public void remove(Class<?> type) {172ClassValueMap map = getMap(type);173map.removeEntry(this);174}175176// Possible functionality for JSR 292 MR 1177/*public*/ void put(Class<?> type, T value) {178ClassValueMap map = getMap(type);179map.changeEntry(this, value);180}181182/// --------183/// Implementation...184/// --------185186/** Return the cache, if it exists, else a dummy empty cache. */187private static Entry<?>[] getCacheCarefully(Class<?> type) {188// racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y]189ClassValueMap map = type.classValueMap;190if (map == null) return EMPTY_CACHE;191Entry<?>[] cache = map.getCache();192return cache;193// invariant: returned value is safe to dereference and check for an Entry194}195196/** Initial, one-element, empty cache used by all Class instances. Must never be filled. */197private static final Entry<?>[] EMPTY_CACHE = { null };198199/**200* Slow tail of ClassValue.get to retry at nearby locations in the cache,201* or take a slow lock and check the hash table.202* Called only if the first probe was empty or a collision.203* This is a separate method, so compilers can process it independently.204*/205private T getFromBackup(Entry<?>[] cache, Class<?> type) {206Entry<T> e = probeBackupLocations(cache, this);207if (e != null)208return e.value();209return getFromHashMap(type);210}211212// Hack to suppress warnings on the (T) cast, which is a no-op.213@SuppressWarnings("unchecked")214Entry<T> castEntry(Entry<?> e) { return (Entry<T>) e; }215216/** Called when the fast path of get fails, and cache reprobe also fails.217*/218private T getFromHashMap(Class<?> type) {219// The fail-safe recovery is to fall back to the underlying classValueMap.220ClassValueMap map = getMap(type);221for (;;) {222Entry<T> e = map.startEntry(this);223if (!e.isPromise())224return e.value();225try {226// Try to make a real entry for the promised version.227e = makeEntry(e.version(), computeValue(type));228} finally {229// Whether computeValue throws or returns normally,230// be sure to remove the empty entry.231e = map.finishEntry(this, e);232}233if (e != null)234return e.value();235// else try again, in case a racing thread called remove (so e == null)236}237}238239/** Check that e is non-null, matches this ClassValue, and is live. */240boolean match(Entry<?> e) {241// racing e.version : null (blank) => unique Version token => null (GC-ed version)242// non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile)243return (e != null && e.get() == this.version);244// invariant: No false positives on version match. Null is OK for false negative.245// invariant: If version matches, then e.value is readable (final set in Entry.<init>)246}247248/** Internal hash code for accessing Class.classValueMap.cacheArray. */249final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK;250251/** Value stream for hashCodeForCache. See similar structure in ThreadLocal. */252private static final AtomicInteger nextHashCode = new AtomicInteger();253254/** Good for power-of-two tables. See similar structure in ThreadLocal. */255private static final int HASH_INCREMENT = 0x61c88647;256257/** Mask a hash code to be positive but not too large, to prevent wraparound. */258static final int HASH_MASK = (-1 >>> 2);259260/**261* Private key for retrieval of this object from ClassValueMap.262*/263static class Identity {264}265/**266* This ClassValue's identity, expressed as an opaque object.267* The main object {@code ClassValue.this} is incorrect since268* subclasses may override {@code ClassValue.equals}, which269* could confuse keys in the ClassValueMap.270*/271final Identity identity = new Identity();272273/**274* Current version for retrieving this class value from the cache.275* Any number of computeValue calls can be cached in association with one version.276* But the version changes when a remove (on any type) is executed.277* A version change invalidates all cache entries for the affected ClassValue,278* by marking them as stale. Stale cache entries do not force another call279* to computeValue, but they do require a synchronized visit to a backing map.280* <p>281* All user-visible state changes on the ClassValue take place under282* a lock inside the synchronized methods of ClassValueMap.283* Readers (of ClassValue.get) are notified of such state changes284* when this.version is bumped to a new token.285* This variable must be volatile so that an unsynchronized reader286* will receive the notification without delay.287* <p>288* If version were not volatile, one thread T1 could persistently hold onto289* a stale value this.value == V1, while another thread T2 advances290* (under a lock) to this.value == V2. This will typically be harmless,291* but if T1 and T2 interact causally via some other channel, such that292* T1's further actions are constrained (in the JMM) to happen after293* the V2 event, then T1's observation of V1 will be an error.294* <p>295* The practical effect of making this.version be volatile is that it cannot296* be hoisted out of a loop (by an optimizing JIT) or otherwise cached.297* Some machines may also require a barrier instruction to execute298* before this.version.299*/300private volatile Version<T> version = new Version<>(this);301Version<T> version() { return version; }302void bumpVersion() { version = new Version<>(this); }303static class Version<T> {304private final ClassValue<T> classValue;305private final Entry<T> promise = new Entry<>(this);306Version(ClassValue<T> classValue) { this.classValue = classValue; }307ClassValue<T> classValue() { return classValue; }308Entry<T> promise() { return promise; }309boolean isLive() { return classValue.version() == this; }310}311312/** One binding of a value to a class via a ClassValue.313* States are:<ul>314* <li> promise if value == Entry.this315* <li> else dead if version == null316* <li> else stale if version != classValue.version317* <li> else live </ul>318* Promises are never put into the cache; they only live in the319* backing map while a computeValue call is in flight.320* Once an entry goes stale, it can be reset at any time321* into the dead state.322*/323static class Entry<T> extends WeakReference<Version<T>> {324final Object value; // usually of type T, but sometimes (Entry)this325Entry(Version<T> version, T value) {326super(version);327this.value = value; // for a regular entry, value is of type T328}329private void assertNotPromise() { assert(!isPromise()); }330/** For creating a promise. */331Entry(Version<T> version) {332super(version);333this.value = this; // for a promise, value is not of type T, but Entry!334}335/** Fetch the value. This entry must not be a promise. */336@SuppressWarnings("unchecked") // if !isPromise, type is T337T value() { assertNotPromise(); return (T) value; }338boolean isPromise() { return value == this; }339Version<T> version() { return get(); }340ClassValue<T> classValueOrNull() {341Version<T> v = version();342return (v == null) ? null : v.classValue();343}344boolean isLive() {345Version<T> v = version();346if (v == null) return false;347if (v.isLive()) return true;348clear();349return false;350}351Entry<T> refreshVersion(Version<T> v2) {352assertNotPromise();353@SuppressWarnings("unchecked") // if !isPromise, type is T354Entry<T> e2 = new Entry<>(v2, (T) value);355clear();356// value = null -- caller must drop357return e2;358}359static final Entry<?> DEAD_ENTRY = new Entry<>(null, null);360}361362/** Return the backing map associated with this type. */363private static ClassValueMap getMap(Class<?> type) {364// racing type.classValueMap : null (blank) => unique ClassValueMap365// if a null is observed, a map is created (lazily, synchronously, uniquely)366// all further access to that map is synchronized367ClassValueMap map = type.classValueMap;368if (map != null) return map;369return initializeMap(type);370}371372private static final Object CRITICAL_SECTION = new Object();373private static final Unsafe UNSAFE = Unsafe.getUnsafe();374private static ClassValueMap initializeMap(Class<?> type) {375ClassValueMap map;376synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks377// happens about once per type378if ((map = type.classValueMap) == null) {379map = new ClassValueMap();380// Place a Store fence after construction and before publishing to emulate381// ClassValueMap containing final fields. This ensures it can be382// published safely in the non-volatile field Class.classValueMap,383// since stores to the fields of ClassValueMap will not be reordered384// to occur after the store to the field type.classValueMap385UNSAFE.storeFence();386387type.classValueMap = map;388}389}390return map;391}392393static <T> Entry<T> makeEntry(Version<T> explicitVersion, T value) {394// Note that explicitVersion might be different from this.version.395return new Entry<>(explicitVersion, value);396397// As soon as the Entry is put into the cache, the value will be398// reachable via a data race (as defined by the Java Memory Model).399// This race is benign, assuming the value object itself can be400// read safely by multiple threads. This is up to the user.401//402// The entry and version fields themselves can be safely read via403// a race because they are either final or have controlled states.404// If the pointer from the entry to the version is still null,405// or if the version goes immediately dead and is nulled out,406// the reader will take the slow path and retry under a lock.407}408409// The following class could also be top level and non-public:410411/** A backing map for all ClassValues.412* Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).413* Also manages an unserialized fast-path cache.414*/415static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {416private Entry<?>[] cacheArray;417private int cacheLoad, cacheLoadLimit;418419/** Number of entries initially allocated to each type when first used with any ClassValue.420* It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.421* Must be a power of 2.422*/423private static final int INITIAL_ENTRIES = 32;424425/** Build a backing map for ClassValues.426* Also, create an empty cache array and install it on the class.427*/428ClassValueMap() {429sizeCache(INITIAL_ENTRIES);430}431432Entry<?>[] getCache() { return cacheArray; }433434/** Initiate a query. Store a promise (placeholder) if there is no value yet. */435synchronized436<T> Entry<T> startEntry(ClassValue<T> classValue) {437@SuppressWarnings("unchecked") // one map has entries for all value types <T>438Entry<T> e = (Entry<T>) get(classValue.identity);439Version<T> v = classValue.version();440if (e == null) {441e = v.promise();442// The presence of a promise means that a value is pending for v.443// Eventually, finishEntry will overwrite the promise.444put(classValue.identity, e);445// Note that the promise is never entered into the cache!446return e;447} else if (e.isPromise()) {448// Somebody else has asked the same question.449// Let the races begin!450if (e.version() != v) {451e = v.promise();452put(classValue.identity, e);453}454return e;455} else {456// there is already a completed entry here; report it457if (e.version() != v) {458// There is a stale but valid entry here; make it fresh again.459// Once an entry is in the hash table, we don't care what its version is.460e = e.refreshVersion(v);461put(classValue.identity, e);462}463// Add to the cache, to enable the fast path, next time.464checkCacheLoad();465addToCache(classValue, e);466return e;467}468}469470/** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */471synchronized472<T> Entry<T> finishEntry(ClassValue<T> classValue, Entry<T> e) {473@SuppressWarnings("unchecked") // one map has entries for all value types <T>474Entry<T> e0 = (Entry<T>) get(classValue.identity);475if (e == e0) {476// We can get here during exception processing, unwinding from computeValue.477assert(e.isPromise());478remove(classValue.identity);479return null;480} else if (e0 != null && e0.isPromise() && e0.version() == e.version()) {481// If e0 matches the intended entry, there has not been a remove call482// between the previous startEntry and now. So now overwrite e0.483Version<T> v = classValue.version();484if (e.version() != v)485e = e.refreshVersion(v);486put(classValue.identity, e);487// Add to the cache, to enable the fast path, next time.488checkCacheLoad();489addToCache(classValue, e);490return e;491} else {492// Some sort of mismatch; caller must try again.493return null;494}495}496497/** Remove an entry. */498synchronized499void removeEntry(ClassValue<?> classValue) {500Entry<?> e = remove(classValue.identity);501if (e == null) {502// Uninitialized, and no pending calls to computeValue. No change.503} else if (e.isPromise()) {504// State is uninitialized, with a pending call to finishEntry.505// Since remove is a no-op in such a state, keep the promise506// by putting it back into the map.507put(classValue.identity, e);508} else {509// In an initialized state. Bump forward, and de-initialize.510classValue.bumpVersion();511// Make all cache elements for this guy go stale.512removeStaleEntries(classValue);513}514}515516/** Change the value for an entry. */517synchronized518<T> void changeEntry(ClassValue<T> classValue, T value) {519@SuppressWarnings("unchecked") // one map has entries for all value types <T>520Entry<T> e0 = (Entry<T>) get(classValue.identity);521Version<T> version = classValue.version();522if (e0 != null) {523if (e0.version() == version && e0.value() == value)524// no value change => no version change needed525return;526classValue.bumpVersion();527removeStaleEntries(classValue);528}529Entry<T> e = makeEntry(version, value);530put(classValue.identity, e);531// Add to the cache, to enable the fast path, next time.532checkCacheLoad();533addToCache(classValue, e);534}535536/// --------537/// Cache management.538/// --------539540// Statics do not need synchronization.541542/** Load the cache entry at the given (hashed) location. */543static Entry<?> loadFromCache(Entry<?>[] cache, int i) {544// non-racing cache.length : constant545// racing cache[i & (mask)] : null <=> Entry546return cache[i & (cache.length-1)];547// invariant: returned value is null or well-constructed (ready to match)548}549550/** Look in the cache, at the home location for the given ClassValue. */551static <T> Entry<T> probeHomeLocation(Entry<?>[] cache, ClassValue<T> classValue) {552return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache));553}554555/** Given that first probe was a collision, retry at nearby locations. */556static <T> Entry<T> probeBackupLocations(Entry<?>[] cache, ClassValue<T> classValue) {557if (PROBE_LIMIT <= 0) return null;558// Probe the cache carefully, in a range of slots.559int mask = (cache.length-1);560int home = (classValue.hashCodeForCache & mask);561Entry<?> e2 = cache[home]; // victim, if we find the real guy562if (e2 == null) {563return null; // if nobody is at home, no need to search nearby564}565// assume !classValue.match(e2), but do not assert, because of races566int pos2 = -1;567for (int i = home + 1; i < home + PROBE_LIMIT; i++) {568Entry<?> e = cache[i & mask];569if (e == null) {570break; // only search within non-null runs571}572if (classValue.match(e)) {573// relocate colliding entry e2 (from cache[home]) to first empty slot574cache[home] = e;575if (pos2 >= 0) {576cache[i & mask] = Entry.DEAD_ENTRY;577} else {578pos2 = i;579}580cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT)581? e2 // put e2 here if it fits582: Entry.DEAD_ENTRY);583return classValue.castEntry(e);584}585// Remember first empty slot, if any:586if (!e.isLive() && pos2 < 0) pos2 = i;587}588return null;589}590591/** How far out of place is e? */592private static int entryDislocation(Entry<?>[] cache, int pos, Entry<?> e) {593ClassValue<?> cv = e.classValueOrNull();594if (cv == null) return 0; // entry is not live!595int mask = (cache.length-1);596return (pos - cv.hashCodeForCache) & mask;597}598599/// --------600/// Below this line all functions are private, and assume synchronized access.601/// --------602603private void sizeCache(int length) {604assert((length & (length-1)) == 0); // must be power of 2605cacheLoad = 0;606cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100);607cacheArray = new Entry<?>[length];608}609610/** Make sure the cache load stays below its limit, if possible. */611private void checkCacheLoad() {612if (cacheLoad >= cacheLoadLimit) {613reduceCacheLoad();614}615}616private void reduceCacheLoad() {617removeStaleEntries();618if (cacheLoad < cacheLoadLimit)619return; // win620Entry<?>[] oldCache = getCache();621if (oldCache.length > HASH_MASK)622return; // lose623sizeCache(oldCache.length * 2);624for (Entry<?> e : oldCache) {625if (e != null && e.isLive()) {626addToCache(e);627}628}629}630631/** Remove stale entries in the given range.632* Should be executed under a Map lock.633*/634private void removeStaleEntries(Entry<?>[] cache, int begin, int count) {635if (PROBE_LIMIT <= 0) return;636int mask = (cache.length-1);637int removed = 0;638for (int i = begin; i < begin + count; i++) {639Entry<?> e = cache[i & mask];640if (e == null || e.isLive())641continue; // skip null and live entries642Entry<?> replacement = null;643if (PROBE_LIMIT > 1) {644// avoid breaking up a non-null run645replacement = findReplacement(cache, i);646}647cache[i & mask] = replacement;648if (replacement == null) removed += 1;649}650cacheLoad = Math.max(0, cacheLoad - removed);651}652653/** Clearing a cache slot risks disconnecting following entries654* from the head of a non-null run, which would allow them655* to be found via reprobes. Find an entry after cache[begin]656* to plug into the hole, or return null if none is needed.657*/658private Entry<?> findReplacement(Entry<?>[] cache, int home1) {659Entry<?> replacement = null;660int haveReplacement = -1, replacementPos = 0;661int mask = (cache.length-1);662for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) {663Entry<?> e2 = cache[i2 & mask];664if (e2 == null) break; // End of non-null run.665if (!e2.isLive()) continue; // Doomed anyway.666int dis2 = entryDislocation(cache, i2, e2);667if (dis2 == 0) continue; // e2 already optimally placed668int home2 = i2 - dis2;669if (home2 <= home1) {670// e2 can replace entry at cache[home1]671if (home2 == home1) {672// Put e2 exactly where he belongs.673haveReplacement = 1;674replacementPos = i2;675replacement = e2;676} else if (haveReplacement <= 0) {677haveReplacement = 0;678replacementPos = i2;679replacement = e2;680}681// And keep going, so we can favor larger dislocations.682}683}684if (haveReplacement >= 0) {685if (cache[(replacementPos+1) & mask] != null) {686// Be conservative, to avoid breaking up a non-null run.687cache[replacementPos & mask] = (Entry<?>) Entry.DEAD_ENTRY;688} else {689cache[replacementPos & mask] = null;690cacheLoad -= 1;691}692}693return replacement;694}695696/** Remove stale entries in the range near classValue. */697private void removeStaleEntries(ClassValue<?> classValue) {698removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT);699}700701/** Remove all stale entries, everywhere. */702private void removeStaleEntries() {703Entry<?>[] cache = getCache();704removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);705}706707/** Add the given entry to the cache, in its home location, unless it is out of date. */708private <T> void addToCache(Entry<T> e) {709ClassValue<T> classValue = e.classValueOrNull();710if (classValue != null)711addToCache(classValue, e);712}713714/** Add the given entry to the cache, in its home location. */715private <T> void addToCache(ClassValue<T> classValue, Entry<T> e) {716if (PROBE_LIMIT <= 0) return; // do not fill cache717// Add e to the cache.718Entry<?>[] cache = getCache();719int mask = (cache.length-1);720int home = classValue.hashCodeForCache & mask;721Entry<?> e2 = placeInCache(cache, home, e, false);722if (e2 == null) return; // done723if (PROBE_LIMIT > 1) {724// try to move e2 somewhere else in his probe range725int dis2 = entryDislocation(cache, home, e2);726int home2 = home - dis2;727for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) {728if (placeInCache(cache, i2 & mask, e2, true) == null) {729return;730}731}732}733// Note: At this point, e2 is just dropped from the cache.734}735736/** Store the given entry. Update cacheLoad, and return any live victim.737* 'Gently' means return self rather than dislocating a live victim.738*/739private Entry<?> placeInCache(Entry<?>[] cache, int pos, Entry<?> e, boolean gently) {740Entry<?> e2 = overwrittenEntry(cache[pos]);741if (gently && e2 != null) {742// do not overwrite a live entry743return e;744} else {745cache[pos] = e;746return e2;747}748}749750/** Note an entry that is about to be overwritten.751* If it is not live, quietly replace it by null.752* If it is an actual null, increment cacheLoad,753* because the caller is going to store something754* in its place.755*/756private <T> Entry<T> overwrittenEntry(Entry<T> e2) {757if (e2 == null) cacheLoad += 1;758else if (e2.isLive()) return e2;759return null;760}761762/** Percent loading of cache before resize. */763private static final int CACHE_LOAD_LIMIT = 67; // 0..100764/** Maximum number of probes to attempt. */765private static final int PROBE_LIMIT = 6; // 1..766// N.B. Set PROBE_LIMIT=0 to disable all fast paths.767}768}769770771