JVM prune exception edges in inliner-specific DFA

This commit is contained in:
Dmitry Petrov
2022-03-03 19:11:40 +03:00
committed by Space
parent 254ada88d1
commit 78be4f302a
3 changed files with 17 additions and 14 deletions
@@ -467,12 +467,9 @@ class MethodInliner(
replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode)
val toDelete = SmartSet.create<AbstractInsnNode>()
val sources = analyzeMethodNodeWithInterpreter(processingNode, FunctionalArgumentInterpreter(this))
val instructions = processingNode.instructions
markObsoleteInstruction(instructions, toDelete, sources)
val toDelete = markObsoleteInstruction(instructions, sources)
var awaitClassReification = false
var currentFinallyDeep = 0
@@ -625,11 +622,9 @@ class MethodInliner(
return processingNode
}
private fun MethodInliner.markObsoleteInstruction(
instructions: InsnList,
toDelete: SmartSet<AbstractInsnNode>,
sources: Array<out Frame<BasicValue>?>
) {
private fun markObsoleteInstruction(instructions: InsnList, sources: Array<out Frame<BasicValue>?>): SmartSet<AbstractInsnNode> {
val toDelete = SmartSet.create<AbstractInsnNode>()
for (insn in instructions) {
// Parameter checks are processed separately
if (insn.isAloadBeforeCheckParameterIsNotNull()) continue
@@ -658,6 +653,8 @@ class MethodInliner(
}
}
}
return toDelete
}
// Replace ALOAD 0
@@ -110,10 +110,12 @@ 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 : FastMethodAnalyzer<BasicValue>("fake", node, interpreter) {
internal fun analyzeMethodNodeWithInterpreter(
node: MethodNode,
interpreter: BasicInterpreter
): Array<out Frame<BasicValue>?> {
val analyzer = object : FastMethodAnalyzer<BasicValue>("fake", node, interpreter, pruneExceptionEdges = true) {
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> {
return object : Frame<BasicValue>(nLocals, nStack) {
@Throws(AnalyzerException::class)
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
@@ -78,7 +78,7 @@ open class FastMethodAnalyzer<V : Value>
val isTcbStart = BooleanArray(nInsns)
for (tcb in method.tryCatchBlocks) {
isTcbStart[tcb.start.indexOf()] = true
isTcbStart[tcb.start.indexOf() + 1] = true
}
val current = newFrame(method.maxLocals, method.maxStack)
@@ -118,7 +118,11 @@ open class FastMethodAnalyzer<V : Value>
// So, unless we have a store operation, anything we change on stack would be lost,
// and there's no need to analyze exception handler again.
// Add an exception edge from TCB start to make sure handler itself is still visited.
if (!pruneExceptionEdges || insnOpcode in Opcodes.ISTORE..Opcodes.ASTORE || insnOpcode == Opcodes.IINC || isTcbStart[insn]) {
if (!pruneExceptionEdges ||
insnOpcode in Opcodes.ISTORE..Opcodes.ASTORE ||
insnOpcode == Opcodes.IINC ||
isTcbStart[insn]
) {
handlers[insn]?.forEach { tcb ->
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
val jump = tcb.handler.indexOf()