From 47325edb728c45e54198de4dac4fade5ad555737 Mon Sep 17 00:00:00 2001 From: Graham Date: Fri, 7 Aug 2020 18:08:31 +0100 Subject: [PATCH] Fix removal of unused arguments whose local variable slot is re-used Signed-off-by: Graham --- .../deob/analysis/ConstSourceInterpreter.kt | 15 ++++++--- .../openrs2/deob/analysis/ConstSourceValue.kt | 3 +- .../deob/transform/UnusedArgTransformer.kt | 33 ++++++++++++++----- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceInterpreter.kt b/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceInterpreter.kt index efaa872c..03ba92e4 100644 --- a/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceInterpreter.kt +++ b/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceInterpreter.kt @@ -15,10 +15,15 @@ class ConstSourceInterpreter : Interpreter(Opcodes.ASM8) { return ConstSourceValue.Unknown(basicValue) } + override fun newParameterValue(isInstanceMethod: Boolean, local: Int, type: Type): ConstSourceValue { + val basicValue = basicInterpreter.newParameterValue(isInstanceMethod, local, type) + return ConstSourceValue.Arg(basicValue) + } + override fun newOperation(insn: AbstractInsnNode): ConstSourceValue { val basicValue = basicInterpreter.newOperation(insn) return if (insn.intConstant != null) { - ConstSourceValue.Single(basicValue, insn) + ConstSourceValue.Insn(basicValue, insn) } else { ConstSourceValue.Unknown(basicValue) } @@ -74,10 +79,10 @@ class ConstSourceInterpreter : Interpreter(Opcodes.ASM8) { override fun merge(value1: ConstSourceValue, value2: ConstSourceValue): ConstSourceValue { val basicValue = basicInterpreter.merge(value1.basicValue, value2.basicValue) - return if (value1 is ConstSourceValue.Single && value1 == value2) { - value1 - } else { - ConstSourceValue.Unknown(basicValue) + return when { + value1 is ConstSourceValue.Arg || value2 is ConstSourceValue.Arg -> ConstSourceValue.Arg(basicValue) + value1 == value2 -> value1 + else -> ConstSourceValue.Unknown(basicValue) } } } diff --git a/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceValue.kt b/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceValue.kt index 0c787215..19ececfa 100644 --- a/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceValue.kt +++ b/deob/src/main/java/dev/openrs2/deob/analysis/ConstSourceValue.kt @@ -6,7 +6,8 @@ import org.objectweb.asm.tree.analysis.Value sealed class ConstSourceValue : Value { data class Unknown(override val basicValue: BasicValue) : ConstSourceValue() - data class Single(override val basicValue: BasicValue, val source: AbstractInsnNode) : ConstSourceValue() + data class Insn(override val basicValue: BasicValue, val source: AbstractInsnNode) : ConstSourceValue() + data class Arg(override val basicValue: BasicValue) : ConstSourceValue() abstract val basicValue: BasicValue diff --git a/deob/src/main/java/dev/openrs2/deob/transform/UnusedArgTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/UnusedArgTransformer.kt index 92f845e7..3a27dcae 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/UnusedArgTransformer.kt +++ b/deob/src/main/java/dev/openrs2/deob/transform/UnusedArgTransformer.kt @@ -17,10 +17,12 @@ import org.objectweb.asm.Opcodes import org.objectweb.asm.Type import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.IincInsnNode import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.VarInsnNode import org.objectweb.asm.tree.analysis.Analyzer +import org.objectweb.asm.tree.analysis.Frame import javax.inject.Inject import javax.inject.Singleton @@ -46,6 +48,23 @@ class UnusedArgTransformer @Inject constructor(private val profile: Profile) : T } } + private fun retainArg( + partition: DisjointSet.Partition, + localToArgMap: Map, + frame: Frame, + local: Int + ) { + val source = frame.getLocal(local) + if (source !is ConstSourceValue.Arg) { + return + } + + val arg = localToArgMap[local] + if (arg != null) { + retainedArgs.add(ArgPartition(partition, arg)) + } + } + private fun populateRetainedArgs(classPath: ClassPath, clazz: ClassNode, method: MethodNode) { val partition = inheritedMethodSets[MemberRef(clazz, method)]!! val localToArgMap = createLocalToArgMap(method) @@ -62,15 +81,11 @@ class UnusedArgTransformer @Inject constructor(private val profile: Profile) : T when (val insn = method.instructions[i]) { is VarInsnNode -> { - if (insn.opcode != Opcodes.ILOAD) { - continue@frame - } - - val arg = localToArgMap[insn.`var`] - if (arg != null) { - retainedArgs.add(ArgPartition(partition, arg)) + if (insn.opcode == Opcodes.ILOAD) { + retainArg(partition, localToArgMap, frame, insn.`var`) } } + is IincInsnNode -> retainArg(partition, localToArgMap, frame, insn.`var`) is MethodInsnNode -> { val invokePartition = inheritedMethodSets[MemberRef(insn)] if (invokePartition == null) { @@ -84,7 +99,7 @@ class UnusedArgTransformer @Inject constructor(private val profile: Profile) : T val args = Type.getArgumentTypes(insn.desc).size for (j in 0 until args) { val source = frame.getStack(stackSize - args + j) - if (source !is ConstSourceValue.Single) { + if (source !is ConstSourceValue.Insn) { retainedArgs.add(ArgPartition(invokePartition, j)) } } @@ -133,7 +148,7 @@ class UnusedArgTransformer @Inject constructor(private val profile: Profile) : T for ((j, argType) in argTypes.withIndex()) { if (argType.sort in INT_SORTS && ArgPartition(partition, j) !in retainedArgs) { - val value = frame.getStack(stackSize - argTypes.size + j) as ConstSourceValue.Single + val value = frame.getStack(stackSize - argTypes.size + j) as ConstSourceValue.Insn deadInsns.add(value.source) } else { newArgTypes.add(argType)