[JVM] Move visit...Insn methods in FastAnalyzer
They are actually the same.
This commit is contained in:
+37
-4
@@ -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 })
|
||||
|
||||
-30
@@ -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.
|
||||
|
||||
-43
@@ -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 {
|
||||
|
||||
+5
-28
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user