From a553a08def7c8842b229b560b9fd8ee74c63c94d Mon Sep 17 00:00:00 2001 From: Graham Date: Sun, 5 Apr 2020 11:26:36 +0100 Subject: [PATCH] Mark additional methods and classes as final where possible Signed-off-by: Graham --- .../deob/transform/FinalTransformer.kt | 91 +++++++++++++++++-- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/deob/src/main/java/dev/openrs2/deob/transform/FinalTransformer.kt b/deob/src/main/java/dev/openrs2/deob/transform/FinalTransformer.kt index 3cdcdff8..da264f78 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/FinalTransformer.kt +++ b/deob/src/main/java/dev/openrs2/deob/transform/FinalTransformer.kt @@ -1,18 +1,63 @@ package dev.openrs2.deob.transform import com.github.michaelbull.logging.InlineLogger +import dev.openrs2.asm.MemberRef import dev.openrs2.asm.classpath.ClassPath import dev.openrs2.asm.classpath.Library import dev.openrs2.asm.transform.Transformer +import dev.openrs2.util.collect.DisjointSet import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.MethodNode class FinalTransformer : Transformer() { - private var redundantFinals = 0 + private val superClasses = mutableListOf() + private lateinit var inheritedMethodSets: DisjointSet + private var methodsChanged = 0 override fun preTransform(classPath: ClassPath) { - redundantFinals = 0 + superClasses.clear() + inheritedMethodSets = classPath.createInheritedMethodSets() + methodsChanged = 0 + } + + override fun transformClass(classPath: ClassPath, library: Library, clazz: ClassNode): Boolean { + val superClass = clazz.superName + if (superClass != null) { + superClasses += superClass + } + + superClasses.addAll(clazz.interfaces) + + return false + } + + private fun isMethodFinal(classPath: ClassPath, clazz: ClassNode, method: MethodNode): Boolean { + if (method.name == "") { + return false + } else if ((method.access and (Opcodes.ACC_ABSTRACT or Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC)) != 0) { + return false + } + + val thisClass = classPath[clazz.name]!! + + val partition = inheritedMethodSets[MemberRef(clazz, method)]!! + for (methodRef in partition) { + if (methodRef.owner == clazz.name) { + continue + } + + val otherClass = classPath[methodRef.owner]!! + if (otherClass.methods.none { it.name == methodRef.name && it.desc == methodRef.desc }) { + continue + } + + if (thisClass.isAssignableFrom(otherClass)) { + return false + } + } + + return true } override fun preTransformMethod( @@ -21,19 +66,49 @@ class FinalTransformer : Transformer() { clazz: ClassNode, method: MethodNode ): Boolean { - if (method.access and Opcodes.ACC_FINAL == 0) { - return false + val access = method.access + + if (isMethodFinal(classPath, clazz, method)) { + method.access = access or Opcodes.ACC_FINAL + } else { + method.access = access and Opcodes.ACC_FINAL.inv() } - if (method.access and (Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC) != 0) { - method.access = method.access and Opcodes.ACC_FINAL.inv() - redundantFinals++ + if (method.access != access) { + methodsChanged++ } + return false } + private fun isClassFinal(clazz: ClassNode): Boolean { + if ((clazz.access and (Opcodes.ACC_ABSTRACT or Opcodes.ACC_INTERFACE)) != 0) { + return false + } + + return !superClasses.contains(clazz.name) + } + override fun postTransform(classPath: ClassPath) { - logger.info { "Removed $redundantFinals redundant final modifiers" } + var classesChanged = 0 + + for (library in classPath.libraries) { + for (clazz in library) { + val access = clazz.access + + if (isClassFinal(clazz)) { + clazz.access = access or Opcodes.ACC_FINAL + } else { + clazz.access = access and Opcodes.ACC_FINAL.inv() + } + + if (clazz.access != access) { + classesChanged++ + } + } + } + + logger.info { "Updated final modifier on $classesChanged classes and $methodsChanged methods" } } companion object {