[JVM] Fully move analyze method into FastAnalyzer

This commit is contained in:
Ivan Kylchik
2023-08-24 12:07:59 +02:00
committed by Space Team
parent abe727fdd7
commit 02d8a62cb0
4 changed files with 27 additions and 42 deletions
@@ -28,7 +28,19 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
private val queue = IntArray(nInsns) private val queue = IntArray(nInsns)
private var top = 0 private var top = 0
protected fun analyzeInner() { fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
checkAssertions()
computeExceptionHandlers(method)
beforeAnalyze()
analyzeMainLoop()
return frames
}
private fun analyzeMainLoop() {
val current = newFrame(method.maxLocals, method.maxStack) val current = newFrame(method.maxLocals, method.maxStack)
val handler = newFrame(method.maxLocals, method.maxStack) val handler = newFrame(method.maxLocals, method.maxStack)
initLocals(current) initLocals(current)
@@ -37,8 +49,7 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
while (top > 0) { while (top > 0) {
val insn = queue[--top] val insn = queue[--top]
@Suppress("UNCHECKED_CAST") val f = getFrame(insn)!!
val f = frames[insn]!! as F
queued[insn] = false queued[insn] = false
val insnNode = method.instructions[insn] val insnNode = method.instructions[insn]
@@ -63,6 +74,8 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
} }
} }
protected open fun beforeAnalyze() {}
protected abstract fun initLocals(current: F) protected abstract fun initLocals(current: F)
protected abstract fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false) protected abstract fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false)
@@ -89,8 +102,6 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
frames[index] = newFrame frames[index] = newFrame
} }
protected fun getFrames(): Array<Frame<V>?> = frames
protected fun visitMeaningfulInstruction(insnNode: AbstractInsnNode, insnType: Int, insnOpcode: Int, current: F, insn: Int) { protected fun visitMeaningfulInstruction(insnNode: AbstractInsnNode, insnType: Int, insnOpcode: Int, current: F, insn: Int) {
when { when {
insnType == AbstractInsnNode.JUMP_INSN -> insnType == AbstractInsnNode.JUMP_INSN ->
@@ -111,7 +122,7 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
protected abstract fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F) protected abstract fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F)
protected abstract fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int) protected abstract fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int)
protected fun checkAssertions() { private fun checkAssertions() {
if (method.instructions.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET }) if (method.instructions.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6") throw AssertionError("Subroutines are deprecated since Java 6")
} }
@@ -119,9 +130,11 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
protected fun AbstractInsnNode.indexOf() = protected fun AbstractInsnNode.indexOf() =
method.instructions.indexOf(this) method.instructions.indexOf(this)
protected fun computeExceptionHandlers(m: MethodNode, forEachInsn: Boolean = true) { protected open fun useFastComputeExceptionHandlers(): Boolean = false
private fun computeExceptionHandlers(m: MethodNode) {
for (tcb in m.tryCatchBlocks) { for (tcb in m.tryCatchBlocks) {
if (forEachInsn) computeExceptionHandlersForEachInsn(tcb) else computeExceptionHandlerFast(tcb) if (useFastComputeExceptionHandlers()) computeExceptionHandlerFast(tcb) else computeExceptionHandlersForEachInsn(tcb)
} }
} }
@@ -57,19 +57,10 @@ open class FastMethodAnalyzer<V : Value>
override fun newFrame(nLocals: Int, nStack: Int): Frame<V> = override fun newFrame(nLocals: Int, nStack: Int): Frame<V> =
Frame(nLocals, nStack) Frame(nLocals, nStack)
fun analyze(): Array<Frame<V>?> { override fun beforeAnalyze() {
if (nInsns == 0) return getFrames()
checkAssertions()
computeExceptionHandlers(method)
for (tcb in method.tryCatchBlocks) { for (tcb in method.tryCatchBlocks) {
isTcbStart[tcb.start.indexOf() + 1] = true isTcbStart[tcb.start.indexOf() + 1] = true
} }
analyzeInner()
return getFrames()
} }
override fun analyzeInstruction( override fun analyzeInstruction(
@@ -44,6 +44,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/** /**
* @see org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer * @see org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
*/ */
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
// but infers stack types for reachable instructions instead.
internal open class FastStackAnalyzer<V : Value>( internal open class FastStackAnalyzer<V : Value>(
owner: String, owner: String,
method: MethodNode, method: MethodNode,
@@ -55,21 +57,8 @@ internal open class FastStackAnalyzer<V : Value>(
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> { // Don't have to visit the same exception handler multiple times - we care only about stack state at TCB start.
if (nInsns == 0) return getFrames() override fun useFastComputeExceptionHandlers(): Boolean = true
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
// but infers stack types for reachable instructions instead.
checkAssertions()
// Don't have to visit same exception handler multiple times - we care only about stack state at TCB start.
computeExceptionHandlers(method, forEachInsn = false)
analyzeInner()
return getFrames()
}
override fun analyzeInstruction( override fun analyzeInstruction(
insnNode: AbstractInsnNode, insnNode: AbstractInsnNode,
@@ -106,16 +106,8 @@ class FastStoreLoadAnalyzer<V : StoreLoadValue>(
) : FastAnalyzer<V, StoreLoadInterpreter<V>, StoreLoadFrame<V>>(owner, method, interpreter) { ) : FastAnalyzer<V, StoreLoadInterpreter<V>, StoreLoadFrame<V>>(owner, method, interpreter) {
private val isMergeNode = BooleanArray(nInsns) private val isMergeNode = BooleanArray(nInsns)
fun analyze(): Array<Frame<V>?> { override fun beforeAnalyze() {
if (nInsns == 0) return getFrames()
checkAssertions()
computeExceptionHandlers(method)
initMergeNodes() initMergeNodes()
analyzeInner()
return getFrames()
} }
override fun analyzeInstruction( override fun analyzeInstruction(