Adapt FixStackAnalyzer to code generated by coroutine transformation
Without this change internal error happens while inlining coroutine code with try/catch inside Also get rid of hack with SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC See comment within MethodAnalyzer for clarification
This commit is contained in:
-3
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.insnListOf
|
||||
@@ -70,8 +69,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
|
||||
processUninitializedStores(methodNode)
|
||||
|
||||
methodNode.visibleAnnotations.add(AnnotationNode(SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC))
|
||||
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
if (suspensionPoints.isEmpty()) return
|
||||
|
||||
|
||||
-5
@@ -20,16 +20,11 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransfor
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
val SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC = "Lkotlin/SkipMandatoryTransformations;"
|
||||
|
||||
class MandatoryMethodTransformer : MethodTransformer() {
|
||||
private val labelNormalization = LabelNormalizationMethodTransformer()
|
||||
private val fixStack = FixStackMethodTransformer()
|
||||
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
// Mandatory transformations have already been applied
|
||||
if (methodNode.visibleAnnotations?.removeAll { it.desc == SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC } == true) return
|
||||
|
||||
labelNormalization.transform(internalClassName, methodNode)
|
||||
fixStack.transform(internalClassName, methodNode)
|
||||
}
|
||||
|
||||
+6
-1
@@ -136,7 +136,12 @@ open class MethodAnalyzer<V : Value>(
|
||||
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
|
||||
var jump = instructions.indexOf(insnNode.dflt)
|
||||
processControlFlowEdge(current, insn, jump)
|
||||
for (label in insnNode.labels) {
|
||||
// In most cases order of visiting switch labels should not matter
|
||||
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
|
||||
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
|
||||
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
|
||||
// Using 'reversed' is because nodes are processed in LIFO order
|
||||
for (label in insnNode.labels.reversed()) {
|
||||
jump = instructions.indexOf(label)
|
||||
processControlFlowEdge(current, insn, jump)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
class Controller {
|
||||
suspend fun suspendHere(v: String, x: Continuation<String>) {
|
||||
x.resume(v)
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||
c(Controller()).resume(Unit)
|
||||
}
|
||||
|
||||
inline fun run(block: () -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = ""
|
||||
run {
|
||||
builder {
|
||||
try {
|
||||
result += suspendHere("O")
|
||||
} finally {
|
||||
result += suspendHere("K")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -4200,6 +4200,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryFinallyInsideInlineLambda.kt")
|
||||
public void testTryFinallyInsideInlineLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
||||
|
||||
Reference in New Issue
Block a user