Remove redundant continuation classes and INNERCLASS nodes

#KT-31339 Fixed
This commit is contained in:
Ilmir Usmanov
2019-05-06 21:29:49 +03:00
parent ccf2941f4a
commit 360e30c133
12 changed files with 875 additions and 99 deletions
@@ -141,7 +141,7 @@ class AnonymousObjectTransformer(
superClassName,
allCapturedParamBuilder.listCaptured()
)
loop@for (next in methodsToTransform) {
loop@ for (next in methodsToTransform) {
val deferringVisitor =
when {
coroutineTransformer.shouldSkip(next) -> continue@loop
@@ -162,9 +162,15 @@ class AnonymousObjectTransformer(
}
deferringMethods.forEach { method ->
val continuationToRemove = CoroutineTransformer.findFakeContinuationConstructorClassName(method.intermediate)
val oldContinuationName = coroutineTransformer.oldContinuationFrom(method.intermediate)
coroutineTransformer.replaceFakesWithReals(method.intermediate)
removeFinallyMarkers(method.intermediate)
method.visitEnd()
if (continuationToRemove != null && coroutineTransformer.safeToRemoveContinuationClass(method.intermediate)) {
transformationResult.addClassToRemove(continuationToRemove)
innerClassNodes.removeIf { it.name == oldContinuationName }
}
}
SourceMapper.flushToClassBuilder(sourceMapper, classBuilder)
@@ -215,6 +215,13 @@ class CoroutineTransformer(
fun unregisterClassBuilder(continuationClassName: String) =
(inliningContext as RegeneratedClassContext).continuationBuilders.remove(continuationClassName)
// If tail-call optimization took place, we do not need continuation class anymore, unless it is used by $$forInline method
fun safeToRemoveContinuationClass(method: MethodNode): Boolean = !generateForInline && !isStateMachine(method)
fun oldContinuationFrom(method: MethodNode): String? =
methods.find { it.name == method.name + FOR_INLINE_SUFFIX && it.desc == method.desc }
?.let { findFakeContinuationConstructorClassName(it) }
companion object {
fun findFakeContinuationConstructorClassName(node: MethodNode): String? {
val marker = node.instructions.asSequence().firstOrNull(::isBeforeFakeContinuationConstructorCallMarker) ?: return null