diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastAnalyzer.kt index ebdac9a9591..4664f14e509 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastAnalyzer.kt @@ -28,7 +28,19 @@ abstract class FastAnalyzer, F : Frame>( private val queue = IntArray(nInsns) private var top = 0 - protected fun analyzeInner() { + fun analyze(): Array?> { + if (nInsns == 0) return frames + + checkAssertions() + computeExceptionHandlers(method) + beforeAnalyze() + + analyzeMainLoop() + + return frames + } + + private fun analyzeMainLoop() { val current = newFrame(method.maxLocals, method.maxStack) val handler = newFrame(method.maxLocals, method.maxStack) initLocals(current) @@ -37,8 +49,7 @@ abstract class FastAnalyzer, F : Frame>( while (top > 0) { val insn = queue[--top] - @Suppress("UNCHECKED_CAST") - val f = frames[insn]!! as F + val f = getFrame(insn)!! queued[insn] = false val insnNode = method.instructions[insn] @@ -63,6 +74,8 @@ abstract class FastAnalyzer, F : Frame>( } } + protected open fun beforeAnalyze() {} + protected abstract fun initLocals(current: F) protected abstract fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false) @@ -89,8 +102,6 @@ abstract class FastAnalyzer, F : Frame>( frames[index] = newFrame } - protected fun getFrames(): Array?> = frames - protected fun visitMeaningfulInstruction(insnNode: AbstractInsnNode, insnType: Int, insnOpcode: Int, current: F, insn: Int) { when { insnType == AbstractInsnNode.JUMP_INSN -> @@ -111,7 +122,7 @@ abstract class FastAnalyzer, F : Frame>( protected abstract fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F) 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 }) throw AssertionError("Subroutines are deprecated since Java 6") } @@ -119,9 +130,11 @@ abstract class FastAnalyzer, F : Frame>( protected fun AbstractInsnNode.indexOf() = 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) { - if (forEachInsn) computeExceptionHandlersForEachInsn(tcb) else computeExceptionHandlerFast(tcb) + if (useFastComputeExceptionHandlers()) computeExceptionHandlerFast(tcb) else computeExceptionHandlersForEachInsn(tcb) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt index 972437199c9..771a06ee1db 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt @@ -57,19 +57,10 @@ open class FastMethodAnalyzer override fun newFrame(nLocals: Int, nStack: Int): Frame = Frame(nLocals, nStack) - fun analyze(): Array?> { - if (nInsns == 0) return getFrames() - - checkAssertions() - computeExceptionHandlers(method) - + override fun beforeAnalyze() { for (tcb in method.tryCatchBlocks) { isTcbStart[tcb.start.indexOf() + 1] = true } - - analyzeInner() - - return getFrames() } override fun analyzeInstruction( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt index e15758e5999..830d12233d4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt @@ -44,6 +44,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value /** * @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( owner: String, method: MethodNode, @@ -55,21 +57,8 @@ internal open class FastStackAnalyzer( protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true - fun analyze(): Array?> { - if (nInsns == 0) return getFrames() - - // 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() - } + // Don't have to visit the same exception handler multiple times - we care only about stack state at TCB start. + override fun useFastComputeExceptionHandlers(): Boolean = true override fun analyzeInstruction( insnNode: AbstractInsnNode, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt index 665bcc20a91..3915fb56004 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt @@ -106,16 +106,8 @@ class FastStoreLoadAnalyzer( ) : FastAnalyzer, StoreLoadFrame>(owner, method, interpreter) { private val isMergeNode = BooleanArray(nInsns) - fun analyze(): Array?> { - if (nInsns == 0) return getFrames() - - checkAssertions() - computeExceptionHandlers(method) + override fun beforeAnalyze() { initMergeNodes() - - analyzeInner() - - return getFrames() } override fun analyzeInstruction(