Skip to content

Commit 05de6e9

Browse files
committed
wip
1 parent 0079d1a commit 05de6e9

18 files changed

+228
-151
lines changed

hypo-types/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ val typesExport = project(":types-export")
3535
tasks.test {
3636
dependsOn(typesExport.tasks.named("buildTypesExport"))
3737

38+
// systemProperty("hypo.interning.disabled", "true")
3839
val zipFile = typesExport.layout.buildDirectory.file("types-export/types-export.zip").get().asFile.absolutePath
3940
systemProperty("hypo.types.zip", zipFile)
4041
}

hypo-types/src/main/java/dev/denwav/hypo/types/Intern.java

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,110 @@
1818

1919
package dev.denwav.hypo.types;
2020

21+
import java.lang.ref.Reference;
2122
import java.lang.ref.WeakReference;
22-
import java.util.WeakHashMap;
23+
import java.util.ArrayList;
24+
import java.util.IdentityHashMap;
25+
import java.util.List;
26+
import java.util.concurrent.ConcurrentHashMap;
27+
import java.util.concurrent.atomic.AtomicLong;
2328
import org.jetbrains.annotations.NotNull;
29+
import org.jetbrains.annotations.Nullable;
2430

2531
public abstract class Intern<T extends Intern<T>> implements TypeRepresentable {
2632

27-
private final Object lock = new Object();
28-
private final @NotNull WeakHashMap<T, WeakReference<T>> internment;
33+
private static final IdentityHashMap<ConcurrentHashMap<String, WeakReference<?>>, AtomicLong> interns = new IdentityHashMap<>();
34+
private static final List<ConcurrentHashMap<String, WeakReference<?>>> newInterns = new ArrayList<>();
35+
static {
36+
final Thread t = new Thread(() -> {
37+
while (true) {
38+
try {
39+
//noinspection BusyWait
40+
Thread.sleep(500);
41+
} catch (final InterruptedException e) {
42+
break;
43+
}
44+
for (final var entry : interns.entrySet()) {
45+
final var map = entry.getKey();
46+
final AtomicLong lastSize = entry.getValue();
47+
if (Math.abs(map.mappingCount() - lastSize.get()) < 10_000) {
48+
System.out.println("SKIPPED");
49+
continue;
50+
}
51+
map.values().removeIf(r -> r.get() == null);
52+
lastSize.set(map.mappingCount());
53+
}
2954

30-
protected Intern(final @NotNull WeakHashMap<T, WeakReference<T>> internment) {
31-
this.internment = internment;
55+
// Prevent CME
56+
if (!newInterns.isEmpty()) {
57+
synchronized (newInterns) {
58+
for (final var newIntern : newInterns) {
59+
interns.put(newIntern, new AtomicLong(0));
60+
}
61+
newInterns.clear();
62+
}
63+
}
64+
}
65+
}, "Interning Cleanup");
66+
t.setDaemon(true);
67+
t.start();
68+
}
69+
70+
private static final class InternClassValue extends ClassValue<ConcurrentHashMap<String, WeakReference<?>>> {
71+
@Override
72+
protected ConcurrentHashMap<String, WeakReference<?>> computeValue(final @NotNull Class<?> type) {
73+
final ConcurrentHashMap<String, WeakReference<?>> map = new ConcurrentHashMap<>();
74+
synchronized (newInterns) {
75+
newInterns.add(map);
76+
}
77+
return map;
78+
}
3279
}
3380

81+
private static final InternClassValue internment = new InternClassValue();
82+
83+
private static final boolean interningDisabled = Boolean.getBoolean("hypo.interning.disabled");
84+
3485
public final T intern() {
35-
synchronized (this.lock) {
36-
final T t = HypoTypesUtil.cast(this);
37-
WeakReference<T> ref = this.internment.get(t);
38-
if (ref != null) {
39-
return ref.get();
86+
if (interningDisabled) {
87+
return HypoTypesUtil.cast(this);
88+
}
89+
90+
final T t = HypoTypesUtil.cast(this);
91+
try {
92+
final ConcurrentHashMap<String, WeakReference<?>> map = internment.get(this.getClass());
93+
final String key = t.asInternal();
94+
final WeakReference<T> ref = new WeakReference<>(t);
95+
final T res = HypoTypesUtil.cast(map.computeIfAbsent(key, k -> ref).get());
96+
if (res != null) {
97+
return res;
4098
}
41-
this.internment.put(t, new WeakReference<>(t));
99+
100+
map.put(key, ref);
42101
return t;
102+
} finally {
103+
Reference.reachabilityFence(t);
104+
}
105+
}
106+
107+
@SuppressWarnings("TypeParameterUnusedInFormals")
108+
public static <T> @Nullable T tryFind(final @NotNull Class<?> c, final @NotNull String key) {
109+
final WeakReference<?> ref = internment.get(c).get(key);
110+
if (ref == null) {
111+
return null;
43112
}
113+
final Object r = ref.get();
114+
try {
115+
if (r != null) {
116+
return HypoTypesUtil.cast(r);
117+
}
118+
return null;
119+
} finally {
120+
Reference.reachabilityFence(r);
121+
}
122+
}
123+
124+
public static long internmentSize(final @NotNull Class<?> c) {
125+
return internment.get(c).mappingCount();
44126
}
45127
}

hypo-types/src/main/java/dev/denwav/hypo/types/desc/ArrayTypeDescriptor.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@
2323
import java.lang.ref.WeakReference;
2424
import java.util.Objects;
2525
import java.util.WeakHashMap;
26+
import java.util.concurrent.ConcurrentHashMap;
2627
import org.jetbrains.annotations.NotNull;
2728

2829
public final class ArrayTypeDescriptor extends Intern<ArrayTypeDescriptor> implements TypeDescriptor {
2930

30-
private static final WeakHashMap<ArrayTypeDescriptor, WeakReference<ArrayTypeDescriptor>> internment =
31-
new WeakHashMap<>();
32-
3331
private final int dimension;
3432
private final @NotNull TypeDescriptor baseType;
3533

@@ -41,7 +39,6 @@ private ArrayTypeDescriptor(
4139
final int dimension,
4240
final @NotNull TypeDescriptor baseType
4341
) {
44-
super(internment);
4542
this.dimension = dimension;
4643
this.baseType = baseType;
4744
}

hypo-types/src/main/java/dev/denwav/hypo/types/desc/ClassTypeDescriptor.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,18 @@
2424
import java.lang.ref.WeakReference;
2525
import java.util.Objects;
2626
import java.util.WeakHashMap;
27+
import java.util.concurrent.ConcurrentHashMap;
2728
import org.jetbrains.annotations.NotNull;
2829

2930
public final class ClassTypeDescriptor extends Intern<ClassTypeDescriptor> implements TypeDescriptor {
3031

31-
private static final WeakHashMap<ClassTypeDescriptor, WeakReference<ClassTypeDescriptor>> internment =
32-
new WeakHashMap<>();
33-
3432
private final @NotNull String name;
3533

3634
public static @NotNull ClassTypeDescriptor of(final @NotNull String name) {
3735
return new ClassTypeDescriptor(HypoTypesUtil.normalizedClassName(name)).intern();
3836
}
3937

4038
private ClassTypeDescriptor(final @NotNull String name) {
41-
super(internment);
4239
this.name = name;
4340
}
4441

hypo-types/src/main/java/dev/denwav/hypo/types/desc/MethodDescriptor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,20 @@
2121
import dev.denwav.hypo.types.Intern;
2222
import dev.denwav.hypo.types.TypeRepresentable;
2323
import dev.denwav.hypo.types.parsing.JvmTypeParser;
24+
import dev.denwav.hypo.types.sig.ClassTypeSignature;
2425
import dev.denwav.hypo.types.sig.MethodSignature;
2526
import dev.denwav.hypo.types.sig.TypeSignature;
2627
import java.lang.ref.WeakReference;
2728
import java.util.Collections;
2829
import java.util.List;
2930
import java.util.Objects;
3031
import java.util.WeakHashMap;
32+
import java.util.concurrent.ConcurrentHashMap;
3133
import java.util.stream.Collectors;
3234
import org.jetbrains.annotations.NotNull;
3335

3436
public final class MethodDescriptor extends Intern<MethodDescriptor> implements TypeRepresentable {
3537

36-
private static final WeakHashMap<MethodDescriptor, WeakReference<MethodDescriptor>> internment =
37-
new WeakHashMap<>();
38-
3938
final @NotNull List<? extends TypeDescriptor> parameters;
4039
final @NotNull TypeDescriptor returnType;
4140

@@ -50,14 +49,19 @@ public final class MethodDescriptor extends Intern<MethodDescriptor> implements
5049
return parse(text, 0);
5150
}
5251
public static @NotNull MethodDescriptor parse(final String text, final int from) {
52+
if (text.length() > 1 && from == 0) {
53+
final MethodDescriptor r = Intern.tryFind(MethodDescriptor.class, text);
54+
if (r != null) {
55+
return r;
56+
}
57+
}
5358
return JvmTypeParser.parseMethodDescriptor(text, from);
5459
}
5560

5661
private MethodDescriptor(
5762
final @NotNull List<? extends TypeDescriptor> parameters,
5863
final @NotNull TypeDescriptor returnType
5964
) {
60-
super(internment);
6165
this.parameters = List.copyOf(parameters);
6266
this.returnType = returnType;
6367
}

hypo-types/src/main/java/dev/denwav/hypo/types/desc/TypeDescriptor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package dev.denwav.hypo.types.desc;
2020

21+
import dev.denwav.hypo.types.Intern;
2122
import dev.denwav.hypo.types.TypeRepresentable;
2223
import dev.denwav.hypo.types.parsing.JvmTypeParser;
2324
import dev.denwav.hypo.types.sig.TypeSignature;
@@ -31,6 +32,12 @@ public interface TypeDescriptor extends TypeRepresentable {
3132
return parse(text, 0);
3233
}
3334
static @NotNull TypeDescriptor parse(final @NotNull String text, final int from) {
35+
if (text.length() > 1 && from == 0) {
36+
final TypeDescriptor r = Intern.tryFind(ClassTypeDescriptor.class, text);
37+
if (r != null) {
38+
return r;
39+
}
40+
}
3441
return JvmTypeParser.parseTypeDescriptor(text, from);
3542
}
3643
}

hypo-types/src/main/java/dev/denwav/hypo/types/sig/ArrayTypeSignature.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@
2424
import java.lang.ref.WeakReference;
2525
import java.util.Objects;
2626
import java.util.WeakHashMap;
27+
import java.util.concurrent.ConcurrentHashMap;
2728
import org.jetbrains.annotations.NotNull;
2829

2930
public final class ArrayTypeSignature
3031
extends Intern<ArrayTypeSignature>
3132
implements ReferenceTypeSignature {
3233

33-
private static final WeakHashMap<ArrayTypeSignature, WeakReference<ArrayTypeSignature>> internment =
34-
new WeakHashMap<>();
35-
3634
private final int dimension;
3735
private final @NotNull TypeSignature baseType;
3836

@@ -41,7 +39,6 @@ public final class ArrayTypeSignature
4139
}
4240

4341
private ArrayTypeSignature(final int dimension, final @NotNull TypeSignature baseType) {
44-
super(internment);
4542
this.dimension = dimension;
4643
this.baseType = baseType;
4744
}

hypo-types/src/main/java/dev/denwav/hypo/types/sig/ClassSignature.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@
2727
import java.util.List;
2828
import java.util.Objects;
2929
import java.util.WeakHashMap;
30+
import java.util.concurrent.ConcurrentHashMap;
3031
import java.util.stream.Collectors;
3132
import org.jetbrains.annotations.NotNull;
3233

3334
public final class ClassSignature extends Intern<ClassSignature> implements TypeRepresentable {
3435

35-
private static final WeakHashMap<ClassSignature, WeakReference<ClassSignature>> internment = new WeakHashMap<>();
36-
3736
private final @NotNull List<? extends TypeParameter> typeParameters;
3837
private final @NotNull ClassTypeSignature superClass;
3938
private final @NotNull List<? extends ClassTypeSignature> superInterfaces;
@@ -58,7 +57,6 @@ private ClassSignature(
5857
final @NotNull ClassTypeSignature superClass,
5958
final @NotNull List<? extends ClassTypeSignature> superInterfaces
6059
) {
61-
super(internment);
6260
this.typeParameters = List.copyOf(typeParameters);
6361
this.superClass = superClass;
6462
this.superInterfaces = List.copyOf(superInterfaces);

hypo-types/src/main/java/dev/denwav/hypo/types/sig/ClassTypeSignature.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.List;
2929
import java.util.Objects;
3030
import java.util.WeakHashMap;
31+
import java.util.concurrent.ConcurrentHashMap;
3132
import java.util.stream.Collectors;
3233
import org.jetbrains.annotations.NotNull;
3334
import org.jetbrains.annotations.Nullable;
@@ -36,9 +37,6 @@ public final class ClassTypeSignature
3637
extends Intern<ClassTypeSignature>
3738
implements ReferenceTypeSignature, ThrowsSignature {
3839

39-
private static final WeakHashMap<ClassTypeSignature, WeakReference<ClassTypeSignature>> internment =
40-
new WeakHashMap<>();
41-
4240
private final @Nullable ClassTypeSignature parentClass;
4341
private final @NotNull String name;
4442
private final @NotNull List<? extends TypeArgument> typeArguments;
@@ -69,7 +67,6 @@ private ClassTypeSignature(
6967
final @NotNull String name,
7068
final @Nullable List<? extends TypeArgument> typeArguments
7169
) {
72-
super(internment);
7370
this.parentClass = parentClass;
7471
this.name = name;
7572
if (typeArguments == null) {

hypo-types/src/main/java/dev/denwav/hypo/types/sig/MethodSignature.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,12 @@
2929
import java.util.List;
3030
import java.util.Objects;
3131
import java.util.WeakHashMap;
32+
import java.util.concurrent.ConcurrentHashMap;
3233
import java.util.stream.Collectors;
3334
import org.jetbrains.annotations.NotNull;
3435

3536
public final class MethodSignature extends Intern<MethodSignature> implements TypeRepresentable {
3637

37-
private static final WeakHashMap<MethodSignature, WeakReference<MethodSignature>> internment = new WeakHashMap<>();
38-
3938
private final @NotNull List<? extends TypeParameter> typeParameters;
4039
private final @NotNull List<? extends TypeSignature> parameters;
4140
private final @NotNull TypeSignature returnType;
@@ -56,7 +55,6 @@ private MethodSignature(
5655
final @NotNull TypeSignature returnType,
5756
final @NotNull List<? extends ThrowsSignature> throwsSignatures
5857
) {
59-
super(internment);
6058
this.typeParameters = List.copyOf(typeParameters);
6159
this.parameters = List.copyOf(parameters);
6260
this.returnType = returnType;
@@ -67,6 +65,12 @@ private MethodSignature(
6765
return parse(text, 0);
6866
}
6967
public static @NotNull MethodSignature parse(final @NotNull String text, final int from) {
68+
if (text.length() > 1 && from == 0) {
69+
final MethodSignature r = Intern.tryFind(MethodSignature.class, text);
70+
if (r != null) {
71+
return r;
72+
}
73+
}
7074
return JvmTypeParser.parseMethodSignature(text, from);
7175
}
7276

0 commit comments

Comments
 (0)