From e3095f4a7e3b0a47635e7cd6ae521ab6a45fdb8f Mon Sep 17 00:00:00 2001 From: Graham Date: Thu, 9 Apr 2020 19:31:07 +0100 Subject: [PATCH] Use fastutil to reduce allocations in LiveVariableAnalyzer Signed-off-by: Graham --- buildSrc/src/main/java/Versions.kt | 1 + deob/build.gradle.kts | 1 + .../deob/analysis/LiveVariableAnalyzer.kt | 47 +++++++++++++++++-- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 425ad73b..bd6cf07f 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -4,6 +4,7 @@ object Versions { const val clikt = "2.6.0" const val commonsCompress = "1.20" const val dependencyLicenseReport = "1.13" + const val fastutil = "8.3.1" const val fernflower = "1.0.3" const val guava = "28.2-jre" const val guice = "4.2.3" diff --git a/deob/build.gradle.kts b/deob/build.gradle.kts index 691738c7..b752d39c 100644 --- a/deob/build.gradle.kts +++ b/deob/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { implementation(project(":bundler")) implementation(project(":deob-annotations")) implementation("com.google.guava:guava:${Versions.guava}") + implementation("it.unimi.dsi:fastutil:${Versions.fastutil}") } publishing { diff --git a/deob/src/main/java/dev/openrs2/deob/analysis/LiveVariableAnalyzer.kt b/deob/src/main/java/dev/openrs2/deob/analysis/LiveVariableAnalyzer.kt index 2f7d7eaf..e9184140 100644 --- a/deob/src/main/java/dev/openrs2/deob/analysis/LiveVariableAnalyzer.kt +++ b/deob/src/main/java/dev/openrs2/deob/analysis/LiveVariableAnalyzer.kt @@ -1,5 +1,8 @@ package dev.openrs2.deob.analysis +import it.unimi.dsi.fastutil.ints.IntOpenHashSet +import it.unimi.dsi.fastutil.ints.IntSet +import it.unimi.dsi.fastutil.ints.IntSets import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.IincInsnNode @@ -7,17 +10,17 @@ import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.VarInsnNode class LiveVariableAnalyzer(owner: String, method: MethodNode) : - DataFlowAnalyzer>(owner, method, backwards = true) { + DataFlowAnalyzer(owner, method, backwards = true) { - override fun createInitialSet(): Set { - return emptySet() + override fun createInitialSet(): IntSet { + return IntSets.EMPTY_SET } - override fun join(set1: Set, set2: Set): Set { + override fun join(set1: IntSet, set2: IntSet): IntSet { return set1 union set2 } - override fun transfer(set: Set, insn: AbstractInsnNode): Set { + override fun transfer(set: IntSet, insn: AbstractInsnNode): IntSet { return when (insn) { is VarInsnNode -> when (insn.opcode) { Opcodes.ILOAD, Opcodes.LLOAD, Opcodes.FLOAD, Opcodes.DLOAD, Opcodes.ALOAD -> set.plus(insn.`var`) @@ -28,4 +31,38 @@ class LiveVariableAnalyzer(owner: String, method: MethodNode) : else -> set } } + + private infix fun IntSet.union(other: IntSet): IntSet { + if (this == other || other.isEmpty()) { + return this + } else if (isEmpty()) { + return other + } + + val set = IntOpenHashSet(this) + set.addAll(other) + return set + } + + private fun IntSet.plus(element: Int): IntSet { + if (contains(element)) { + return this + } + + val newSet = IntOpenHashSet(this) + newSet.add(element) + return newSet + } + + private fun IntSet.minus(element: Int): IntSet { + if (!contains(element)) { + return this + } else if (size == 1) { + return IntSets.EMPTY_SET + } + + val newSet = IntOpenHashSet(this) + newSet.remove(element) + return newSet + } }