Support new Continuation API in JVM BE
#KT-24863 Fixed
This commit is contained in:
+4
-3
@@ -5,14 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||||
|
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|
||||||
|
|
||||||
val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn")
|
val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn")
|
||||||
val INTERCEPTED_NAME = Name.identifier("intercepted")
|
val INTERCEPTED_NAME = Name.identifier("intercepted")
|
||||||
@@ -21,7 +22,7 @@ val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
|
|||||||
val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn")
|
val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn")
|
||||||
|
|
||||||
fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean {
|
fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||||
if (name != INTERCEPTED_NAME) return false
|
if (name != INTERCEPTED_NAME || languageVersionSettings.isReleaseCoroutines()) return false
|
||||||
val original =
|
val original =
|
||||||
module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
|
module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
|
||||||
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
|
||||||
@@ -30,7 +31,7 @@ fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
|
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||||
if (name != SUSPEND_COROUTINE_OR_RETURN_NAME) return false
|
if (name != SUSPEND_COROUTINE_OR_RETURN_NAME || languageVersionSettings.isReleaseCoroutines()) return false
|
||||||
|
|
||||||
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn(languageVersionSettings) ?: return false
|
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn(languageVersionSettings) ?: return false
|
||||||
|
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
|||||||
|
|
||||||
String superClassConstructorDescriptor;
|
String superClassConstructorDescriptor;
|
||||||
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
|
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
|
||||||
superClassAsmType.equals(CoroutineCodegenUtilKt.coroutineImplAsmType(state.getLanguageVersionSettings()))) {
|
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())) {
|
||||||
int arity = calculateArity();
|
int arity = calculateArity();
|
||||||
iv.iconst(arity);
|
iv.iconst(arity);
|
||||||
if (shouldHaveBoundReferenceReceiver) {
|
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.SpecialBuiltinMembers;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
@@ -688,7 +687,10 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FunctionDescriptor lambdaDescriptor = ((ClosureContext) context.getParentContext()).getOriginalSuspendLambdaDescriptor();
|
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());
|
destructuredParametersForSuspendLambda.addAll(lambdaDescriptor.getValueParameters());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.codegen
|
|||||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
|
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
|
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.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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
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.descriptors.impl.MutablePackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -34,7 +36,33 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
|
|||||||
val functionReference: ClassDescriptor by klass("FunctionReference")
|
val functionReference: ClassDescriptor by klass("FunctionReference")
|
||||||
private val localVariableReference: ClassDescriptor by klass("LocalVariableReference")
|
private val localVariableReference: ClassDescriptor by klass("LocalVariableReference")
|
||||||
private val mutableLocalVariableReference: ClassDescriptor by klass("MutableLocalVariableReference")
|
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 {
|
private val propertyReferences: List<ClassDescriptor> by lazy {
|
||||||
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "PropertyReference$i") }
|
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "PropertyReference$i") }
|
||||||
@@ -76,8 +104,21 @@ class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSetti
|
|||||||
|
|
||||||
if (descriptor.isSuspend) {
|
if (descriptor.isSuspend) {
|
||||||
return mutableListOf<KotlinType>().apply {
|
return mutableListOf<KotlinType>().apply {
|
||||||
add(coroutineImplClass.defaultType)
|
if (actualFunctionDescriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true) {
|
||||||
if (descriptor.isSuspendLambda) {
|
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)
|
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.context.MethodContext
|
||||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
@@ -48,7 +49,7 @@ abstract class AbstractCoroutineCodegen(
|
|||||||
element: KtElement,
|
element: KtElement,
|
||||||
closureContext: ClosureContext,
|
closureContext: ClosureContext,
|
||||||
classBuilder: ClassBuilder,
|
classBuilder: ClassBuilder,
|
||||||
userDataForDoResume: Map<out FunctionDescriptor.UserDataKey<*>, *>? = null
|
private val userDataForDoResume: Map<out FunctionDescriptor.UserDataKey<*>, *>? = null
|
||||||
) : ClosureCodegen(
|
) : ClosureCodegen(
|
||||||
outerExpressionCodegen.state,
|
outerExpressionCodegen.state,
|
||||||
element, null, closureContext, null,
|
element, null, closureContext, null,
|
||||||
@@ -58,19 +59,31 @@ abstract class AbstractCoroutineCodegen(
|
|||||||
protected val classDescriptor = closureContext.contextDescriptor
|
protected val classDescriptor = closureContext.contextDescriptor
|
||||||
protected val languageVersionSettings = outerExpressionCodegen.state.languageVersionSettings
|
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(
|
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
|
funDescriptor.source
|
||||||
).apply doResume@{
|
).apply {
|
||||||
initialize(
|
initialize(
|
||||||
null,
|
null,
|
||||||
classDescriptor.thisAsReceiverParameter,
|
classDescriptor.thisAsReceiverParameter,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
listOf(
|
parameters.withIndex().map { (index, nameAndType) ->
|
||||||
createValueParameterForDoResume(Name.identifier("data"), builtIns.nullableAnyType, 0),
|
createValueParameterForDoResume(Name.identifier(nameAndType.first), nameAndType.second, index)
|
||||||
createValueParameterForDoResume(Name.identifier("throwable"), builtIns.throwable.defaultType.makeNullable(), 1)
|
},
|
||||||
),
|
|
||||||
builtIns.nullableAnyType,
|
builtIns.nullableAnyType,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.PUBLIC,
|
Visibilities.PUBLIC,
|
||||||
@@ -104,13 +117,22 @@ abstract class AbstractCoroutineCodegen(
|
|||||||
iv.generateClosureFieldsInitializationFromParameters(closure, args)
|
iv.generateClosureFieldsInitializationFromParameters(closure, args)
|
||||||
|
|
||||||
iv.load(0, AsmTypes.OBJECT_TYPE)
|
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)
|
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(
|
val superClassConstructorDescriptor = Type.getMethodDescriptor(
|
||||||
Type.VOID_TYPE,
|
Type.VOID_TYPE,
|
||||||
Type.INT_TYPE,
|
*parameters.toTypedArray()
|
||||||
languageVersionSettings.continuationAsmType()
|
|
||||||
)
|
)
|
||||||
iv.invokespecial(superClassAsmType.internalName, "<init>", superClassConstructorDescriptor, false)
|
iv.invokespecial(superClassAsmType.internalName, "<init>", superClassConstructorDescriptor, false)
|
||||||
|
|
||||||
@@ -119,6 +141,10 @@ abstract class AbstractCoroutineCodegen(
|
|||||||
FunctionCodegen.endVisit(iv, "constructor", element)
|
FunctionCodegen.endVisit(iv, "constructor", element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (languageVersionSettings.isReleaseCoroutines()) {
|
||||||
|
v.newField(JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "label", "I", null, null)
|
||||||
|
}
|
||||||
|
|
||||||
return constructor
|
return constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +200,7 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
generateDoResume()
|
generateResumeImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateBody() {
|
override fun generateBody() {
|
||||||
@@ -227,7 +253,11 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
checkcast(Type.getObjectType(v.thisName))
|
checkcast(Type.getObjectType(v.thisName))
|
||||||
|
|
||||||
// .doResume(Unit)
|
// .doResume(Unit)
|
||||||
invokeDoResumeWithUnit(v.thisName)
|
if (languageVersionSettings.isReleaseCoroutines()) {
|
||||||
|
invokeInvokeSuspendWithUnit(v.thisName)
|
||||||
|
} else {
|
||||||
|
invokeDoResumeWithUnit(v.thisName)
|
||||||
|
}
|
||||||
areturn(AsmTypes.OBJECT_TYPE)
|
areturn(AsmTypes.OBJECT_TYPE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,10 +337,10 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
name
|
name
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun generateDoResume() {
|
private fun generateResumeImpl() {
|
||||||
functionCodegen.generateMethod(
|
functionCodegen.generateMethod(
|
||||||
OtherOrigin(element),
|
OtherOrigin(element),
|
||||||
doResumeDescriptor,
|
methodToImplement,
|
||||||
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
||||||
|
|
||||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||||
@@ -370,14 +400,18 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
classBuilder: ClassBuilder,
|
classBuilder: ClassBuilder,
|
||||||
originalSuspendFunctionDescriptor: FunctionDescriptor
|
originalSuspendFunctionDescriptor: FunctionDescriptor
|
||||||
) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) {
|
) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) {
|
||||||
private val labelFieldStackValue = StackValue.field(
|
private val labelFieldStackValue by lazy {
|
||||||
FieldInfo.createForHiddenField(
|
StackValue.field(
|
||||||
outerExpressionCodegen.state.languageVersionSettings.coroutineImplAsmType(),
|
FieldInfo.createForHiddenField(
|
||||||
Type.INT_TYPE,
|
computeLabelOwner(languageVersionSettings, v.thisName),
|
||||||
COROUTINE_LABEL_FIELD_NAME
|
Type.INT_TYPE,
|
||||||
),
|
COROUTINE_LABEL_FIELD_NAME
|
||||||
StackValue.LOCAL_0
|
),
|
||||||
)
|
StackValue.LOCAL_0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private val suspendFunctionJvmView =
|
private val suspendFunctionJvmView =
|
||||||
bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!!
|
bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!!
|
||||||
|
|
||||||
@@ -388,7 +422,7 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun generateClosureBody() {
|
override fun generateClosureBody() {
|
||||||
generateDoResume()
|
generateResumeImpl()
|
||||||
|
|
||||||
generateGetLabelMethod()
|
generateGetLabelMethod()
|
||||||
generateSetLabelMethod()
|
generateSetLabelMethod()
|
||||||
@@ -397,16 +431,19 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
||||||
DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor, null, null
|
DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor, null, null
|
||||||
)
|
)
|
||||||
v.newField(
|
|
||||||
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
|
if (!languageVersionSettings.isReleaseCoroutines()) {
|
||||||
EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDoResume() {
|
private fun generateResumeImpl() {
|
||||||
functionCodegen.generateMethod(
|
functionCodegen.generateMethod(
|
||||||
OtherOrigin(element),
|
OtherOrigin(element),
|
||||||
doResumeDescriptor,
|
methodToImplement,
|
||||||
object : FunctionGenerationStrategy.CodegenBased(state) {
|
object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||||
StackValue.field(
|
StackValue.field(
|
||||||
@@ -414,10 +451,12 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
StackValue.LOCAL_0
|
StackValue.LOCAL_0
|
||||||
).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v)
|
).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v)
|
||||||
|
|
||||||
StackValue.field(
|
if (!languageVersionSettings.isReleaseCoroutines()) {
|
||||||
AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false,
|
StackValue.field(
|
||||||
StackValue.LOCAL_0
|
AsmTypes.JAVA_THROWABLE_TYPE, Type.getObjectType(v.thisName), EXCEPTION_FIELD_NAME, false,
|
||||||
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
|
StackValue.LOCAL_0
|
||||||
|
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
|
||||||
|
}
|
||||||
|
|
||||||
labelFieldStackValue.store(
|
labelFieldStackValue.store(
|
||||||
StackValue.operation(Type.INT_TYPE) {
|
StackValue.operation(Type.INT_TYPE) {
|
||||||
|
|||||||
+31
-15
@@ -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.fixStack.top
|
||||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
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.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
@@ -53,7 +54,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
private var continuationIndex = if (isForNamedFunction) -1 else 0
|
private var continuationIndex = if (isForNamedFunction) -1 else 0
|
||||||
private var dataIndex = if (isForNamedFunction) -1 else 1
|
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) {
|
override fun performTransformations(methodNode: MethodNode) {
|
||||||
removeFakeContinuationConstructorCall(methodNode)
|
removeFakeContinuationConstructorCall(methodNode)
|
||||||
@@ -81,7 +82,9 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataIndex = methodNode.maxLocals++
|
dataIndex = methodNode.maxLocals++
|
||||||
exceptionIndex = methodNode.maxLocals++
|
if (!languageVersionSettings.isReleaseCoroutines()) {
|
||||||
|
exceptionIndex = methodNode.maxLocals++
|
||||||
|
}
|
||||||
continuationIndex = methodNode.maxLocals++
|
continuationIndex = methodNode.maxLocals++
|
||||||
|
|
||||||
prepareMethodNodePreludeForNamedFunction(methodNode)
|
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, defaultLabel)
|
||||||
|
|
||||||
insert(last, withInstructionAdapter {
|
insert(last, withInstructionAdapter {
|
||||||
@@ -161,7 +166,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createInsnForReadingLabel() =
|
private fun createInsnForReadingLabel() =
|
||||||
if (isForNamedFunction)
|
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
|
||||||
MethodInsnNode(
|
MethodInsnNode(
|
||||||
Opcodes.INVOKEVIRTUAL,
|
Opcodes.INVOKEVIRTUAL,
|
||||||
classBuilderForCoroutineState.thisName,
|
classBuilderForCoroutineState.thisName,
|
||||||
@@ -172,12 +177,12 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
else
|
else
|
||||||
FieldInsnNode(
|
FieldInsnNode(
|
||||||
Opcodes.GETFIELD,
|
Opcodes.GETFIELD,
|
||||||
languageVersionSettings.coroutineImplAsmType().internalName,
|
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
|
||||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createInsnForSettingLabel() =
|
private fun createInsnForSettingLabel() =
|
||||||
if (isForNamedFunction)
|
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
|
||||||
MethodInsnNode(
|
MethodInsnNode(
|
||||||
Opcodes.INVOKEVIRTUAL,
|
Opcodes.INVOKEVIRTUAL,
|
||||||
classBuilderForCoroutineState.thisName,
|
classBuilderForCoroutineState.thisName,
|
||||||
@@ -188,7 +193,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
else
|
else
|
||||||
FieldInsnNode(
|
FieldInsnNode(
|
||||||
Opcodes.PUTFIELD,
|
Opcodes.PUTFIELD,
|
||||||
languageVersionSettings.coroutineImplAsmType().internalName,
|
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
|
||||||
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -294,9 +299,11 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
getfield(classBuilderForCoroutineState.thisName, DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor)
|
getfield(classBuilderForCoroutineState.thisName, DATA_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor)
|
||||||
visitVarInsn(Opcodes.ASTORE, dataIndex)
|
visitVarInsn(Opcodes.ASTORE, dataIndex)
|
||||||
|
|
||||||
visitVarInsn(Opcodes.ALOAD, continuationIndex)
|
if (!languageVersionSettings.isReleaseCoroutines()) {
|
||||||
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
|
visitVarInsn(Opcodes.ALOAD, continuationIndex)
|
||||||
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
|
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
|
||||||
|
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +524,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
remove(possibleTryCatchBlockStart.previous)
|
remove(possibleTryCatchBlockStart.previous)
|
||||||
|
|
||||||
insert(possibleTryCatchBlockStart, withInstructionAdapter {
|
insert(possibleTryCatchBlockStart, withInstructionAdapter {
|
||||||
generateResumeWithExceptionCheck(exceptionIndex)
|
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
|
||||||
|
|
||||||
// Load continuation argument just like suspending function returns it
|
// Load continuation argument just like suspending function returns it
|
||||||
load(dataIndex, AsmTypes.OBJECT_TYPE)
|
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
|
// Check if resumeWithException has been called
|
||||||
load(exceptionIndex, AsmTypes.OBJECT_TYPE)
|
load(if (isReleaseCoroutines) dataIndex else exceptionIndex, AsmTypes.OBJECT_TYPE)
|
||||||
dup()
|
dup()
|
||||||
val noExceptionLabel = Label()
|
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()
|
athrow()
|
||||||
|
|
||||||
mark(noExceptionLabel)
|
mark(noExceptionLabel)
|
||||||
@@ -823,4 +839,4 @@ private fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continu
|
|||||||
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
|
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
|
||||||
methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex))
|
methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-2
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
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.calls.tower.NewResolvedCallImpl
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
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.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
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 COROUTINE_LABEL_FIELD_NAME = "label"
|
||||||
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
|
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
|
||||||
const val DO_RESUME_METHOD_NAME = "doResume"
|
const val DO_RESUME_METHOD_NAME = "doResume"
|
||||||
|
const val INVOKE_SUSPEND_METHOD_NAME = "invokeSuspend"
|
||||||
const val DATA_FIELD_NAME = "data"
|
const val DATA_FIELD_NAME = "data"
|
||||||
const val EXCEPTION_FIELD_NAME = "exception"
|
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() =
|
fun LanguageVersionSettings.coroutinesJvmInternalPackageFqName() =
|
||||||
coroutinesPackageFqName().child(Name.identifier("jvm")).child(Name.identifier("internal"))
|
coroutinesPackageFqName().child(Name.identifier("jvm")).child(Name.identifier("internal"))
|
||||||
|
|
||||||
@@ -70,8 +82,19 @@ fun continuationAsmTypes() = listOf(
|
|||||||
fun LanguageVersionSettings.coroutineContextAsmType() =
|
fun LanguageVersionSettings.coroutineContextAsmType() =
|
||||||
coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
|
coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
|
||||||
|
|
||||||
fun LanguageVersionSettings.coroutineImplAsmType() =
|
fun LanguageVersionSettings.isCoroutineSuperClass(internalName: String): Boolean {
|
||||||
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
|
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() =
|
private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName() =
|
||||||
coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
|
coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
|
||||||
@@ -79,6 +102,12 @@ private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName()
|
|||||||
private fun LanguageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName() =
|
private fun LanguageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName() =
|
||||||
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName()
|
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 NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
|
||||||
private val GET_CONTEXT_METHOD_NAME = "getContext"
|
private val GET_CONTEXT_METHOD_NAME = "getContext"
|
||||||
|
|
||||||
@@ -284,6 +313,17 @@ fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleas
|
|||||||
)
|
)
|
||||||
} ?: module.builtIns.nullableAnyType
|
} ?: 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) =
|
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
|
||||||
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings) == true
|
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) =
|
fun Method.getImplForOpenMethod(ownerInternalName: String) =
|
||||||
Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes)
|
Method("$name\$suspendImpl", returnType, arrayOf(Type.getObjectType(ownerInternalName)) + argumentTypes)
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -10,17 +10,18 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
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.optimization.common.asSequence
|
||||||
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
|
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.coroutineImplAsmType
|
|
||||||
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
|
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
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.JvmProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||||
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
|
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.protobuf.MessageLite
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||||
@@ -55,7 +56,7 @@ class AnonymousObjectTransformer(
|
|||||||
createClassReader().accept(object : ClassVisitor(API, classBuilder.visitor) {
|
createClassReader().accept(object : ClassVisitor(API, classBuilder.visitor) {
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
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)
|
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
||||||
if (languageVersionSettings.coroutineImplAsmType().internalName == superName) {
|
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
|
||||||
inliningContext.isContinuation = true
|
inliningContext.isContinuation = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +153,7 @@ class AnonymousObjectTransformer(
|
|||||||
// 2) Suspend named function
|
// 2) Suspend named function
|
||||||
// Iff it captures crossinline suspend lambda
|
// Iff it captures crossinline suspend lambda
|
||||||
val generateStateMachineForLambda =
|
val generateStateMachineForLambda =
|
||||||
next.name == "doResume" && capturesCrossinlineSuspend && inliningContext.isContinuation &&
|
languageVersionSettings.isResumeImplMethodName(next.name) && capturesCrossinlineSuspend && inliningContext.isContinuation &&
|
||||||
!isLambdaAlreadyGeneratedAndNotGoingToBeInlined && hasLambdasToInline
|
!isLambdaAlreadyGeneratedAndNotGoingToBeInlined && hasLambdasToInline
|
||||||
val continuationClassName = findFakeContinuationConstructorClassName(next)
|
val continuationClassName = findFakeContinuationConstructorClassName(next)
|
||||||
val generateStateMachineForNamedFunction =
|
val generateStateMachineForNamedFunction =
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class AsmTypes {
|
|||||||
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
|
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
|
||||||
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
|
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
|
||||||
|
|
||||||
|
public static final Type SUCCESS_OR_FAILURE_FAILURE = Type.getObjectType("kotlin/SuccessOrFailure$Failure");
|
||||||
|
|
||||||
public static final Type[] PROPERTY_REFERENCE_IMPL = {
|
public static final Type[] PROPERTY_REFERENCE_IMPL = {
|
||||||
Type.getObjectType("kotlin/jvm/internal/PropertyReference0Impl"),
|
Type.getObjectType("kotlin/jvm/internal/PropertyReference0Impl"),
|
||||||
|
|||||||
+6
-3
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -130,15 +131,17 @@ fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, dia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KotlinType.isRestrictsSuspensionReceiver(languageVersionSettings: LanguageVersionSettings) = (listOf(this) + this.supertypes()).any {
|
||||||
|
it.constructor.declarationDescriptor?.annotations?.hasAnnotation(languageVersionSettings.restrictsSuspensionFqName()) == true
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkRestrictsSuspension(
|
private fun checkRestrictsSuspension(
|
||||||
enclosingSuspendCallableDescriptor: CallableDescriptor,
|
enclosingSuspendCallableDescriptor: CallableDescriptor,
|
||||||
resolvedCall: ResolvedCall<*>,
|
resolvedCall: ResolvedCall<*>,
|
||||||
reportOn: PsiElement,
|
reportOn: PsiElement,
|
||||||
context: CallCheckerContext
|
context: CallCheckerContext
|
||||||
) {
|
) {
|
||||||
fun ReceiverValue.isRestrictsSuspensionReceiver() = (listOf(type) + type.supertypes()).any {
|
fun ReceiverValue.isRestrictsSuspensionReceiver() = type.isRestrictsSuspensionReceiver(context.languageVersionSettings)
|
||||||
it.constructor.declarationDescriptor?.annotations?.hasAnnotation(context.languageVersionSettings.restrictsSuspensionFqName()) == true
|
|
||||||
}
|
|
||||||
|
|
||||||
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
|
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
|
||||||
if (other == null) return false
|
if (other == null) return false
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
|
import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
@@ -128,7 +130,12 @@ object InlineTestUtil {
|
|||||||
if (skipMethodsOfThisClass) {
|
if (skipMethodsOfThisClass) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (name == "doResume" && desc == "(Ljava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object;") {
|
|
||||||
|
if (name == DO_RESUME_METHOD_NAME && desc == "(Ljava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object;") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == INVOKE_SUSPEND_METHOD_NAME && desc == "(Ljava/lang/Object;)Ljava/lang/Object;") {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -5,14 +5,16 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.config
|
package org.jetbrains.kotlin.config
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
fun LanguageVersionSettings.coroutinesPackageFqName(): FqName {
|
fun LanguageVersionSettings.coroutinesPackageFqName(): FqName {
|
||||||
return coroutinesPackageFqName(supportsFeature(LanguageFeature.ReleaseCoroutines))
|
return coroutinesPackageFqName(isReleaseCoroutines())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun LanguageVersionSettings.isReleaseCoroutines() = supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||||
|
|
||||||
private fun coroutinesPackageFqName(isReleaseCoroutines: Boolean): FqName {
|
private fun coroutinesPackageFqName(isReleaseCoroutines: Boolean): FqName {
|
||||||
return if (isReleaseCoroutines)
|
return if (isReleaseCoroutines)
|
||||||
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE
|
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE
|
||||||
@@ -34,4 +36,4 @@ fun FqName.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSet
|
|||||||
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
|
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
|
||||||
else
|
else
|
||||||
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext")) ||
|
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext")) ||
|
||||||
this == DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
|
this == DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ public class DescriptorUtils {
|
|||||||
public static final FqName CONTINUATION_INTERFACE_FQ_NAME_RELEASE =
|
public static final FqName CONTINUATION_INTERFACE_FQ_NAME_RELEASE =
|
||||||
COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("Continuation"));
|
COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("Continuation"));
|
||||||
|
|
||||||
|
public static final FqName SUCCESS_OR_FAILURE_FQ_NAME = new FqName("kotlin.SuccessOrFailure");
|
||||||
|
|
||||||
private DescriptorUtils() {
|
private DescriptorUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.sun.jdi.*
|
|||||||
import com.sun.tools.jdi.LocalVariableImpl
|
import com.sun.tools.jdi.LocalVariableImpl
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmTypes
|
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmTypes
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
||||||
@@ -180,7 +181,8 @@ private class MockStackFrame(private val location: Location, private val vm: Vir
|
|||||||
override fun virtualMachine() = vm
|
override fun virtualMachine() = vm
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DO_RESUME_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object;"
|
private const val DO_RESUME_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Throwable;)Ljava/lang/Object;"
|
||||||
|
private const val INVOKE_SUSPEND_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;"
|
||||||
|
|
||||||
fun isInSuspendMethod(location: Location): Boolean {
|
fun isInSuspendMethod(location: Location): Boolean {
|
||||||
val method = location.method()
|
val method = location.method()
|
||||||
@@ -188,7 +190,8 @@ fun isInSuspendMethod(location: Location): Boolean {
|
|||||||
|
|
||||||
for (continuationAsmType in continuationAsmTypes()) {
|
for (continuationAsmType in continuationAsmTypes()) {
|
||||||
if (signature.contains(continuationAsmType.toString()) ||
|
if (signature.contains(continuationAsmType.toString()) ||
|
||||||
(method.name() == DO_RESUME_METHOD_NAME && signature == DO_RESUME_SIGNATURE)
|
(method.name() == DO_RESUME_METHOD_NAME && signature == DO_RESUME_SIGNATURE) ||
|
||||||
|
(method.name() == INVOKE_SUSPEND_METHOD_NAME && signature == INVOKE_SUSPEND_SIGNATURE)
|
||||||
) return true
|
) return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
+4
-4
@@ -21,7 +21,7 @@ import com.intellij.debugger.engine.BreakpointStepMethodFilter
|
|||||||
import com.intellij.debugger.engine.DebugProcessImpl
|
import com.intellij.debugger.engine.DebugProcessImpl
|
||||||
import com.intellij.util.Range
|
import com.intellij.util.Range
|
||||||
import com.sun.jdi.Location
|
import com.sun.jdi.Location
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.isResumeImplMethodNameFromAnyLanguageSettings
|
||||||
import org.jetbrains.kotlin.idea.debugger.isInsideInlineArgument
|
import org.jetbrains.kotlin.idea.debugger.isInsideInlineArgument
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isMultiLine
|
import org.jetbrains.kotlin.idea.refactoring.isMultiLine
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
@@ -74,11 +74,11 @@ class KotlinLambdaMethodFilter(
|
|||||||
override fun getCallingExpressionLines() = if (isInline) Range(0, 999) else myCallingExpressionLines
|
override fun getCallingExpressionLines() = if (isInline) Range(0, 999) else myCallingExpressionLines
|
||||||
|
|
||||||
private fun isLambdaName(name: String?): Boolean {
|
private fun isLambdaName(name: String?): Boolean {
|
||||||
if (isSuspend) {
|
if (isSuspend && name != null) {
|
||||||
return name == DO_RESUME_METHOD_NAME
|
return isResumeImplMethodNameFromAnyLanguageSettings(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return name == OperatorNameConventions.INVOKE.asString()
|
return name == OperatorNameConventions.INVOKE.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user