From 8254f3d69f894221583676368cf17a1f8e909a5e Mon Sep 17 00:00:00 2001 From: Graham Date: Sat, 6 Jun 2020 15:26:56 +0100 Subject: [PATCH] Improve FieldWriteAnalyzer The new entry set functionality allows us to distinguish fields NEVER written from fields we haven't explored yet. This allows us to find more EXACTLY_ONCE fields in constructors with loops. Signed-off-by: Graham --- .../deob/analysis/FieldWriteAnalyzer.kt | 30 +++++++++++++------ .../deob/transform/FinalFieldTransformer.kt | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/deob/src/main/java/dev/openrs2/deob/analysis/FieldWriteAnalyzer.kt b/deob/src/main/java/dev/openrs2/deob/analysis/FieldWriteAnalyzer.kt index d958cdaa..86ecca29 100644 --- a/deob/src/main/java/dev/openrs2/deob/analysis/FieldWriteAnalyzer.kt +++ b/deob/src/main/java/dev/openrs2/deob/analysis/FieldWriteAnalyzer.kt @@ -4,16 +4,27 @@ import dev.openrs2.asm.MemberDesc import dev.openrs2.asm.classpath.ClassPath import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.AbstractInsnNode +import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.FieldInsnNode import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.analysis.Frame class FieldWriteAnalyzer( - private val owner: String, + private val clazz: ClassNode, private val method: MethodNode, private val classPath: ClassPath, private val frames: Array> -) : DataFlowAnalyzer>(owner, method) { +) : DataFlowAnalyzer>(clazz.name, method) { + override fun createEntrySet(): Map { + val set = mutableMapOf() + + for (field in clazz.fields) { + set[MemberDesc(field)] = FieldWriteCount.NEVER + } + + return set + } + override fun createInitialSet(): Map { return emptyMap() } @@ -29,13 +40,14 @@ class FieldWriteAnalyzer( val set = mutableMapOf() for (member in set1.keys union set2.keys) { - val count1 = set1.getOrDefault(member, FieldWriteCount.NEVER) - val count2 = set2.getOrDefault(member, FieldWriteCount.NEVER) + val count1 = set1[member] + val count2 = set2[member] - set[member] = if (count1 == count2) { - count1 - } else { - FieldWriteCount.UNKNOWN + set[member] = when { + count1 == null && count2 != null -> count2 + count2 == null && count1 != null -> count1 + count1 == count2 -> count1!! + else -> FieldWriteCount.UNKNOWN } } @@ -54,7 +66,7 @@ class FieldWriteAnalyzer( val member = MemberDesc(insn) val declaredOwner = classPath[insn.owner]!!.resolveField(member)!!.name - if (declaredOwner != owner) { + if (declaredOwner != clazz.name) { return set } diff --git a/deob/src/main/java/dev/openrs2/deob/transform/FinalFieldTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/FinalFieldTransformer.kt index 0aec72c0..4b6a5ebe 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/FinalFieldTransformer.kt +++ b/deob/src/main/java/dev/openrs2/deob/transform/FinalFieldTransformer.kt @@ -77,7 +77,7 @@ class FinalFieldTransformer : Transformer() { } if (constructorWithoutThisCall) { - val analyzer = FieldWriteAnalyzer(clazz.name, method, classPath, frames!!) + val analyzer = FieldWriteAnalyzer(clazz, method, classPath, frames!!) analyzer.analyze() val exits = method.instructions.filter { it.opcode == Opcodes.RETURN }