[JVM] Make FixStackAnalyzer inherit FastStackAnalyzer
This commit is contained in:
+1
-1
@@ -116,7 +116,7 @@ abstract class FastAnalyzer<V : Value, I : Interpreter<V>, F : Frame<V>>(
|
|||||||
protected abstract fun newFrame(nLocals: Int, nStack: Int): F
|
protected abstract fun newFrame(nLocals: Int, nStack: Int): F
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun getFrame(insn: AbstractInsnNode): F? = frames[insn.indexOf()] as? F
|
protected fun getFrame(insn: AbstractInsnNode): F? = frames[insn.indexOf()] as? F
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
protected fun getFrame(index: Int): F? = frames[index] as? F
|
protected fun getFrame(index: Int): F? = frames[index] as? F
|
||||||
|
|||||||
+14
-13
@@ -46,12 +46,13 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
|||||||
*/
|
*/
|
||||||
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
|
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
|
||||||
// but infers stack types for reachable instructions instead.
|
// but infers stack types for reachable instructions instead.
|
||||||
internal open class FastStackAnalyzer<V : Value>(
|
internal open class FastStackAnalyzer<V : Value, F : Frame<V>>(
|
||||||
owner: String,
|
owner: String,
|
||||||
method: MethodNode,
|
method: MethodNode,
|
||||||
interpreter: Interpreter<V>
|
interpreter: Interpreter<V>
|
||||||
) : FastAnalyzer<V, Interpreter<V>, Frame<V>>(owner, method, interpreter) {
|
) : FastAnalyzer<V, Interpreter<V>, F>(owner, method, interpreter) {
|
||||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
|
@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
|
protected open fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean = true
|
||||||
|
|
||||||
@@ -65,9 +66,9 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
insnIndex: Int,
|
insnIndex: Int,
|
||||||
insnType: Int,
|
insnType: Int,
|
||||||
insnOpcode: Int,
|
insnOpcode: Int,
|
||||||
currentlyAnalyzing: Frame<V>,
|
currentlyAnalyzing: F,
|
||||||
current: Frame<V>,
|
current: F,
|
||||||
handler: Frame<V>,
|
handler: F,
|
||||||
) {
|
) {
|
||||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
||||||
visitNopInsn(insnNode, currentlyAnalyzing, insnIndex)
|
visitNopInsn(insnNode, currentlyAnalyzing, insnIndex)
|
||||||
@@ -92,15 +93,15 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitOpInsn(insnNode: AbstractInsnNode, current: Frame<V>, insn: Int) {
|
override fun visitOpInsn(insnNode: AbstractInsnNode, current: F, insn: Int) {
|
||||||
processControlFlowEdge(current, insnNode, insn + 1)
|
processControlFlowEdge(current, insnNode, insn + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitNopInsn(insnNode: AbstractInsnNode, f: Frame<V>, 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: Frame<V>) {
|
override fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: F) {
|
||||||
var jump = insnNode.dflt.indexOf()
|
var jump = insnNode.dflt.indexOf()
|
||||||
processControlFlowEdge(current, insnNode, jump)
|
processControlFlowEdge(current, insnNode, jump)
|
||||||
// In most cases order of visiting switch labels should not matter
|
// In most cases order of visiting switch labels should not matter
|
||||||
@@ -114,7 +115,7 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>) {
|
override fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: F) {
|
||||||
var jump = insnNode.dflt.indexOf()
|
var jump = insnNode.dflt.indexOf()
|
||||||
processControlFlowEdge(current, insnNode, jump)
|
processControlFlowEdge(current, insnNode, jump)
|
||||||
for (label in insnNode.labels) {
|
for (label in insnNode.labels) {
|
||||||
@@ -123,7 +124,7 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
|
override fun visitJumpInsnNode(insnNode: JumpInsnNode, current: F, insn: Int, insnOpcode: Int) {
|
||||||
if (insnOpcode != Opcodes.GOTO) {
|
if (insnOpcode != Opcodes.GOTO) {
|
||||||
processControlFlowEdge(current, insnNode, insn + 1)
|
processControlFlowEdge(current, insnNode, insn + 1)
|
||||||
}
|
}
|
||||||
@@ -131,13 +132,13 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
processControlFlowEdge(current, insnNode, jump)
|
processControlFlowEdge(current, insnNode, jump)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processControlFlowEdge(current: Frame<V>, insnNode: AbstractInsnNode, jump: Int) {
|
private fun processControlFlowEdge(current: F, insnNode: AbstractInsnNode, jump: Int) {
|
||||||
if (visitControlFlowEdge(insnNode, jump)) {
|
if (visitControlFlowEdge(insnNode, jump)) {
|
||||||
mergeControlFlowEdge(jump, current)
|
mergeControlFlowEdge(jump, current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mergeControlFlowEdge(dest: Int, frame: Frame<V>, canReuse: Boolean) {
|
override fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean) {
|
||||||
val destFrame = getFrame(dest)
|
val destFrame = getFrame(dest)
|
||||||
if (destFrame == null) {
|
if (destFrame == null) {
|
||||||
// Don't have to visit same instruction multiple times - we care only about "initial" stack state.
|
// Don't have to visit same instruction multiple times - we care only about "initial" stack state.
|
||||||
|
|||||||
+8
-21
@@ -32,10 +32,10 @@ import kotlin.math.max
|
|||||||
|
|
||||||
internal class FixStackAnalyzer(
|
internal class FixStackAnalyzer(
|
||||||
owner: String,
|
owner: String,
|
||||||
val method: MethodNode,
|
method: MethodNode,
|
||||||
val context: FixStackContext,
|
val context: FixStackContext,
|
||||||
private val skipBreakContinueGotoEdges: Boolean = true
|
private val skipBreakContinueGotoEdges: Boolean = true
|
||||||
) {
|
) : FastStackAnalyzer<FixStackValue, FixStackAnalyzer.FixStackFrame>(owner, method, FixStackInterpreter()) {
|
||||||
companion object {
|
companion object {
|
||||||
// Stack size is always non-negative
|
// Stack size is always non-negative
|
||||||
const val DEAD_CODE_STACK_SIZE = -1
|
const val DEAD_CODE_STACK_SIZE = -1
|
||||||
@@ -43,10 +43,11 @@ internal class FixStackAnalyzer(
|
|||||||
|
|
||||||
private val loopEntryPointMarkers = hashMapOf<LabelNode, SmartList<AbstractInsnNode>>()
|
private val loopEntryPointMarkers = hashMapOf<LabelNode, SmartList<AbstractInsnNode>>()
|
||||||
|
|
||||||
val maxExtraStackSize: Int get() = analyzer.maxExtraStackSize
|
var maxExtraStackSize = 0; private set
|
||||||
|
private val spilledStacks = hashMapOf<AbstractInsnNode, List<FixStackValue>>()
|
||||||
|
|
||||||
fun getStackToSpill(location: AbstractInsnNode): List<FixStackValue>? =
|
fun getStackToSpill(location: AbstractInsnNode): List<FixStackValue>? =
|
||||||
analyzer.spilledStacks[location]
|
spilledStacks[location]
|
||||||
|
|
||||||
fun getActualStack(location: AbstractInsnNode): List<FixStackValue>? =
|
fun getActualStack(location: AbstractInsnNode): List<FixStackValue>? =
|
||||||
getFrame(location)?.getStackContent()
|
getFrame(location)?.getStackContent()
|
||||||
@@ -70,11 +71,8 @@ internal class FixStackAnalyzer(
|
|||||||
return DEAD_CODE_STACK_SIZE
|
return DEAD_CODE_STACK_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFrame(location: AbstractInsnNode) = analyzer.getFrame(location) as? InternalAnalyzer.FixStackFrame
|
override fun beforeAnalyze() {
|
||||||
|
|
||||||
fun analyze() {
|
|
||||||
recordLoopEntryPointMarkers()
|
recordLoopEntryPointMarkers()
|
||||||
analyzer.analyze()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recordLoopEntryPointMarkers() {
|
private fun recordLoopEntryPointMarkers() {
|
||||||
@@ -87,24 +85,16 @@ internal class FixStackAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val analyzer = InternalAnalyzer(owner)
|
|
||||||
|
|
||||||
private inner class InternalAnalyzer(owner: String) :
|
|
||||||
FastStackAnalyzer<FixStackValue>(owner, method, FixStackInterpreter()) {
|
|
||||||
|
|
||||||
val spilledStacks = hashMapOf<AbstractInsnNode, List<FixStackValue>>()
|
|
||||||
var maxExtraStackSize = 0; private set
|
|
||||||
|
|
||||||
override fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean {
|
override fun visitControlFlowEdge(insnNode: AbstractInsnNode, successor: Int): Boolean {
|
||||||
if (!skipBreakContinueGotoEdges) return true
|
if (!skipBreakContinueGotoEdges) return true
|
||||||
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
|
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newFrame(nLocals: Int, nStack: Int): Frame<FixStackValue> =
|
override fun newFrame(nLocals: Int, nStack: Int): FixStackFrame =
|
||||||
FixStackFrame(nLocals, nStack)
|
FixStackFrame(nLocals, nStack)
|
||||||
|
|
||||||
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<FixStackValue>(nLocals, nStack) {
|
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<FixStackValue>(nLocals, nStack) {
|
||||||
val extraStack = Stack<FixStackValue>()
|
private val extraStack = Stack<FixStackValue>()
|
||||||
|
|
||||||
override fun init(src: Frame<out FixStackValue>): Frame<FixStackValue> {
|
override fun init(src: Frame<out FixStackValue>): Frame<FixStackValue> {
|
||||||
extraStack.clear()
|
extraStack.clear()
|
||||||
@@ -213,7 +203,4 @@ internal class FixStackAnalyzer(
|
|||||||
saveStackAndClear(insn)
|
saveStackAndClear(insn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user