Remove unreachable instructions

This commit is contained in:
Ilmir Usmanov
2020-05-19 19:42:21 +02:00
parent ea60b83f16
commit 3fa9ea9bc0
2 changed files with 15 additions and 14 deletions
@@ -573,11 +573,9 @@ class CoroutineTransformerMethodVisitor(
return false return false
} }
val starts = methodNode.instructions.asSequence().filter { return methodNode.instructions.asSequence().filter {
isBeforeSuspendMarker(it) && isBeforeSuspendMarker(it)
cfg.getPredecessorsIndices(it).isNotEmpty() // Ignore unreachable start markers }.mapNotNull { start ->
}.toList()
return starts.mapNotNull { start ->
val ends = mutableSetOf<AbstractInsnNode>() val ends = mutableSetOf<AbstractInsnNode>()
if (collectSuspensionPointEnds(start, mutableSetOf(), ends)) return@mapNotNull null if (collectSuspensionPointEnds(start, mutableSetOf(), ends)) return@mapNotNull null
// Ignore suspension points, if the suspension call begin is alive and suspension call end is dead // 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. // this is an exit point for the corresponding coroutine.
val end = ends.find { isAfterSuspendMarker(it) } ?: return@mapNotNull null val end = ends.find { isAfterSuspendMarker(it) } ?: return@mapNotNull null
SuspensionPoint(start.previous, end) SuspensionPoint(start.previous, end)
} }.toList()
} }
private fun dropSuspensionMarkers(methodNode: MethodNode) { private fun dropSuspensionMarkers(methodNode: MethodNode) {
@@ -983,7 +981,7 @@ private class MethodNodeExaminer(
val typedFrames = basicAnalyser.frames val typedFrames = basicAnalyser.frames
val isReferenceMap = popsBeforeSafeUnitInstances 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() .toMap()
for (pop in popsBeforeSafeUnitInstances) { for (pop in popsBeforeSafeUnitInstances) {
@@ -1008,8 +1006,6 @@ private class MethodNodeExaminer(
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin) val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd) val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
if (isUnreachable(endIndex, sourceFrames)) return@all true
val insideTryBlock = methodNode.tryCatchBlocks.any { block -> val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
val tryBlockStartIndex = instructions.indexOf(block.start) val tryBlockStartIndex = instructions.indexOf(block.start)
val tryBlockEndIndex = instructions.indexOf(block.end) val tryBlockEndIndex = instructions.indexOf(block.end)
@@ -1043,7 +1039,6 @@ private class MethodNodeExaminer(
val insn = insns[index] val insn = insns[index]
if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) { if (insn.opcode == Opcodes.ARETURN && !insn.isAreturnAfterSafeUnitInstance()) {
if (isUnreachable(index, sourceFrames)) return@init null
return@init setOf(index) return@init setOf(index)
} }
@@ -1215,10 +1210,6 @@ internal class IgnoringCopyOperationSourceInterpreter : SourceInterpreter(Opcode
override fun copyOperation(insn: AbstractInsnNode?, value: SourceValue?) = value 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 { private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode): Boolean {
val insns = methodNode.instructions val insns = methodNode.instructions
val index = insns.indexOf(this) val index = insns.indexOf(this)
@@ -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) methodNode.instructions.removeAll(toDelete)
} }