JVM use FastMethodAnalyzer when possible

This commit is contained in:
Dmitry Petrov
2021-07-09 13:08:13 +03:00
committed by teamcityserver
parent c54e680021
commit 68560c60f3
7 changed files with 20 additions and 15 deletions
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
@@ -85,7 +85,7 @@ private class UnitSourceInterpreter(private val localVariables: Set<Int>) : Basi
}
fun run(internalClassName: String, methodNode: MethodNode): Array<Frame<BasicValue>?> {
val frames = MethodAnalyzer<BasicValue>(internalClassName, methodNode, this).analyze()
val frames = FastMethodAnalyzer<BasicValue>(internalClassName, methodNode, this).analyze()
// The ASM analyzer does not visit POP instructions, so we do so here.
for ((insn, frame) in methodNode.instructions.asSequence().zip(frames.asSequence())) {
if (frame != null && insn.opcode == Opcodes.POP) {
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -130,11 +130,11 @@ internal fun performSpilledVariableFieldTypesAnalysis(
thisName: String
): Array<out Frame<BasicValue>?> {
val interpreter = IntLikeCoerceInterpreter()
MethodAnalyzer(thisName, methodNode, interpreter).analyze()
FastMethodAnalyzer(thisName, methodNode, interpreter).analyze()
for ((insn, type) in interpreter.needsToBeCoerced) {
methodNode.instructions.insert(insn, withInstructionAdapter { coerceInt(type, this) })
}
return MethodAnalyzer(thisName, methodNode, OptimizationBasicInterpreter()).analyze()
return FastMethodAnalyzer(thisName, methodNode, OptimizationBasicInterpreter()).analyze()
}
private fun coerceInt(to: Type, v: InstructionAdapter) {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
@@ -136,7 +137,7 @@ internal class Aload0Interpreter(private val node: MethodNode) : BasicInterprete
internal fun AbstractInsnNode.isAload0() = opcode == Opcodes.ALOAD && (this as VarInsnNode).`var` == 0
internal fun analyzeMethodNodeWithInterpreter(node: MethodNode, interpreter: BasicInterpreter): Array<out Frame<BasicValue>?> {
val analyzer = object : Analyzer<BasicValue>(interpreter) {
val analyzer = object : FastMethodAnalyzer<BasicValue>("fake", node, interpreter) {
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> {
return object : Frame<BasicValue>(nLocals, nStack) {
@@ -151,7 +152,7 @@ internal fun analyzeMethodNodeWithInterpreter(node: MethodNode, interpreter: Bas
}
try {
return analyzer.analyze("fake", node)
return analyzer.analyze()
} catch (e: AnalyzerException) {
throw RuntimeException(e)
}
@@ -17,13 +17,16 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.isLoadOperation
import org.jetbrains.kotlin.codegen.optimization.fixStack.peekWords
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
@@ -52,7 +55,7 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
private val dontTouchInsnIndices = BitSet(insns.size)
fun transform() {
val frames = Analyzer(HazardsTrackingInterpreter()).analyze("fake", methodNode)
val frames = FastMethodAnalyzer("fake", methodNode, HazardsTrackingInterpreter()).analyze()
for ((i, insn) in insns.withIndex()) {
val frame = frames[i] ?: continue
when (insn.opcode) {
@@ -12,8 +12,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
class ControlFlowGraph private constructor(private val insns: InsnList) {
private val edges: Array<MutableList<Int>> = Array(insns.size()) { arrayListOf<Int>() }
private val backwardEdges: Array<MutableList<Int>> = Array(insns.size()) { arrayListOf<Int>() }
private val edges: Array<MutableList<Int>> = Array(insns.size()) { ArrayList() }
private val backwardEdges: Array<MutableList<Int>> = Array(insns.size()) { ArrayList() }
fun getSuccessorsIndices(insn: AbstractInsnNode): List<Int> = getSuccessorsIndices(insns.indexOf(insn))
fun getSuccessorsIndices(index: Int): List<Int> = edges[index]
@@ -30,6 +30,7 @@ class ControlFlowGraph private constructor(private val insns: InsnList) {
graph.backwardEdges[to].add(from)
}
// TODO custom analyzer, no need to analyze data flow
object : MethodAnalyzer<BasicValue>("fake", node, OptimizationBasicInterpreter()) {
override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
addEdge(insn, successor)
@@ -24,6 +24,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
class CustomFramesMethodAnalyzer<V : Value>(
owner: String, method: MethodNode, interpreter: Interpreter<V>,
private val frameFactory: (Int, Int) -> Frame<V>
) : MethodAnalyzer<V>(owner, method, interpreter) {
) : FastMethodAnalyzer<V>(owner, method, interpreter) {
override fun newFrame(nLocals: Int, nStack: Int) = frameFactory(nLocals, nStack)
}
@@ -45,7 +45,7 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
@Suppress("DuplicatedCode")
class FastMethodAnalyzer<V : Value>(
open class FastMethodAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
private val interpreter: Interpreter<V>
@@ -87,7 +87,7 @@ class FastMethodAnalyzer<V : Value>(
private val queue = IntArray(nInsns)
private var top = 0
private fun newFrame(nLocals: Int, nStack: Int): Frame<V> =
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> =
Frame(nLocals, nStack)
fun analyze(): Array<Frame<V>?> {