Skip to content

Commit 6af0af5

Browse files
author
Jim Laskey
committed
8310913: Move ReferencedKeyMap to jdk.internal so it may be shared
Reviewed-by: naoto, rriggs, mchung, liach
1 parent 86783b9 commit 6af0af5

File tree

11 files changed

+537
-275
lines changed

11 files changed

+537
-275
lines changed

src/java.base/share/classes/java/lang/invoke/MethodType.java

Lines changed: 12 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
import java.lang.ref.WeakReference;
3434
import java.util.Arrays;
3535
import java.util.Collections;
36+
import java.util.function.Supplier;
3637
import java.util.List;
38+
import java.util.Map;
3739
import java.util.NoSuchElementException;
3840
import java.util.Objects;
3941
import java.util.Optional;
@@ -42,7 +44,8 @@
4244
import java.util.concurrent.ConcurrentMap;
4345
import java.util.stream.Stream;
4446

45-
import jdk.internal.access.SharedSecrets;
47+
import jdk.internal.util.ReferencedKeySet;
48+
import jdk.internal.util.ReferenceKey;
4649
import jdk.internal.vm.annotation.Stable;
4750
import sun.invoke.util.BytecodeDescriptor;
4851
import sun.invoke.util.VerifyType;
@@ -227,7 +230,13 @@ private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num
227230
return new IndexOutOfBoundsException(num.toString());
228231
}
229232

230-
static final ConcurrentWeakInternSet<MethodType> internTable = new ConcurrentWeakInternSet<>();
233+
static final ReferencedKeySet<MethodType> internTable =
234+
ReferencedKeySet.create(false, true, new Supplier<>() {
235+
@Override
236+
public Map<ReferenceKey<MethodType>, ReferenceKey<MethodType>> get() {
237+
return new ConcurrentHashMap<>(512);
238+
}
239+
});
231240

232241
static final Class<?>[] NO_PTYPES = {};
233242

@@ -405,7 +414,7 @@ private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean tr
405414
mt = new MethodType(rtype, ptypes);
406415
}
407416
mt.form = MethodTypeForm.findForm(mt);
408-
return internTable.add(mt);
417+
return internTable.intern(mt);
409418
}
410419
private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
411420

