Consider static and instance fields separately in FieldWriteAnalyzer

This fixes a bug where fields could never become static if a class had a
mixture of static and non-static fields and constructors.

Signed-off-by: Graham <gpe@openrs2.dev>
bzip2
Graham 5 years ago
parent 2cbe6ce8e0
commit d410f87240
  1. 9
      deob/src/main/java/dev/openrs2/deob/analysis/FieldWriteAnalyzer.kt
  2. 11
      deob/src/main/java/dev/openrs2/deob/transform/FinalFieldTransformer.kt

@ -15,12 +15,17 @@ class FieldWriteAnalyzer(
private val classPath: ClassPath,
private val frames: Array<Frame<ThisValue>>
) : DataFlowAnalyzer<Map<MemberDesc, FieldWriteCount>>(clazz.name, method) {
private val methodStatic = (method.access and Opcodes.ACC_STATIC) != 0
override fun createEntrySet(): Map<MemberDesc, FieldWriteCount> {
val set = mutableMapOf<MemberDesc, FieldWriteCount>()
for (field in clazz.fields) {
val fieldStatic = (field.access and Opcodes.ACC_STATIC) != 0
if (methodStatic == fieldStatic) {
set[MemberDesc(field)] = FieldWriteCount.NEVER
}
}
return set
}
@ -60,7 +65,9 @@ class FieldWriteAnalyzer(
): Map<MemberDesc, FieldWriteCount> {
if (insn !is FieldInsnNode) {
return set
} else if (insn.opcode != Opcodes.PUTFIELD && insn.opcode != Opcodes.PUTSTATIC) {
} else if (methodStatic && insn.opcode != Opcodes.PUTSTATIC) {
return set
} else if (!methodStatic && insn.opcode != Opcodes.PUTFIELD) {
return set
}

@ -29,7 +29,8 @@ class FinalFieldTransformer : Transformer() {
override fun transformCode(classPath: ClassPath, library: Library, clazz: ClassNode, method: MethodNode): Boolean {
val constructor = method.name == "<init>" || method.name == "<clinit>"
val thisCall = if (constructor && method.name == "<init>") {
val constructorStatic = (method.access and Opcodes.ACC_STATIC) != 0
val thisCall = if (constructor && !constructorStatic) {
method.instructions.filterIsInstance<MethodInsnNode>()
.any { it.opcode == Opcodes.INVOKESPECIAL && it.owner == clazz.name && it.name == "<init>" }
} else {
@ -61,7 +62,8 @@ class FinalFieldTransformer : Transformer() {
}
val declaredOwner = classPath[insn.owner]!!.resolveField(MemberDesc(insn))!!.name
if (isThis && declaredOwner == clazz.name) {
val fieldStatic = insn.opcode == Opcodes.PUTSTATIC
if (isThis && declaredOwner == clazz.name && fieldStatic == constructorStatic) {
/*
* Writes inside constructors without a this(...) call to
* fields owned by the same class are analyzed separately - if
@ -84,10 +86,9 @@ class FinalFieldTransformer : Transformer() {
for (insn in exits) {
val counts = analyzer.getOutSet(insn) ?: emptyMap()
for (field in clazz.fields) {
val count = counts.getOrDefault(MemberDesc(field), FieldWriteCount.NEVER)
for ((field, count) in counts) {
if (count != FieldWriteCount.EXACTLY_ONCE) {
val partition = inheritedFieldSets[MemberRef(clazz, field)]!!
val partition = inheritedFieldSets[MemberRef(clazz.name, field)]!!
nonFinalFields += partition
}
}

Loading…
Cancel
Save