Rewrite clear_mixin_classinfo, now more aggressive

This commit is contained in:
embeddedt 2023-07-05 20:01:43 -04:00
parent 095b9c3277
commit c6cb0acd3c
No known key found for this signature in database
GPG Key ID: A69433EC199B5613

View File

@ -1,30 +1,73 @@
package org.embeddedt.modernfix.util; package org.embeddedt.modernfix.util;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import org.spongepowered.asm.mixin.transformer.ClassInfo; import org.spongepowered.asm.mixin.transformer.ClassInfo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map; import java.util.Map;
public class ClassInfoManager { public class ClassInfoManager {
private static Map<String, ClassInfo> classInfoCache = null; private static boolean hasRun = false;
public static void clear() { public static void clear() {
if(!ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_mixin_classinfo.ClassInfoManager")) if (!ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_mixin_classinfo.ClassInfoManager") || hasRun)
return; return;
if(classInfoCache == null) { hasRun = true;
ModernFix.resourceReloadExecutor().execute(ClassInfoManager::doClear);
}
private static Field accessible(Field f) {
f.setAccessible(true);
return f;
}
private static void doClear() {
Map<String, ClassInfo> classInfoCache;
Field mixinField, stateField, classNodeField, methodsField, fieldsField;
Class<?> stateClz;
try { try {
Field field = ClassInfo.class.getDeclaredField("cache"); Field field = accessible(ClassInfo.class.getDeclaredField("cache"));
field.setAccessible(true); classInfoCache = (Map<String, ClassInfo>) field.get(null);
classInfoCache = (Map<String, ClassInfo>)field.get(null); mixinField = accessible(ClassInfo.class.getDeclaredField("mixin"));
} catch(ReflectiveOperationException | RuntimeException e) { methodsField = accessible(ClassInfo.class.getDeclaredField("methods"));
fieldsField = accessible(ClassInfo.class.getDeclaredField("fields"));
stateClz = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo$State");
stateField = accessible(Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo").getDeclaredField("state"));
classNodeField = accessible(stateClz.getDeclaredField("classNode"));
} catch (ReflectiveOperationException | RuntimeException e) {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
} MixinEnvironment.getDefaultEnvironment().audit();
try { try {
classInfoCache.entrySet().removeIf(entry -> !entry.getKey().equals("java/lang/Object") && (entry.getValue() == null || !entry.getValue().isMixin())); ClassNode emptyNode = new ClassNode();
} catch(RuntimeException e) { classInfoCache.entrySet().removeIf(entry -> {
if(entry.getKey().equals("java/lang/Object"))
return false;
ClassInfo mixinClz = entry.getValue();
try {
if(mixinClz.isMixin()) {
// clear classNode in MixinInfo.State
IMixinInfo theInfo = (IMixinInfo) mixinField.get(mixinClz);
Object state = stateField.get(theInfo);
if (state != null)
classNodeField.set(state, emptyNode);
}
// clear fields, methods
((Collection<?>)methodsField.get(mixinClz)).clear();
((Collection<?>)fieldsField.get(mixinClz)).clear();
} catch (ReflectiveOperationException | RuntimeException e) {
e.printStackTrace(); e.printStackTrace();
} }
return true;
});
} catch (RuntimeException e) {
e.printStackTrace();
}
ModernFix.LOGGER.warn("Cleared mixin data structures");
} }
} }