diff --git a/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.java b/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.java deleted file mode 100644 index d66b3910..00000000 --- a/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.java +++ /dev/null @@ -1,99 +0,0 @@ -package dev.openrs2.deob.transform; - -import java.util.HashMap; -import java.util.Map; - -import dev.openrs2.asm.InsnMatcher; -import dev.openrs2.asm.MemberRef; -import dev.openrs2.asm.MethodNodeUtilsKt; -import dev.openrs2.asm.classpath.ClassPath; -import dev.openrs2.asm.classpath.Library; -import dev.openrs2.asm.transform.Transformer; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.VarInsnNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class BitwiseOpTransformer extends Transformer { - private static final Logger logger = LoggerFactory.getLogger(BitwiseOpTransformer.class); - - private static final InsnMatcher BITWISE_OP_MATCHER = InsnMatcher.compile("^ILOAD ILOAD (IXOR | IAND | IOR) IRETURN$"); - private static final String BITWISE_OP_DESC = "(II)I"; - - private final Map methodOps = new HashMap<>(); - private int inlinedOps; - - @Override - protected void preTransform(ClassPath classPath) { - methodOps.clear(); - inlinedOps = 0; - - for (var library : classPath.getLibraries()) { - for (var clazz : library) { - for (var method : clazz.methods) { - if (!MethodNodeUtilsKt.hasCode(method)) { - continue; - } - - if ((method.access & Opcodes.ACC_STATIC) == 0) { - continue; - } - - if (!method.desc.equals(BITWISE_OP_DESC)) { - continue; - } - - BITWISE_OP_MATCHER.match(method).findAny().ifPresent(match -> { - var iload0 = (VarInsnNode) match.get(0); - if (iload0.var != 0) { - return; - } - - var iload1 = (VarInsnNode) match.get(1); - if (iload1.var != 1) { - return; - } - - var methodRef = new MemberRef(clazz, method); - methodOps.put(methodRef, match.get(2).getOpcode()); - }); - } - } - } - } - - @Override - protected boolean transformClass(ClassPath classPath, Library library, ClassNode clazz) { - clazz.methods.removeIf(m -> methodOps.containsKey(new MemberRef(clazz, m))); - return false; - } - - @Override - protected boolean transformCode(ClassPath classPath, Library library, ClassNode clazz, MethodNode method) { - for (var it = method.instructions.iterator(); it.hasNext(); ) { - var insn = it.next(); - if (insn.getOpcode() != Opcodes.INVOKESTATIC) { - continue; - } - - var invokestatic = (MethodInsnNode) insn; - var methodRef = new MemberRef(invokestatic); - var opcode = methodOps.get(methodRef); - if (opcode != null) { - it.set(new InsnNode(opcode)); - inlinedOps++; - } - } - - return false; - } - - @Override - protected void postTransform(ClassPath classPath) { - logger.info("Inlined {} bitwise ops and removed {} redundant methods", inlinedOps, methodOps.size()); - } -} diff --git a/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.kt new file mode 100644 index 00000000..361a864c --- /dev/null +++ b/deob/src/main/java/dev/openrs2/deob/transform/BitwiseOpTransformer.kt @@ -0,0 +1,84 @@ +package dev.openrs2.deob.transform + +import com.github.michaelbull.logging.InlineLogger +import dev.openrs2.asm.InsnMatcher +import dev.openrs2.asm.MemberRef +import dev.openrs2.asm.classpath.ClassPath +import dev.openrs2.asm.classpath.Library +import dev.openrs2.asm.hasCode +import dev.openrs2.asm.transform.Transformer +import org.objectweb.asm.Opcodes +import org.objectweb.asm.tree.* +import kotlin.streams.asSequence + +class BitwiseOpTransformer : Transformer() { + private val methodOps = mutableMapOf() + private var inlinedOps = 0 + + override fun preTransform(classPath: ClassPath) { + methodOps.clear() + inlinedOps = 0 + + for (library in classPath.libraries) { + for (clazz in library) { + for (method in clazz.methods) { + if (!method.hasCode()) { + continue + } + + if (method.access and Opcodes.ACC_STATIC == 0) { + continue + } + + if (method.desc != BITWISE_OP_DESC) { + continue + } + + val match = BITWISE_OP_MATCHER.match(method).asSequence().firstOrNull() ?: continue + + val iload0 = match[0] as VarInsnNode + val iload1 = match[1] as VarInsnNode + if (iload0.`var` != 0 || iload1.`var` != 1) { + continue + } + + val methodRef = MemberRef(clazz, method) + methodOps[methodRef] = match[2].opcode + } + } + } + } + + override fun transformClass(classPath: ClassPath, library: Library, clazz: ClassNode): Boolean { + clazz.methods.removeIf { methodOps.containsKey(MemberRef(clazz, it)) } + return false + } + + override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { + val it = method.instructions.iterator() + while (it.hasNext()) { + val insn = it.next() + if (insn !is MethodInsnNode || insn.opcode != Opcodes.INVOKESTATIC) { + continue + } + + val opcode = methodOps[MemberRef(insn)] + if (opcode != null) { + it.set(InsnNode(opcode)) + inlinedOps++ + } + } + + return false + } + + override fun postTransform(classPath: ClassPath) { + logger.info { "Inlined $inlinedOps bitwise ops and removed ${methodOps.size} redundant methods" } + } + + companion object { + private val logger = InlineLogger() + private val BITWISE_OP_MATCHER = InsnMatcher.compile("^ILOAD ILOAD (IXOR | IAND | IOR) IRETURN$") + private const val BITWISE_OP_DESC = "(II)I" + } +}