org.jetbrains.kotlin.codegen.optimization.common.variableLiveness.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.optimization.common
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 java.util.*
class VariableLivenessFrame(val maxLocals: Int) : VarFrame {
private val bitSet = BitSet(maxLocals)
private var controlFlowMerge = false
override fun mergeFrom(other: VariableLivenessFrame) {
bitSet.or(other.bitSet)
}
override fun markControlFlowMerge() {
controlFlowMerge = true
}
fun markAlive(varIndex: Int) {
bitSet.set(varIndex, true)
}
fun markDead(varIndex: Int) {
bitSet.set(varIndex, false)
}
fun isAlive(varIndex: Int): Boolean = bitSet.get(varIndex)
fun isControlFlowMerge(): Boolean = controlFlowMerge
override fun equals(other: Any?): Boolean {
if (other !is VariableLivenessFrame) return false
return bitSet == other.bitSet && controlFlowMerge == other.controlFlowMerge
}
override fun hashCode() = bitSet.hashCode() * 31 + controlFlowMerge.hashCode()
override fun toString(): String =
(if (controlFlowMerge) "*" else " ") + (0 until maxLocals).map { if (bitSet[it]) '@' else '_' }.joinToString(separator = "")
}
fun analyzeLiveness(method: MethodNode): List =
analyze(method, object : BackwardAnalysisInterpreter {
override fun newFrame(maxLocals: Int) = VariableLivenessFrame(maxLocals)
override fun def(frame: VariableLivenessFrame, insn: AbstractInsnNode) = defVar(frame, insn)
override fun use(frame: VariableLivenessFrame, insn: AbstractInsnNode) =
useVar(frame, insn)
})
private fun defVar(frame: VariableLivenessFrame, insn: AbstractInsnNode) {
if (insn is VarInsnNode && insn.isStoreOperation()) {
frame.markDead(insn.`var`)
}
}
private fun useVar(frame: VariableLivenessFrame, insn: AbstractInsnNode) {
if (insn is VarInsnNode && insn.isLoadOperation()) {
frame.markAlive(insn.`var`)
} else if (insn is IincInsnNode) {
frame.markAlive(insn.`var`)
}
}