Remove unreachable instructions
This commit is contained in:
+5
-14
@@ -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)
|
||||||
|
|||||||
+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)
|
methodNode.instructions.removeAll(toDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user