Remove unreachable instructions
This commit is contained in:
+5
-14
@@ -573,11 +573,9 @@ class CoroutineTransformerMethodVisitor(
|
||||
return false
|
||||
}
|
||||
|
||||
val starts = methodNode.instructions.asSequence().filter {
|
||||
isBeforeSuspendMarker(it) &&
|
||||
cfg.getPredecessorsIndices(it).isNotEmpty() // Ignore unreachable start markers
|
||||
}.toList()
|
||||
return starts.mapNotNull { start ->
|
||||
return methodNode.instructions.asSequence().filter {
|
||||
isBeforeSuspendMarker(it)
|
||||
}.mapNotNull { start ->
|
||||
val ends = mutableSetOf<AbstractInsnNode>()
|
||||
if (collectSuspensionPointEnds(start, mutableSetOf(), ends)) return@mapNotNull null
|
||||
// Ignore suspension points, if the suspension call begin is alive and suspension call end is dead
|
||||
@@ -586,7 +584,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
// this is an exit point for the corresponding coroutine.
|
||||
val end = ends.find { isAfterSuspendMarker(it) } ?: return@mapNotNull null
|
||||
SuspensionPoint(start.previous, end)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private fun dropSuspensionMarkers(methodNode: MethodNode) {
|
||||
@@ -983,7 +981,7 @@ private class MethodNodeExaminer(
|
||||
val typedFrames = basicAnalyser.frames
|
||||
|
||||
val isReferenceMap = popsBeforeSafeUnitInstances
|
||||
.map { it to (!isUnreachable(it.index(), sourceFrames) && typedFrames[it.index()]?.top()?.isReference == true) }
|
||||
.map { it to (typedFrames[it.index()]?.top()?.isReference == true) }
|
||||
.toMap()
|
||||
|
||||
for (pop in popsBeforeSafeUnitInstances) {
|
||||
@@ -1008,8 +1006,6 @@ private class MethodNodeExaminer(
|
||||
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
|
||||
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
|
||||
|
||||
if (isUnreachable(endIndex, sourceFrames)) return@all true
|
||||
|
||||
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
|
||||
val tryBlockStartIndex = instructions.indexOf(block.start)
|
||||
val tryBlockEndIndex = instructions.indexOf(block.end)
|
||||
@@ -1043,7 +1039,6 @@ private class MethodNodeExaminer(
|
||||
val insn = insns[index]
|
||||
|
||||
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
|
||||
if (isUnreachable(index, sourceFrames)) return@init null
|
||||
return@init setOf(index)
|
||||
}
|
||||
|
||||
@@ -1215,10 +1210,6 @@ internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter(Opcode
|
||||
override fun copyOperation(insn: AbstractInsnNode?, value: SourceValue?) = value
|
||||
}
|
||||
|
||||
// Check whether this instruction is unreachable, i.e. there is no path leading to this instruction
|
||||
internal fun <T : Value> isUnreachable(index: Int, sourceFrames: Array<out Frame<out T>?>): Boolean =
|
||||
sourceFrames.size <= index || sourceFrames[index] == null
|
||||
|
||||
private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
|
||||
val insns = methodNode.instructions
|
||||
val index = insns.indexOf(this)
|
||||
|
||||
+10
@@ -121,6 +121,16 @@ internal class RedundantLocalsEliminationMethodTransformer(private val suspensio
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unreachable instructions to simplify further analyses
|
||||
for (index in frames.indices) {
|
||||
if (frames[index] == null) {
|
||||
val insn = methodNode.instructions[index]
|
||||
if (insn !is LabelNode) {
|
||||
toDelete.add(insn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
methodNode.instructions.removeAll(toDelete)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user