@@ -883,10 +892,6 @@ public Class<?>[] parameterArray() {
883892
* @param x object to compare
884893
* @see Object#equals(Object)
885894
*/
886-
// This implementation may also return true if x is a WeakEntry containing
887-
// a method type that is equal to this. This is an internal implementation
888-
// detail to allow for faster method type lookups.
889-
// See ConcurrentWeakInternSet.WeakEntry#equals(Object)
890895
@Override
891896
public boolean equals(Object x) {
892897
if (this == x) {
@@ -895,10 +900,6 @@ public boolean equals(Object x) {
895900
if (x instanceof MethodType mt) {
896901
return equals(mt);
897902
}
898-
if (x instanceof ConcurrentWeakInternSet.WeakEntry<?> e
899-
&& e.get() instanceof MethodType mt) {
900-
return equals(mt);
901-
}
902903
return false;
903904
}
904905

@@ -1390,112 +1391,4 @@ private Object readResolve() {
13901391
wrapAlt = null;
13911392
return mt;
13921393
}
1393-
1394-
/**
1395-
* Simple implementation of weak concurrent intern set.
1396-
*
1397-
* @param <T> interned type
1398-
*/
1399-
private static class ConcurrentWeakInternSet<T> {
1400-
1401-
private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
1402-
private final ReferenceQueue<T> stale;
1403-
1404-
public ConcurrentWeakInternSet() {
1405-
this.map = new ConcurrentHashMap<>(512);
1406-
this.stale = SharedSecrets.getJavaLangRefAccess().newNativeReferenceQueue();
1407-
}
1408-
1409-
/**
1410-
* Get the existing interned element.
1411-
* This method returns null if no element is interned.
1412-
*
1413-
* @param elem element to look up
1414-
* @return the interned element
1415-
*/
1416-
public T get(T elem) {
1417-
if (elem == null) throw new NullPointerException();
1418-
expungeStaleElements();
1419-
1420-
WeakEntry<T> value = map.get(elem);
1421-
if (value != null) {
1422-
T res = value.get();
1423-
if (res != null) {
1424-
return res;
1425-
}
1426-
}
1427-
return null;
1428-
}
1429-
1430-
/**
1431-
* Interns the element.
1432-
* Always returns non-null element, matching the one in the intern set.
1433-
* Under the race against another add(), it can return <i>different</i>
1434-
* element, if another thread beats us to interning it.
1435-
*
1436-
* @param elem element to add
1437-
* @return element that was actually added
1438-
*/
1439-
public T add(T elem) {
1440-
if (elem == null) throw new NullPointerException();
1441-
1442-
// Playing double race here, and so spinloop is required.
1443-
// First race is with two concurrent updaters.
1444-
// Second race is with GC purging weak ref under our feet.
1445-
// Hopefully, we almost always end up with a single pass.
1446-
T interned;
1447-
WeakEntry<T> e = new WeakEntry<>(elem, stale);
1448-
do {
1449-
expungeStaleElements();
1450-
WeakEntry<T> exist = map.putIfAbsent(e, e);
1451-
interned = (exist == null) ? elem : exist.get();
1452-
} while (interned == null);
1453-
return interned;
1454-
}
1455-
1456-
private void expungeStaleElements() {
1457-
Reference<? extends T> reference;
1458-
while ((reference = stale.poll()) != null) {
1459-
map.remove(reference);
1460-
}
1461-
}
1462-
1463-
private static class WeakEntry<T> extends WeakReference<T> {
1464-
1465-
public final int hashcode;
1466-
1467-
public WeakEntry(T key, ReferenceQueue<T> queue) {
1468-
super(key, queue);
1469-
hashcode = key.hashCode();
1470-
}
1471-
1472-
/**
1473-
* This implementation returns {@code true} if {@code obj} is another
1474-
* {@code WeakEntry} whose referent is equal to this referent, or
1475-
* if {@code obj} is equal to the referent of this. This allows
1476-
* lookups to be made without wrapping in a {@code WeakEntry}.
1477-
*
1478-
* @param obj the object to compare
1479-
* @return true if {@code obj} is equal to this or the referent of this
1480-
* @see MethodType#equals(Object)
1481-
* @see Object#equals(Object)
1482-
*/
1483-
@Override
1484-
public boolean equals(Object obj) {
1485-
Object mine = get();
1486-
if (obj instanceof WeakEntry<?> we) {
1487-
Object that = we.get();
1488-
return (that == null || mine == null) ? (this == obj) : mine.equals(that);
1489-
}
1490-
return (mine == null) ? (obj == null) : mine.equals(obj);
1491-
}
1492-
1493-
@Override
1494-
public int hashCode() {
1495-
return hashcode;
1496-
}
1497-
1498-
}
1499-
}
1500-
15011394
}

src/java.base/share/classes/java/lang/runtime/Carriers.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.concurrent.ConcurrentHashMap;
3636

3737
import jdk.internal.misc.Unsafe;
38+
import jdk.internal.util.ReferencedKeyMap;
3839

3940
import static java.lang.invoke.MethodType.methodType;
4041

@@ -366,7 +367,7 @@ MethodHandle[] createComponents(CarrierShape carrierShape) {
366367
* Cache mapping {@link MethodType} to previously defined {@link CarrierElements}.
367368
*/
368369
private static final Map<MethodType, CarrierElements>
369-
methodTypeCache = ReferencedKeyMap.create(ConcurrentHashMap::new);
370+
methodTypeCache = ReferencedKeyMap.create(false, ConcurrentHashMap::new);
370371

371372
/**
372373
* Permute a raw constructor and component accessor {@link MethodHandle MethodHandles} to

src/java.base/share/classes/jdk/internal/access/JavaLangRefAccess.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public interface JavaLangRefAccess {
5454
/**
5555
* Constructs a new NativeReferenceQueue.
5656
*
57-
* Invoked by MethodType.ConcurrentWeakInternSet
57+
* Invoked by jdk.internal.util.ReferencedKeyMap
5858
*/
5959
<T> ReferenceQueue<T> newNativeReferenceQueue();
6060
}

src/java.base/share/classes/java/lang/runtime/ReferenceKey.java renamed to src/java.base/share/classes/jdk/internal/util/ReferenceKey.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,9 @@
2323
* questions.
2424
*/
2525

26-
package java.lang.runtime;
26+
package jdk.internal.util;
2727

28-
import java.lang.ref.ReferenceQueue;
29-
import java.lang.ref.SoftReference;
30-
import java.lang.ref.WeakReference;
31-
import java.util.Objects;
28+
import java.lang.ref.Reference;
3229

3330
/**
3431
* View/wrapper of keys used by the backing {@link ReferencedKeyMap}.
@@ -39,11 +36,8 @@
3936
* @param <T> key type
4037
*
4138
* @since 21
42-
*
43-
* Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
44-
* Do not rely on its availability.
4539
*/
46-
sealed interface ReferenceKey<T> permits StrongReferenceKey, WeakReferenceKey, SoftReferenceKey {
40+
public sealed interface ReferenceKey<T> permits StrongReferenceKey, WeakReferenceKey, SoftReferenceKey {
4741
/**
4842
* {@return the value of the unwrapped key}
4943
*/

0 commit comments

Comments
 (0)