[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 val queue = IntArray(nInsns)
|
||||||
private var top = 0
|
private var top = 0
|
||||||
|
|
||||||
|
protected open fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean = true
|
||||||
|
|
||||||
fun analyze(): Array<Frame<V>?> {
|
fun analyze(): Array<Frame<V>?> {
|
||||||
if (nInsns == 0) return frames
|
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 mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false)
|
||||||
|
|
||||||
protected abstract fun analyzeInstruction(
|
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)
|
private fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int) {
|
||||||
protected abstract fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: F)
|
processControlFlowEdge(current, insnNode, insn + 1)
|
||||||
protected abstract fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F)
|
}
|
||||||
protected abstract fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int)
|
|
||||||
|
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() {
|
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 })
|
||||||
|
|||||||
-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].
|
* 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.
|
* 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")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun newFrame(nLocals: Int, nStack: Int): F = Frame<V>(nLocals, nStack) as F
|
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.
|
// 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 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) {
|
private fun visitNopInsn(insnNode: AbstractInsnNode, f: F, insn: Int) {
|
||||||
processControlFlowEdge(f, insnNode, insn + 1)
|
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) {
|
override fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean) {
|
||||||
val oldFrame = getFrame(dest)
|
val oldFrame = getFrame(dest)
|
||||||
val changes = when {
|
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.FastAnalyzer
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
|
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
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.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
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 newFrame(nLocals: Int, nStack: Int): StoreLoadFrame<V> = StoreLoadFrame(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 mergeControlFlowEdge(dest: Int, frame: StoreLoadFrame<V>, canReuse: Boolean) {
|
override fun mergeControlFlowEdge(dest: Int, frame: StoreLoadFrame<V>, canReuse: Boolean) {
|
||||||
val oldFrame = getFrame(dest)
|
val oldFrame = getFrame(dest)
|
||||||
|
|||||||
Reference in New Issue
Block a user