mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8310913: Move ReferencedKeyMap to jdk.internal so it may be shared
Reviewed-by: naoto, rriggs, mchung, liach
This commit is contained in:
parent
86783b9851
commit
6af0af5934
11 changed files with 537 additions and 275 deletions
|
@ -33,7 +33,9 @@ import java.lang.ref.ReferenceQueue;
|
|||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -42,7 +44,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.util.ReferencedKeySet;
|
||||
import jdk.internal.util.ReferenceKey;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.invoke.util.BytecodeDescriptor;
|
||||
import sun.invoke.util.VerifyType;
|
||||
|
@ -227,7 +230,13 @@ class MethodType
|
|||
return new IndexOutOfBoundsException(num.toString());
|
||||
}
|
||||
|
||||
static final ConcurrentWeakInternSet<MethodType> internTable = new ConcurrentWeakInternSet<>();
|
||||
static final ReferencedKeySet<MethodType> internTable =
|
||||
ReferencedKeySet.create(false, true, new Supplier<>() {
|
||||
@Override
|
||||
public Map<ReferenceKey<MethodType>, ReferenceKey<MethodType>> get() {
|
||||
return new ConcurrentHashMap<>(512);
|
||||
}
|
||||
});
|
||||
|
||||
static final Class<?>[] NO_PTYPES = {};
|
||||
|
||||
|
@ -405,7 +414,7 @@ class MethodType
|
|||
mt = new MethodType(rtype, ptypes);
|
||||
}
|
||||
mt.form = MethodTypeForm.findForm(mt);
|
||||
return internTable.add(mt);
|
||||
return internTable.intern(mt);
|
||||
}
|
||||
private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
|
||||
|
||||
|
@ -883,10 +892,6 @@ class MethodType
|
|||
* @param x object to compare
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
// This implementation may also return true if x is a WeakEntry containing
|
||||
// a method type that is equal to this. This is an internal implementation
|
||||
// detail to allow for faster method type lookups.
|
||||
// See ConcurrentWeakInternSet.WeakEntry#equals(Object)
|
||||
@Override
|
||||
public boolean equals(Object x) {
|
||||
if (this == x) {
|
||||
|
@ -895,10 +900,6 @@ class MethodType
|
|||
if (x instanceof MethodType mt) {
|
||||
return equals(mt);
|
||||
}
|
||||
if (x instanceof ConcurrentWeakInternSet.WeakEntry<?> e
|
||||
&& e.get() instanceof MethodType mt) {
|
||||
return equals(mt);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1390,112 +1391,4 @@ s.writeObject(this.parameterArray());
|
|||
wrapAlt = null;
|
||||
return mt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple implementation of weak concurrent intern set.
|
||||
*
|
||||
* @param <T> interned type
|
||||
*/
|
||||
private static class ConcurrentWeakInternSet<T> {
|
||||
|
||||
private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
|
||||
private final ReferenceQueue<T> stale;
|
||||
|
||||
public ConcurrentWeakInternSet() {
|
||||
this.map = new ConcurrentHashMap<>(512);
|
||||
this.stale = SharedSecrets.getJavaLangRefAccess().newNativeReferenceQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the existing interned element.
|
||||
* This method returns null if no element is interned.
|
||||
*
|
||||
* @param elem element to look up
|
||||
* @return the interned element
|
||||
*/
|
||||
public T get(T elem) {
|
||||
if (elem == null) throw new NullPointerException();
|
||||
expungeStaleElements();
|
||||
|
||||
WeakEntry<T> value = map.get(elem);
|
||||
if (value != null) {
|
||||
T res = value.get();
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interns the element.
|
||||
* Always returns non-null element, matching the one in the intern set.
|
||||
* Under the race against another add(), it can return <i>different</i>
|
||||
* element, if another thread beats us to interning it.
|
||||
*
|
||||
* @param elem element to add
|
||||
* @return element that was actually added
|
||||
*/
|
||||
public T add(T elem) {
|
||||
if (elem == null) throw new NullPointerException();
|
||||
|
||||
// Playing double race here, and so spinloop is required.
|
||||
// First race is with two concurrent updaters.
|
||||
// Second race is with GC purging weak ref under our feet.
|
||||
// Hopefully, we almost always end up with a single pass.
|
||||
T interned;
|
||||
WeakEntry<T> e = new WeakEntry<>(elem, stale);
|
||||
do {
|
||||
expungeStaleElements();
|
||||
WeakEntry<T> exist = map.putIfAbsent(e, e);
|
||||
interned = (exist == null) ? elem : exist.get();
|
||||
} while (interned == null);
|
||||
return interned;
|
||||
}
|
||||
|
||||
private void expungeStaleElements() {
|
||||
Reference<? extends T> reference;
|
||||
while ((reference = stale.poll()) != null) {
|
||||
map.remove(reference);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WeakEntry<T> extends WeakReference<T> {
|
||||
|
||||
public final int hashcode;
|
||||
|
||||
public WeakEntry(T key, ReferenceQueue<T> queue) {
|
||||
super(key, queue);
|
||||
hashcode = key.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns {@code true} if {@code obj} is another
|
||||
* {@code WeakEntry} whose referent is equal to this referent, or
|
||||
* if {@code obj} is equal to the referent of this. This allows
|
||||
* lookups to be made without wrapping in a {@code WeakEntry}.
|
||||
*
|
||||
* @param obj the object to compare
|
||||
* @return true if {@code obj} is equal to this or the referent of this
|
||||
* @see MethodType#equals(Object)
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
Object mine = get();
|
||||
if (obj instanceof WeakEntry<?> we) {
|
||||
Object that = we.get();
|
||||
return (that == null || mine == null) ? (this == obj) : mine.equals(that);
|
||||
}
|
||||
return (mine == null) ? (obj == null) : mine.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue