|
|
@ -5,7 +5,9 @@ import dev.openrs2.asm.classpath.ClassPath |
|
|
|
import dev.openrs2.asm.classpath.Library |
|
|
|
import dev.openrs2.asm.classpath.Library |
|
|
|
import dev.openrs2.asm.deleteSimpleExpression |
|
|
|
import dev.openrs2.asm.deleteSimpleExpression |
|
|
|
import dev.openrs2.asm.transform.Transformer |
|
|
|
import dev.openrs2.asm.transform.Transformer |
|
|
|
|
|
|
|
import dev.openrs2.deob.analysis.LiveVariableAnalyzer |
|
|
|
import org.objectweb.asm.Opcodes |
|
|
|
import org.objectweb.asm.Opcodes |
|
|
|
|
|
|
|
import org.objectweb.asm.tree.AbstractInsnNode |
|
|
|
import org.objectweb.asm.tree.ClassNode |
|
|
|
import org.objectweb.asm.tree.ClassNode |
|
|
|
import org.objectweb.asm.tree.MethodNode |
|
|
|
import org.objectweb.asm.tree.MethodNode |
|
|
|
import org.objectweb.asm.tree.VarInsnNode |
|
|
|
import org.objectweb.asm.tree.VarInsnNode |
|
|
@ -18,29 +20,25 @@ class DummyLocalTransformer : Transformer() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { |
|
|
|
override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean { |
|
|
|
/* |
|
|
|
val analyzer = LiveVariableAnalyzer(clazz.name, method) |
|
|
|
* XXX(gpe): this is primitive (ideally we'd do a proper data flow |
|
|
|
analyzer.analyze() |
|
|
|
* analysis, but we'd need to do it in reverse and ASM only supports |
|
|
|
|
|
|
|
* forward data flow), however, it seems to be good enough to catch |
|
|
|
|
|
|
|
* most dummy locals. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
val loads = BooleanArray(method.maxLocals) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (insn in method.instructions) { |
|
|
|
val deadStores = mutableListOf<AbstractInsnNode>() |
|
|
|
if (insn is VarInsnNode && insn.opcode == Opcodes.ILOAD) { |
|
|
|
|
|
|
|
loads[insn.`var`] = true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (insn in method.instructions) { |
|
|
|
for (insn in method.instructions) { |
|
|
|
if (insn !is VarInsnNode || insn.opcode != Opcodes.ISTORE) { |
|
|
|
if (insn !is VarInsnNode || insn.opcode != Opcodes.ISTORE) { |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (loads[insn.`var`]) { |
|
|
|
val live = analyzer.getInSet(insn)?.contains(insn.`var`) ?: false |
|
|
|
|
|
|
|
if (live) { |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deadStores += insn |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (insn in deadStores) { |
|
|
|
if (method.instructions.deleteSimpleExpression(insn)) { |
|
|
|
if (method.instructions.deleteSimpleExpression(insn)) { |
|
|
|
localsRemoved++ |
|
|
|
localsRemoved++ |
|
|
|
} |
|
|
|
} |
|
|
|