Generate probeCoroutineSuspended call in suspendCoroutineUninterceptedOrReturn
#KT-25508: Fixed
This commit is contained in:
+33
-14
@@ -10,14 +10,11 @@ import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
|
|||||||
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
|
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
|
||||||
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
|
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
|
||||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker
|
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.codegen.topLevelClassAsmType
|
|
||||||
import org.jetbrains.kotlin.codegen.topLevelClassInternalName
|
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -46,6 +43,7 @@ import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
@@ -395,18 +393,39 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
|
|||||||
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
|
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
|
||||||
)
|
)
|
||||||
|
|
||||||
node.visitVarInsn(Opcodes.ALOAD, 0)
|
with(InstructionAdapter(node)) {
|
||||||
node.visitVarInsn(Opcodes.ALOAD, 1)
|
load(0, AsmTypes.OBJECT_TYPE) // block
|
||||||
|
load(1, AsmTypes.OBJECT_TYPE) // continuation
|
||||||
|
|
||||||
|
// block.invoke(continuation)
|
||||||
|
invokeinterface(
|
||||||
|
typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName,
|
||||||
|
OperatorNameConventions.INVOKE.identifier,
|
||||||
|
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) {
|
||||||
|
val elseLabel = Label()
|
||||||
|
// if (result === COROUTINE_SUSPENDED) {
|
||||||
|
dup()
|
||||||
|
loadCoroutineSuspendedMarker(languageVersionSettings)
|
||||||
|
ifacmpne(elseLabel)
|
||||||
|
// DebugProbesKt.probeCoroutineSuspended(continuation)
|
||||||
|
load(1, AsmTypes.OBJECT_TYPE) // continuation
|
||||||
|
checkcast(languageVersionSettings.continuationAsmType())
|
||||||
|
invokestatic(
|
||||||
|
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("DebugProbesKt")).topLevelClassAsmType().internalName,
|
||||||
|
"probeCoroutineSuspended",
|
||||||
|
"(${languageVersionSettings.continuationAsmType()})V",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
// }
|
||||||
|
mark(elseLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node.visitMethodInsn(
|
|
||||||
Opcodes.INVOKEINTERFACE,
|
|
||||||
typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName,
|
|
||||||
OperatorNameConventions.INVOKE.identifier,
|
|
||||||
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
node.visitInsn(Opcodes.ARETURN)
|
node.visitInsn(Opcodes.ARETURN)
|
||||||
node.visitMaxs(2, 2)
|
node.visitMaxs(3, 2)
|
||||||
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.3
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// TREAT_AS_ONE_FILE
|
||||||
|
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
|
suspend fun suspended() = suspendCoroutineUninterceptedOrReturn<Int> { cont ->
|
||||||
|
cont.resume(0)
|
||||||
|
COROUTINE_SUSPENDED
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun simpleReturn() = suspendCoroutineUninterceptedOrReturn<Int> { cont ->
|
||||||
|
cont.resume(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 INVOKESTATIC kotlin/coroutines/jvm/internal/DebugProbesKt.probeCoroutineSuspended
|
||||||
@@ -1102,6 +1102,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable_1_2.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable_1_2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/debug")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Debug extends AbstractBytecodeTextTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDebug() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/coroutines/debug"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("probeCoroutineSuspended.kt")
|
||||||
|
public void testProbeCoroutineSuspended() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/debug/probeCoroutineSuspended.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/destructuringInLambda")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/destructuringInLambda")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user