Skip to content

Commit 7688fc2

Browse files
committed
Implement Java 17-compatible DFU cache blaster
1 parent 20b3d8b commit 7688fc2

File tree

2 files changed

+67
-41
lines changed

2 files changed

+67
-41
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.dynamic_dfu;
2+
3+
import com.mojang.datafixers.DataFixer;
4+
import com.mojang.serialization.Dynamic;
5+
import net.minecraft.util.datafix.DataFixTypes;
6+
import org.embeddedt.modernfix.dfu.DFUBlaster;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
11+
12+
@Mixin(DataFixTypes.class)
13+
public class DataFixTypesMixin {
14+
@Inject(method = "update(Lcom/mojang/datafixers/DataFixer;Lcom/mojang/serialization/Dynamic;II)Lcom/mojang/serialization/Dynamic;", at = @At(value = "INVOKE", target = "Lcom/mojang/datafixers/DataFixer;update(Lcom/mojang/datafixers/DSL$TypeReference;Lcom/mojang/serialization/Dynamic;II)Lcom/mojang/serialization/Dynamic;"))
15+
private void kickOnUpdate(DataFixer fixer, Dynamic<?> input, int version, int newVersion, CallbackInfoReturnable<Dynamic<?>> cir) {
16+
if (version < newVersion) {
17+
DFUBlaster.kick();
18+
}
19+
}
20+
}

common/src/main/java/org/embeddedt/modernfix/dfu/DFUBlaster.java

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,51 @@
11
package org.embeddedt.modernfix.dfu;
22

3-
import com.google.common.cache.Cache;
4-
import com.google.common.cache.CacheBuilder;
5-
import com.mojang.datafixers.RewriteResult;
6-
import com.mojang.datafixers.TypeRewriteRule;
7-
import com.mojang.datafixers.functions.PointFreeRule;
8-
import com.mojang.datafixers.types.Type;
9-
import com.mojang.datafixers.util.Pair;
10-
import org.apache.commons.lang3.tuple.Triple;
113
import org.embeddedt.modernfix.ModernFix;
12-
import sun.misc.Unsafe;
134

145
import java.lang.reflect.Field;
15-
import java.util.Optional;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Map;
169
import java.util.concurrent.TimeUnit;
17-
import java.util.function.IntFunction;
10+
import java.util.concurrent.atomic.AtomicLong;
11+
import java.util.concurrent.locks.LockSupport;
1812

1913
public class DFUBlaster {
20-
private static final Cache<Pair<IntFunction<RewriteResult<?, ?>>, Integer>, RewriteResult<?, ?>> hmapApplyCache = CacheBuilder.newBuilder()
21-
.expireAfterAccess(3, TimeUnit.MINUTES)
22-
.build();
23-
private static final Cache<Triple<Type<?>, TypeRewriteRule, PointFreeRule>, Optional<? extends RewriteResult<?, ?>>> rewriteCache = CacheBuilder.newBuilder()
24-
.expireAfterAccess(3, TimeUnit.MINUTES)
25-
.build();
26-
public static void blastMaps() {
14+
private static final List<Map<?, ?>> TRACKED_MAPS = buildTrackedMaps();
15+
private static final long DELAY_TIME = TimeUnit.SECONDS.toNanos(60);
16+
private static final AtomicLong NEXT_WAKE_TIME = new AtomicLong(System.nanoTime() + DELAY_TIME);
17+
18+
private static List<Map<?, ?>> buildTrackedMaps() {
19+
var list = new ArrayList<Map<?, ?>>();
20+
tryAdd(list, "com.mojang.datafixers.DSL$Instances", "TAGGED_CHOICE_TYPE_CACHE");
21+
tryAdd(list, "com.mojang.datafixers.functions.Fold", "HMAP_APPLY_CACHE");
22+
tryAdd(list, "com.mojang.datafixers.types.Type", "REWRITE_CACHE");
23+
return list;
24+
}
25+
26+
private static void tryAdd(List<Map<?, ?>> list, String className, String fieldName) {
2727
try {
28-
Class<?> FOLD_CLASS = Class.forName("com.mojang.datafixers.functions.Fold");
29-
Field hmapField = FOLD_CLASS.getDeclaredField("HMAP_APPLY_CACHE");
30-
hmapField.setAccessible(true);
31-
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
32-
theUnsafe.setAccessible(true);
33-
Unsafe unsafe = (Unsafe)theUnsafe.get(null);
34-
Object base = unsafe.staticFieldBase(hmapField);
35-
long offset = unsafe.staticFieldOffset(hmapField);
36-
unsafe.putObject(base, offset, hmapApplyCache.asMap());
37-
Field rewriteCacheField = Type.class.getDeclaredField("REWRITE_CACHE");
38-
rewriteCacheField.setAccessible(true);
39-
base = unsafe.staticFieldBase(rewriteCacheField);
40-
offset = unsafe.staticFieldOffset(rewriteCacheField);
41-
unsafe.putObject(base, offset, rewriteCache.asMap());
42-
new CleanerThread().start();
43-
} catch(Throwable e) {
44-
ModernFix.LOGGER.error("Could not replace DFU map", e);
28+
Class<?> clz = Class.forName(className);
29+
Field field = clz.getDeclaredField(fieldName);
30+
field.setAccessible(true);
31+
if (Map.class.isAssignableFrom(field.getType())) {
32+
list.add((Map<?, ?>)field.get(null));
33+
} else {
34+
ModernFix.LOGGER.error("Field {} on class {} is not a map", field, className);
35+
}
36+
} catch (ReflectiveOperationException e) {
37+
ModernFix.LOGGER.error("Error tracking DFU field {} on class {}", fieldName, className, e);
4538
}
4639
}
4740

41+
public static void blastMaps() {
42+
new CleanerThread().start();
43+
}
44+
45+
public static void kick() {
46+
NEXT_WAKE_TIME.getAndAdd(DELAY_TIME);
47+
}
48+
4849
static class CleanerThread extends Thread {
4950
CleanerThread() {
5051
this.setName("DFU cleaning thread");
@@ -55,13 +56,18 @@ static class CleanerThread extends Thread {
5556
@Override
5657
public void run() {
5758
while(true) {
58-
try {
59-
Thread.sleep(15000);
60-
} catch(InterruptedException e){
61-
return;
59+
long waitTime = NEXT_WAKE_TIME.get() - System.nanoTime();
60+
if (waitTime > 0) {
61+
LockSupport.parkNanos(waitTime);
62+
}
63+
64+
long lastStamp = NEXT_WAKE_TIME.get();
65+
if (System.nanoTime() >= lastStamp) {
66+
// Nobody kicked the watchdog again, we should clear the maps
67+
TRACKED_MAPS.forEach(Map::clear);
68+
NEXT_WAKE_TIME.compareAndSet(lastStamp, System.nanoTime() + DELAY_TIME);
6269
}
63-
rewriteCache.cleanUp();
64-
hmapApplyCache.cleanUp();
70+
// Otherwise, we were told to wait for longer, so don't do anything
6571
}
6672
}
6773
}

0 commit comments

Comments
 (0)