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.*
|
||||||
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer
|
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.OptimizationBasicInterpreter
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.insnListOf
|
import org.jetbrains.kotlin.codegen.optimization.common.insnListOf
|
||||||
@@ -70,8 +69,6 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
processUninitializedStores(methodNode)
|
processUninitializedStores(methodNode)
|
||||||
|
|
||||||
methodNode.visibleAnnotations.add(AnnotationNode(SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC))
|
|
||||||
|
|
||||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||||
if (suspensionPoints.isEmpty()) return
|
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.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
val SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC = "Lkotlin/SkipMandatoryTransformations;"
|
|
||||||
|
|
||||||
class MandatoryMethodTransformer : MethodTransformer() {
|
class MandatoryMethodTransformer : MethodTransformer() {
|
||||||
private val labelNormalization = LabelNormalizationMethodTransformer()
|
private val labelNormalization = LabelNormalizationMethodTransformer()
|
||||||
private val fixStack = FixStackMethodTransformer()
|
private val fixStack = FixStackMethodTransformer()
|
||||||
|
|
||||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
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)
|
labelNormalization.transform(internalClassName, methodNode)
|
||||||
fixStack.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) {
|
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
|
||||||
var jump = instructions.indexOf(insnNode.dflt)
|
var jump = instructions.indexOf(insnNode.dflt)
|
||||||
processControlFlowEdge(current, insn, jump)
|
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)
|
jump = instructions.indexOf(label)
|
||||||
processControlFlowEdge(current, insn, jump)
|
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");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
||||||
|
|||||||
Reference in New Issue
Block a user