Support new Continuation API in JVM BE

#KT-24863 Fixed
This commit is contained in:
Denis Zharkov
2018-06-28 18:54:21 +03:00
parent aee0afbff1
commit 170086250b
15 changed files with 249 additions and 80 deletions
@@ -422,7 +422,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
String superClassConstructorDescriptor;
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
superClassAsmType.equals(CoroutineCodegenUtilKt.coroutineImplAsmType(state.getLanguageVersionSettings()))) {
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())) {
int arity = calculateArity();
iv.iconst(arity);
if (shouldHaveBoundReferenceReceiver) {
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -688,7 +687,10 @@ public class FunctionCodegen {
}
} else {
FunctionDescriptor lambdaDescriptor = ((ClosureContext) context.getParentContext()).getOriginalSuspendLambdaDescriptor();
if (lambdaDescriptor != null && functionDescriptor.getName().equals(Name.identifier("doResume"))) {
if (lambdaDescriptor != null &&
CoroutineCodegenUtilKt.isResumeImplMethodName(
parentCodegen.state.getLanguageVersionSettings(), functionDescriptor.getName().asString()
)) {
destructuredParametersForSuspendLambda.addAll(lambdaDescriptor.getValueParameters());
}
}
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.codegen.coroutines.isSuspendLambdaOrLocalFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
@@ -34,7 +36,33 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
val functionReference: ClassDescriptor by klass("FunctionReference")
private val localVariableReference: ClassDescriptor by klass("LocalVariableReference")
private val mutableLocalVariableReference: ClassDescriptor by klass("MutableLocalVariableReference")
private val coroutineImplClass by lazy { createClass(kotlinCoroutinesJvmInternalPackage, "CoroutineImpl") }
private val coroutineImpl: ClassDescriptor by lazy {
createClass(kotlinCoroutinesJvmInternalPackage, "CoroutineImpl")
}
private val continuationImpl by lazy {
createCoroutineSuperClass("ContinuationImpl")
}
private val restrictedContinuationImpl by lazy {
createCoroutineSuperClass("RestrictedContinuationImpl")
}
private val suspendLambda by lazy {
createCoroutineSuperClass("SuspendLambda")
}
private val restrictedSuspendLambda by lazy {
createCoroutineSuperClass("RestrictedSuspendLambda")
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor {
return if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, className)
else
coroutineImpl
}
private val propertyReferences: List<ClassDescriptor> by lazy {
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "PropertyReference$i") }
@@ -76,8 +104,21 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
if (descriptor.isSuspend) {
return mutableListOf<KotlinType>().apply {
add(coroutineImplClass.defaultType)
if (descriptor.isSuspendLambda) {
if (actualFunctionDescriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true) {
if (descriptor.isSuspendLambdaOrLocalFunction()) {
add(restrictedSuspendLambda.defaultType)
} else {
add(restrictedContinuationImpl.defaultType)
}
} else {
if (descriptor.isSuspendLambdaOrLocalFunction()) {
add(suspendLambda.defaultType)
} else {
add(continuationImpl.defaultType)
}
}
if (descriptor.isSuspendLambdaOrLocalFunction()) {
add(functionType)
}
}
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
@@ -48,7 +49,7 @@ abstract class AbstractCoroutineCodegen(
element: KtElement,
closureContext: ClosureContext,
classBuilder: ClassBuilder,
userDataForDoResume: Map<out FunctionDescriptor.UserDataKey<*>, *>? = null
private val userDataForDoResume: Map<out FunctionDescriptor.UserDataKey<*>, *>? = null
) : ClosureCodegen(
outerExpressionCodegen.state,
element, null, closureContext, null,
@@ -58,19 +59,31 @@ abstract class AbstractCoroutineCodegen(
protected val classDescriptor = closureContext.contextDescriptor
protected val languageVersionSettings = outerExpressionCodegen.state.languageVersionSettings
protected val doResumeDescriptor =
protected val methodToImplement =
if (languageVersionSettings.isReleaseCoroutines())
createImplMethod(
INVOKE_SUSPEND_METHOD_NAME,
"result" to classDescriptor.module.getSuccessOrFailure(classDescriptor.builtIns.anyType)
)
else
createImplMethod(
DO_RESUME_METHOD_NAME,
"data" to classDescriptor.builtIns.nullableAnyType,
"throwable" to classDescriptor.builtIns.throwable.defaultType.makeNullable()
)
private fun createImplMethod(name: String, vararg parameters: Pair<String, KotlinType>) =
SimpleFunctionDescriptorImpl.create(
classDescriptor, Annotations.EMPTY, Name.identifier(DO_RESUME_METHOD_NAME), CallableMemberDescriptor.Kind.DECLARATION,
classDescriptor, Annotations.EMPTY, Name.identifier(name), CallableMemberDescriptor.Kind.DECLARATION,
funDescriptor.source
).apply doResume@{
).apply {
initialize(
null,
classDescriptor.thisAsReceiverParameter,
emptyList(),
listOf(
createValueParameterForDoResume(Name.identifier("data"), builtIns.nullableAnyType, 0),
createValueParameterForDoResume(Name.identifier("throwable"), builtIns.throwable.defaultType.makeNullable(), 1)
),
parameters.withIndex().map { (index, nameAndType) ->
createValueParameterForDoResume(Name.identifier(nameAndType.first), nameAndType.second, index)
},
builtIns.nullableAnyType,
Modality.FINAL,
Visibilities.PUBLIC,
@@ -104,13 +117,22 @@ abstract class AbstractCoroutineCodegen(
iv.generateClosureFieldsInitializationFromParameters(closure, args)
iv.load(0, AsmTypes.OBJECT_TYPE)
iv.iconst(if (passArityToSuperClass) calculateArity() else 0)
val hasArityParameter = !languageVersionSettings.isReleaseCoroutines() || passArityToSuperClass
if (hasArityParameter) {
iv.iconst(if (passArityToSuperClass) calculateArity() else 0)
}
iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE)
val parameters =
if (hasArityParameter)
listOf(Type.INT_TYPE, languageVersionSettings.continuationAsmType())
else
listOf(languageVersionSettings.continuationAsmType())
val superClassConstructorDescriptor = Type.getMethodDescriptor(
Type.VOID_TYPE,
Type.INT_TYPE,
languageVersionSettings.continuationAsmType()
*parameters.toTypedArray()
)
iv.invokespecial(superClassAsmType.internalName, "<init>", superClassConstructorDescriptor, false)
@@ -119,6 +141,10 @@ abstract class AbstractCoroutineCodegen(
FunctionCodegen.endVisit(iv, "constructor", element)
}
if (languageVersionSettings.isReleaseCoroutines()) {
v.newField(JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "label", "I", null, null)
}
return constructor
}
@@ -174,7 +200,7 @@ class CoroutineCodegenForLambda private constructor(
)
}
generateDoResume()
generateResumeImpl()
}
override fun generateBody() {
@@ -227,7 +253,11 @@ class CoroutineCodegenForLambda private constructor(
checkcast(Type.getObjectType(v.thisName))
// .doResume(Unit)
invokeDoResumeWithUnit(v.thisName)
if (languageVersionSettings.isReleaseCoroutines()) {
invokeInvokeSuspendWithUnit(v.thisName)
} else {
invokeDoResumeWithUnit(v.thisName)
}
areturn(AsmTypes.OBJECT_TYPE)
}
@@ -307,10 +337,10 @@ class CoroutineCodegenForLambda private constructor(
name
)
private fun generateDoResume() {
private fun generateResumeImpl() {
functionCodegen.generateMethod(
OtherOrigin(element),
doResumeDescriptor,
methodToImplement,
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
@@ -370,14 +400,18 @@ class CoroutineCodegenForNamedFunction private constructor(
classBuilder: ClassBuilder,
originalSuspendFunctionDescriptor: FunctionDescriptor
) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) {
private val labelFieldStackValue = StackValue.field(
FieldInfo.createForHiddenField(
outerExpressionCodegen.state.languageVersionSettings.coroutineImplAsmType(),
Type.INT_TYPE,
COROUTINE_LABEL_FIELD_NAME
),
StackValue.LOCAL_0
)
private val labelFieldStackValue by lazy {
StackValue.field(
FieldInfo.createForHiddenField(
computeLabelOwner(languageVersionSettings, v.thisName),
Type.INT_TYPE,
COROUTINE_LABEL_FIELD_NAME
),
StackValue.LOCAL_0
)
}
private val suspendFunctionJvmView =
bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!!
@@ -388,7 +422,7 @@ class CoroutineCodegenForNamedFunction private constructor(
}
override fun generateClosureBody() {
generateDoResume()
generateResumeImpl()
generateGetLabelMethod()
generateSetLabelMethod()
@@ -397,16 +431,19 @@ class CoroutineCodegenForNamedFunction private constructor(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor, null, null
)
v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor, null, null
)
if (!languageVersionSettings.isReleaseCoroutines()) {
v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor, null, null
)
}
}
private fun generateDoResume() {
private fun generateResumeImpl() {
functionCodegen.generateMethod(
OtherOrigin(element),
doResumeDescriptor,
methodToImplement,
object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
StackValue.field(
@@ -414,10 +451,12 @@ class CoroutineCodegenForNamedFunction private constructor(
StackValue.LOCAL_0
).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v)
StackValue.field(
AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false,
StackValue.LOCAL_0
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
if (!languageVersionSettings.isReleaseCoroutines()) {
StackValue.field(
AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false,
StackValue.LOCAL_0
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
}
labelFieldStackValue.store(
StackValue.operation(Type.INT_TYPE) {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransfor
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.sure
@@ -53,7 +54,7 @@ class CoroutineTransformerMethodVisitor(
private var continuationIndex = if (isForNamedFunction) -1 else 0
private var dataIndex = if (isForNamedFunction) -1 else 1
private var exceptionIndex = if (isForNamedFunction) -1 else 2
private var exceptionIndex = if (isForNamedFunction || languageVersionSettings.isReleaseCoroutines()) -1 else 2
override fun performTransformations(methodNode: MethodNode) {
removeFakeContinuationConstructorCall(methodNode)
@@ -81,7 +82,9 @@ class CoroutineTransformerMethodVisitor(
}
dataIndex = methodNode.maxLocals++
exceptionIndex = methodNode.maxLocals++
if (!languageVersionSettings.isReleaseCoroutines()) {
exceptionIndex = methodNode.maxLocals++
}
continuationIndex = methodNode.maxLocals++
prepareMethodNodePreludeForNamedFunction(methodNode)
@@ -136,7 +139,9 @@ class CoroutineTransformerMethodVisitor(
)
)
insert(startLabel, withInstructionAdapter { generateResumeWithExceptionCheck(exceptionIndex) })
insert(startLabel, withInstructionAdapter {
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
})
insert(last, defaultLabel)
insert(last, withInstructionAdapter {
@@ -161,7 +166,7 @@ class CoroutineTransformerMethodVisitor(
}
private fun createInsnForReadingLabel() =
if (isForNamedFunction)
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
classBuilderForCoroutineState.thisName,
@@ -172,12 +177,12 @@ class CoroutineTransformerMethodVisitor(
else
FieldInsnNode(
Opcodes.GETFIELD,
languageVersionSettings.coroutineImplAsmType().internalName,
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
private fun createInsnForSettingLabel() =
if (isForNamedFunction)
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
classBuilderForCoroutineState.thisName,
@@ -188,7 +193,7 @@ class CoroutineTransformerMethodVisitor(
else
FieldInsnNode(
Opcodes.PUTFIELD,
languageVersionSettings.coroutineImplAsmType().internalName,
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
@@ -294,9 +299,11 @@ class CoroutineTransformerMethodVisitor(
getfield(classBuilderForCoroutineState.thisName, DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, dataIndex)
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
if (!languageVersionSettings.isReleaseCoroutines()) {
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
}
})
}
@@ -517,7 +524,7 @@ class CoroutineTransformerMethodVisitor(
remove(possibleTryCatchBlockStart.previous)
insert(possibleTryCatchBlockStart, withInstructionAdapter {
generateResumeWithExceptionCheck(exceptionIndex)
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
// Load continuation argument just like suspending function returns it
load(dataIndex, AsmTypes.OBJECT_TYPE)
@@ -628,12 +635,21 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
)
}
private fun InstructionAdapter.generateResumeWithExceptionCheck(exceptionIndex: Int) {
private fun InstructionAdapter.generateResumeWithExceptionCheck(isReleaseCoroutines: Boolean, dataIndex: Int, exceptionIndex: Int) {
// Check if resumeWithException has been called
load(exceptionIndex, AsmTypes.OBJECT_TYPE)
load(if (isReleaseCoroutines) dataIndex else exceptionIndex, AsmTypes.OBJECT_TYPE)
dup()
val noExceptionLabel = Label()
ifnull(noExceptionLabel)
if (isReleaseCoroutines) {
instanceOf(AsmTypes.SUCCESS_OR_FAILURE_FAILURE)
ifeq(noExceptionLabel)
// TODO: do we need this checkcast?
checkcast(AsmTypes.SUCCESS_OR_FAILURE_FAILURE)
getfield(AsmTypes.SUCCESS_OR_FAILURE_FAILURE.internalName, "exception", AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
} else {
ifnull(noExceptionLabel)
}
athrow()
mark(noExceptionLabel)
@@ -823,4 +839,4 @@ private fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continu
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex))
}
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -37,7 +38,9 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
@@ -53,9 +56,18 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
const val COROUTINE_LABEL_FIELD_NAME = "label"
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
const val DO_RESUME_METHOD_NAME = "doResume"
const val INVOKE_SUSPEND_METHOD_NAME = "invokeSuspend"
const val DATA_FIELD_NAME = "data"
const val EXCEPTION_FIELD_NAME = "exception"
fun LanguageVersionSettings.isResumeImplMethodName(name: String) =
if (isReleaseCoroutines())
name == INVOKE_SUSPEND_METHOD_NAME
else
name == DO_RESUME_METHOD_NAME
fun isResumeImplMethodNameFromAnyLanguageSettings(name: String) = name == INVOKE_SUSPEND_METHOD_NAME || name == DO_RESUME_METHOD_NAME
fun LanguageVersionSettings.coroutinesJvmInternalPackageFqName() =
coroutinesPackageFqName().child(Name.identifier("jvm")).child(Name.identifier("internal"))
@@ -70,8 +82,19 @@ fun continuationAsmTypes() = listOf(
fun LanguageVersionSettings.coroutineContextAsmType() =
coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
fun LanguageVersionSettings.coroutineImplAsmType() =
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
fun LanguageVersionSettings.isCoroutineSuperClass(internalName: String): Boolean {
val coroutinesJvmInternalPackage = coroutinesJvmInternalPackageFqName()
return if (isReleaseCoroutines())
coroutinesJvmInternalPackage.identifiedChild("ContinuationImpl") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("RestrictedContinuationImpl") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("SuspendLambda") == internalName ||
coroutinesJvmInternalPackage.identifiedChild("RestrictedSuspendLambda") == internalName
else
coroutinesJvmInternalPackage.identifiedChild("CoroutineImpl") == internalName
}
private fun FqName.identifiedChild(name: String) = child(Name.identifier(name)).topLevelClassInternalName()
private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName() =
coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
@@ -79,6 +102,12 @@ private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName()
private fun LanguageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName() =
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName()
fun computeLabelOwner(languageVersionSettings: LanguageVersionSettings, thisName: String): Type =
if (languageVersionSettings.isReleaseCoroutines())
Type.getObjectType(thisName)
else
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
private val GET_CONTEXT_METHOD_NAME = "getContext"
@@ -284,6 +313,17 @@ fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleas
)
} ?: module.builtIns.nullableAnyType
fun ModuleDescriptor.getSuccessOrFailure(kotlinType: KotlinType) =
module.resolveTopLevelClass(
DescriptorUtils.SUCCESS_OR_FAILURE_FQ_NAME,
NoLookupLocation.FROM_BACKEND
)?.defaultType?.let {
KotlinTypeFactory.simpleType(
it,
arguments = listOf(kotlinType.asTypeProjection())
)
} ?: ErrorUtils.createErrorType("For SuccessOrFailure")
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings) == true
@@ -470,6 +510,17 @@ fun InstructionAdapter.invokeDoResumeWithUnit(thisName: String) {
)
}
fun InstructionAdapter.invokeInvokeSuspendWithUnit(thisName: String) {
StackValue.putUnitInstance(this)
invokevirtual(
thisName,
INVOKE_SUSPEND_METHOD_NAME,
Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE, AsmTypes.OBJECT_TYPE),
false
)
}
fun Method.getImplForOpenMethod(ownerInternalName: String) =
Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes)
@@ -10,17 +10,18 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.codegen.coroutines.isResumeImplMethodName
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
import org.jetbrains.kotlin.codegen.coroutines.coroutineImplAsmType
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
@@ -55,7 +56,7 @@ class AnonymousObjectTransformer(
createClassReader().accept(object : ClassVisitor(API, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
if (languageVersionSettings.coroutineImplAsmType().internalName == superName) {
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
inliningContext.isContinuation = true
}
}
@@ -152,7 +153,7 @@ class AnonymousObjectTransformer(
// 2) Suspend named function
// Iff it captures crossinline suspend lambda
val generateStateMachineForLambda =
next.name == "doResume" && capturesCrossinlineSuspend && inliningContext.isContinuation &&
languageVersionSettings.isResumeImplMethodName(next.name) && capturesCrossinlineSuspend && inliningContext.isContinuation &&
!isLambdaAlreadyGeneratedAndNotGoingToBeInlined && hasLambdasToInline
val continuationClassName = findFakeContinuationConstructorClassName(next)
val generateStateMachineForNamedFunction =