From bd5772cbcecbf26394a203616f068a7ea3f3d4b5 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Mon, 27 May 2024 14:34:34 +0200 Subject: [PATCH] more efficient turbo transformer --- .../transformers/ConfigOrderTransformer.java | 7 ++- .../transformers/MixinPluginTransformer.java | 43 ++++++++++++++----- .../TypeDiscovererModuleInfoSilencer.java | 7 +-- .../lib/turboasm/TransformerUtil.java | 18 +++++--- .../lib/turboasm/TurboClassTransformer.java | 4 +- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/falsepattern/lib/internal/asm/transformers/ConfigOrderTransformer.java b/src/main/java/com/falsepattern/lib/internal/asm/transformers/ConfigOrderTransformer.java index 068a851..c894820 100644 --- a/src/main/java/com/falsepattern/lib/internal/asm/transformers/ConfigOrderTransformer.java +++ b/src/main/java/com/falsepattern/lib/internal/asm/transformers/ConfigOrderTransformer.java @@ -64,11 +64,12 @@ public class ConfigOrderTransformer implements TurboClassTransformer { } @Override - public void transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { + public boolean transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { val cn = classNode.getNode(); if (cn == null) - return; + return false; int order = 0; + boolean changed = false; outer: for (val field : cn.fields) { if ((field.access & Opcodes.ACC_PUBLIC) == 0 @@ -85,6 +86,8 @@ public class ConfigOrderTransformer implements TurboClassTransformer { val annVisitor = field.visitAnnotation(DESC_ORDER, true); annVisitor.visit("value", order++); annVisitor.visitEnd(); + changed = true; } + return changed; } } diff --git a/src/main/java/com/falsepattern/lib/internal/asm/transformers/MixinPluginTransformer.java b/src/main/java/com/falsepattern/lib/internal/asm/transformers/MixinPluginTransformer.java index a6055b7..19ed089 100644 --- a/src/main/java/com/falsepattern/lib/internal/asm/transformers/MixinPluginTransformer.java +++ b/src/main/java/com/falsepattern/lib/internal/asm/transformers/MixinPluginTransformer.java @@ -73,32 +73,43 @@ public class MixinPluginTransformer implements TurboClassTransformer { if (IMIXINPLUGIN.equals(className) || IMIXINCONFIGPLUGIN.equals(className)) return true; + + if (!classNode.isPresent()) + return false; + if (classNode.isOriginal()) { val meta = classNode.getOriginalMetadata(); if (meta != null && meta.interfacesCount == 0) return false; } + val cn = classNode.getNode(); if (cn == null) return false; - return cn.interfaces.stream() - .anyMatch((i) -> IMIXINPLUGIN_INTERNAL.equals(i) || - IMIXINCONFIGPLUGIN_INTERNAL.equals(i)); + + for (String i : cn.interfaces) { + if (IMIXINPLUGIN_INTERNAL.equals(i) || IMIXINCONFIGPLUGIN_INTERNAL.equals(i)) { + return true; + } + } + + return false; } @Override - public void transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { + public boolean transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { val cn = classNode.getNode(); if (cn == null) - return; + return false; if (IMIXINCONFIGPLUGIN.equals(className)) { - extractMixinConfigPluginData(cn); + return extractMixinConfigPluginData(cn); } else { - transformPlugin(cn); + return transformPlugin(cn); } } - private static void extractMixinConfigPluginData(ClassNode cn) { + private static boolean extractMixinConfigPluginData(ClassNode cn) { + boolean changed = false; for (val method : cn.methods) { switch (method.name) { case "preApply": @@ -114,29 +125,39 @@ public class MixinPluginTransformer implements TurboClassTransformer { for (val local : method.localVariables) { if (local.desc.contains("ClassNode;")) { local.desc = local.desc.replaceAll("L[a-zA-Z/$]+[a-zA-Z$]+/ClassNode;", CLASSNODE_REAL); + changed = true; } } } } + return changed; } - private static void transformPlugin(ClassNode cn) { + private static boolean transformPlugin(ClassNode cn) { if (PREAPPLY_DESC == null) { PREAPPLY_DESC = extractMethodWithReflection("preApply"); } if (POSTAPPLY_DESC == null) { POSTAPPLY_DESC = extractMethodWithReflection("postApply"); } + boolean changed = false; for (val method : cn.methods) { switch (method.name) { case "preApply": - method.desc = PREAPPLY_DESC; + if (!PREAPPLY_DESC.equals(method.desc)) { + method.desc = PREAPPLY_DESC; + changed = true; + } break; case "postApply": - method.desc = POSTAPPLY_DESC; + if (!POSTAPPLY_DESC.equals(method.desc)) { + method.desc = POSTAPPLY_DESC; + changed = true; + } break; } } + return changed; } private static String extractMethodWithReflection(String m) { diff --git a/src/main/java/com/falsepattern/lib/internal/asm/transformers/TypeDiscovererModuleInfoSilencer.java b/src/main/java/com/falsepattern/lib/internal/asm/transformers/TypeDiscovererModuleInfoSilencer.java index 21d0482..a93feea 100644 --- a/src/main/java/com/falsepattern/lib/internal/asm/transformers/TypeDiscovererModuleInfoSilencer.java +++ b/src/main/java/com/falsepattern/lib/internal/asm/transformers/TypeDiscovererModuleInfoSilencer.java @@ -48,10 +48,10 @@ public class TypeDiscovererModuleInfoSilencer implements TurboClassTransformer { } @Override - public void transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { + public boolean transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode) { val cn = classNode.getNode(); if (cn == null) - return; + return false; for (val method : cn.methods) { if (!method.name.equals("")) { continue; @@ -63,10 +63,11 @@ public class TypeDiscovererModuleInfoSilencer implements TurboClassTransformer { val ldc = (LdcInsnNode) insn; if (ldc.cst.equals("[^\\s\\$]+(\\$[^\\s]+)?\\.class$")) { ldc.cst = "(?!module-info)[^\\s\\$]+(\\$[^\\s]+)?\\.class$"; - return; + return true; } } } } + return false; } } diff --git a/src/main/java/com/falsepattern/lib/turboasm/TransformerUtil.java b/src/main/java/com/falsepattern/lib/turboasm/TransformerUtil.java index b59a98b..1cf6e35 100644 --- a/src/main/java/com/falsepattern/lib/turboasm/TransformerUtil.java +++ b/src/main/java/com/falsepattern/lib/turboasm/TransformerUtil.java @@ -32,22 +32,26 @@ import java.util.List; public class TransformerUtil { private static final Logger LOG = LogManager.getLogger("ASM"); public static boolean executeTransformers(String transformedName, ClassNodeHandle handle, List transformers) { - boolean didTransformation = false; + boolean modified = false; for (val transformer: transformers) { try { if (transformer.shouldTransformClass(transformedName, handle)) { - if (!didTransformation) { - LOG.debug("Transforming {}!", transformedName); + LOG.trace("Transforming {} with {}, owner: {}", transformedName, transformer.name(), transformer.owner()); + if (transformer.transformClass(transformedName, handle)) { + LOG.trace("Transformed."); + modified = true; + } else { + LOG.trace("No change."); } - didTransformation = true; - transformer.transformClass(transformedName, handle); - LOG.debug("Successfully transformed class {} with {}, owner: {}", transformedName, transformer.name(), transformer.owner()); } } catch (Exception e) { LOG.error("Failed to transform class {} with {}, owner: {}", transformedName, transformer.name(), transformer.owner()); LOG.error("Exception stacktrace:", e); } } - return didTransformation; + if (modified) { + LOG.trace("Transformed class {}", transformedName); + } + return modified; } } diff --git a/src/main/java/com/falsepattern/lib/turboasm/TurboClassTransformer.java b/src/main/java/com/falsepattern/lib/turboasm/TurboClassTransformer.java index 0ed58e0..791173e 100644 --- a/src/main/java/com/falsepattern/lib/turboasm/TurboClassTransformer.java +++ b/src/main/java/com/falsepattern/lib/turboasm/TurboClassTransformer.java @@ -58,7 +58,9 @@ public interface TurboClassTransformer { * (Optionally) transform a given class. No ClassReader flags are used for maximum efficiency, so stack frames are not expanded. * @param className The name of the transformed class (in the dot-separated format). * @param classNode The handle to the lazily ASM-parsed class to modify, and metadata used for class writing. + * @return True if the class has been modified in any way by this transformer. If all transformers return false, + * then the ClassNode instance will not be re-serialized. */ @Expose - void transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode); + boolean transformClass(@NotNull String className, @NotNull ClassNodeHandle classNode); } \ No newline at end of file