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