[JVM] Move visit...Insn methods in FastAnalyzer

They are actually the same.
This commit is contained in:
Ivan Kylchik
2023-09-06 10:49:26 +02:00
committed by Space Team
parent 7845e6bb0a
commit ed95ebc585
4 changed files with 42 additions and 105 deletions
@@ -29,6 +29,8 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
private val queue = IntArray(nInsns)
private var top = 0
protected open fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
@@ -101,6 +103,12 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
}
}
protected fun processControlFlowEdge(current: F, insnNode: AbstractInsnNode, jump: Int) {
if (visitControlFlowEdge(insnNode, jump)) {
mergeControlFlowEdge(jump, current)
}
}
protected abstract fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false)
protected abstract fun analyzeInstruction(
@@ -140,10 +148,35 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
}
}
protected abstract fun visitJumpInsnNode(insnNode: JumpInsnNode, current: F, insn: Int, insnOpcode: Int)
protected abstract fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: F)
protected abstract fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F)
protected abstract fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int)
private fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int) {
processControlFlowEdge(current, insnNode, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F) {
processControlFlowEdge(current, insnNode, insnNode.dflt.indexOf())
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FastAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'asReversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.asReversed()) {
processControlFlowEdge(current, insnNode, label.indexOf())
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: F) {
processControlFlowEdge(current, insnNode, insnNode.dflt.indexOf())
for (label in insnNode.labels) {
processControlFlowEdge(current, insnNode, label.indexOf())
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, current: F, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO) {
processControlFlowEdge(current, insnNode, insn + 1)
}
processControlFlowEdge(current, insnNode, insnNode.label.indexOf())
}
private fun checkAssertions() {
if (method.instructions.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
@@ -104,36 +104,6 @@ class FastMethodAnalyzer<V : Value>
}
}
override fun visitOpInsn(insnNode: AbstractInsnNode, current: Frame<V>, insn: Int) {
mergeControlFlowEdge(insn + 1, current)
}
override fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>) {
mergeControlFlowEdge(insnNode.dflt.indexOf(), current)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.asReversed()) {
mergeControlFlowEdge(label.indexOf(), current)
}
}
override fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>) {
mergeControlFlowEdge(insnNode.dflt.indexOf(), current)
for (label in insnNode.labels) {
mergeControlFlowEdge(label.indexOf(), current)
}
}
override fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
mergeControlFlowEdge(insnNode.label.indexOf(), current)
if (insnOpcode != Opcodes.GOTO) {
mergeControlFlowEdge(insn + 1, current)
}
}
/**
* Updates frame at the index [dest] with its old value if provided and previous control flow node frame [frame].
* Reuses old frame when possible and when [canReuse] is true.
@@ -54,8 +54,6 @@ internal open class FastStackAnalyzer<V : Value, F : Frame<V>>(
@Suppress("UNCHECKED_CAST")
override fun newFrame(nLocals: Int, nStack: Int): F = Frame<V>(nLocals, nStack) as F
protected open fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean = true
// 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
@@ -90,51 +88,10 @@ internal open class FastStackAnalyzer<V : Value, F : Frame<V>>(
}
}
override fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int) {
processControlFlowEdge(current, insnNode, insn + 1)
}
private fun visitNopInsn(insnNode: AbstractInsnNode, f: F, insn: Int) {
processControlFlowEdge(f, insnNode, insn + 1)
}
override fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insnNode, jump)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.reversed()) {
jump = label.indexOf()
processControlFlowEdge(current, insnNode, jump)
}
}
override fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: F) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insnNode, jump)
for (label in insnNode.labels) {
jump = label.indexOf()
processControlFlowEdge(current, insnNode, jump)
}
}
override fun visitJumpInsnNode(insnNode: JumpInsnNode, current: F, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO) {
processControlFlowEdge(current, insnNode, insn + 1)
}
val jump = insnNode.label.indexOf()
processControlFlowEdge(current, insnNode, jump)
}
private fun processControlFlowEdge(current: F, insnNode: AbstractInsnNode, jump: Int) {
if (visitControlFlowEdge(insnNode, jump)) {
mergeControlFlowEdge(jump, current)
}
}
override fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean) {
val oldFrame = getFrame(dest)
val changes = when {
@@ -36,8 +36,10 @@ package org.jetbrains.kotlin.codegen.optimization.temporaryVals
import org.jetbrains.kotlin.codegen.optimization.common.FastAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.IincInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
@@ -91,32 +93,7 @@ class FastStoreLoadAnalyzer<V : Value>(
}
}
override fun newFrame(nLocals: Int, nStack: Int): StoreLoadFrame<V> = StoreLoadFrame<V>(nLocals)
override fun visitOpInsn(insnNode: AbstractInsnNode, current: StoreLoadFrame<V>, insn: Int) {
mergeControlFlowEdge(insn + 1, current)
}
override fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: StoreLoadFrame<V>) {
mergeControlFlowEdge(insnNode.dflt.indexOf(), current)
for (label in insnNode.labels) {
mergeControlFlowEdge(label.indexOf(), current)
}
}
override fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: StoreLoadFrame<V>) {
mergeControlFlowEdge(insnNode.dflt.indexOf(), current)
for (label in insnNode.labels) {
mergeControlFlowEdge(label.indexOf(), current)
}
}
override fun visitJumpInsnNode(insnNode: JumpInsnNode, current: StoreLoadFrame<V>, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO) {
mergeControlFlowEdge(insn + 1, current)
}
mergeControlFlowEdge(insnNode.label.indexOf(), current)
}
override fun newFrame(nLocals: Int, nStack: Int): StoreLoadFrame<V> = StoreLoadFrame(nLocals)
override fun mergeControlFlowEdge(dest: Int, frame: StoreLoadFrame<V>, canReuse: Boolean) {
val oldFrame = getFrame(dest)