Support suspendCoroutineUninterceptedOrReturn intrinsic

KT-17336: Fixed
This commit is contained in:
Ilmir Usmanov
2017-10-27 21:03:17 +03:00
parent 4c583c5a61
commit 0fbbe10143
13 changed files with 420 additions and 8 deletions
@@ -172,7 +172,7 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
fun ResolvedCall<*>.isSuspendNoInlineCall() =
resultingDescriptor.safeAs<FunctionDescriptor>()
?.let {
it.isSuspend && (!it.isInline || it.isBuiltInSuspendCoroutineOrReturnInJvm())
it.isSuspend && (!it.isInline || it.isBuiltInSuspendCoroutineOrReturnInJvm() || it.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm())
} == true
fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
@@ -245,7 +245,6 @@ fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType) =
)
} ?: module.builtIns.nullableAnyType
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn() == true
@@ -289,6 +288,40 @@ fun createMethodNodeForSuspendCoroutineOrReturn(
return node
}
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true
fun createMethodNodeForIntercepted(
functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper
): MethodNode {
assert(functionDescriptor.isBuiltInIntercepted()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.intercepted"
}
val node =
MethodNode(
Opcodes.ASM5,
Opcodes.ACC_STATIC,
"fake",
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
)
node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitMethodInsn(
Opcodes.INVOKESTATIC,
INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME,
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE),
false
)
node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1)
return node
}
fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.coroutineContext property getter"
@@ -318,6 +351,39 @@ fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor):
return node
}
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper
): MethodNode {
assert(functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn"
}
val node =
MethodNode(
Opcodes.ASM5,
Opcodes.ACC_STATIC,
"fake",
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
)
node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitVarInsn(Opcodes.ALOAD, 1)
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.visitMaxs(2, 2)
return node
}
@Suppress("UNCHECKED_CAST")
fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.isBuiltInCoroutineContext
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
@@ -490,13 +491,23 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
}
functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() ->
return SMAPAndMethodNode(
createMethodNodeForSuspendCoroutineOrReturn(functionDescriptor, state.typeMapper),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
createMethodNodeForSuspendCoroutineOrReturn(functionDescriptor, state.typeMapper),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
)
functionDescriptor.isBuiltInIntercepted() ->
return SMAPAndMethodNode(
createMethodNodeForIntercepted(functionDescriptor, state.typeMapper),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
)
functionDescriptor.isBuiltInCoroutineContext() ->
return SMAPAndMethodNode(
createMethodNodeForCoroutineContext(functionDescriptor),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
createMethodNodeForCoroutineContext(functionDescriptor),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
)
functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() ->
return SMAPAndMethodNode(
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(functionDescriptor, state.typeMapper),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
)
}