Remove obsolete experimental coroutines support

in compiler.
This commit is contained in:
Ilmir Usmanov
2021-07-29 08:49:46 +02:00
parent ebb340fe68
commit 486c6b3c15
74 changed files with 349 additions and 1019 deletions
@@ -5,21 +5,15 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
import org.jetbrains.kotlin.name.Name
val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean =
!languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) &&
isTopLevelInPackage("intercepted", languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString())
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean =
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean =
isTopLevelInPackage(
"suspendCoroutineUninterceptedOrReturn",
languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString()
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.asString()
)
@@ -475,7 +475,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
List<Type> superCtorArgTypes = new ArrayList<>();
if (superClassAsmType.equals(LAMBDA) || functionReferenceTarget != null ||
CoroutineCodegenUtilKt.isCoroutineSuperClass(state.getLanguageVersionSettings(), superClassAsmType.getInternalName())
CoroutineCodegenUtilKt.isCoroutineSuperClass(superClassAsmType.getInternalName())
) {
iv.iconst(CodegenUtilKt.getArity(funDescriptor));
superCtorArgTypes.add(Type.INT_TYPE);
@@ -89,7 +89,6 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContextImpl;
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
import org.jetbrains.kotlin.types.model.TypeParameterMarker;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.kotlin.util.OperatorNameConventions;
@@ -1288,11 +1287,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull
private static CallableDescriptor unwrapOriginalReceiverOwnerForSuspendLambda(@NotNull MethodContext context) {
FunctionDescriptor originalForDoResume =
context.getFunctionDescriptor().getUserData(CoroutineCodegenUtilKt.INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME);
FunctionDescriptor originalForInvokeSuspend =
context.getFunctionDescriptor().getUserData(CoroutineCodegenUtilKt.INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND);
if (originalForDoResume != null) {
return originalForDoResume;
if (originalForInvokeSuspend != null) {
return originalForInvokeSuspend;
}
if (context.getFunctionDescriptor().isSuspend()) {
@@ -2617,26 +2616,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
? coroutineInstanceValueForSuspensionPoint
: getContinuationParameterFromEnclosingSuspendFunction(resolvedCall);
if (coroutineInstanceValue != null && needsExperimentalCoroutinesWrapper(resolvedCall.getCandidateDescriptor())) {
StackValue releaseContinuation = coroutineInstanceValue;
coroutineInstanceValue = new StackValue(CoroutineCodegenUtilKt.EXPERIMENTAL_CONTINUATION_ASM_TYPE) {
@Override
public void putSelector(
@NotNull Type type, @Nullable KotlinType kotlinType, @NotNull InstructionAdapter v
) {
releaseContinuation.put(CoroutineCodegenUtilKt.RELEASE_CONTINUATION_ASM_TYPE, v);
invokeCoroutineMigrationMethod(
v,
"toExperimentalContinuation",
Type.getMethodDescriptor(
CoroutineCodegenUtilKt.EXPERIMENTAL_CONTINUATION_ASM_TYPE,
CoroutineCodegenUtilKt.RELEASE_CONTINUATION_ASM_TYPE
)
);
}
};
}
tempVariables.put(continuationExpression, coroutineInstanceValue);
}
@@ -2774,7 +2753,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
SuspensionPointKind suspensionPointKind =
CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, this, state.getLanguageVersionSettings());
CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, this);
boolean maybeSuspensionPoint = suspensionPointKind != SuspensionPointKind.NEVER && !insideCallableReference();
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
@@ -2833,7 +2812,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
KotlinType unboxedInlineClass = CoroutineCodegenUtilKt.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), typeMapper);
if (unboxedInlineClass != null) {
CoroutineCodegenUtilKt.generateCoroutineSuspendedCheck(v, state.getLanguageVersionSettings());
CoroutineCodegenUtilKt.generateCoroutineSuspendedCheck(v);
}
}
@@ -2948,7 +2927,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor original =
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
bindingContext, state
bindingContext
);
FunctionDescriptor functionDescriptor =
@@ -5243,7 +5222,7 @@ The "returned" value of try expression with no finally is either the last expres
}
CodegenUtilKt.generateAsCast(
v, rightKotlinType, boxedRightType, safeAs, state.getLanguageVersionSettings(), state.getUnifiedNullChecks()
v, rightKotlinType, boxedRightType, safeAs, state.getUnifiedNullChecks()
);
return Unit.INSTANCE;
@@ -5297,7 +5276,7 @@ The "returned" value of try expression with no finally is either the last expres
return null;
}
CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type, state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
CodegenUtilKt.generateIsCheck(v, rhsKotlinType, type);
return null;
});
}
@@ -481,8 +481,7 @@ public class FunctionCodegen {
}
if (!functionDescriptor.isExternal()) {
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode(),
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode());
}
else if (staticInCompanionObject) {
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
@@ -583,8 +582,7 @@ public class FunctionCodegen {
@NotNull JvmMethodSignature signature,
@NotNull FunctionGenerationStrategy strategy,
@NotNull MemberCodegen<?> parentCodegen,
@NotNull JvmDefaultMode jvmDefaultMode,
boolean isReleaseCoroutines
@NotNull JvmDefaultMode jvmDefaultMode
) {
mv.visitCode();
@@ -594,8 +592,7 @@ public class FunctionCodegen {
KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, typeMapper::mapAsmMethod)) {
generateTypeCheckBarrierIfNeeded(
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper,
isReleaseCoroutines);
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), null, typeMapper);
}
Label methodEntry = null;
@@ -1430,8 +1427,7 @@ public class FunctionCodegen {
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper,
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes(), typeMapper);
}
iv.load(0, OBJECT_TYPE);
@@ -1477,8 +1473,7 @@ public class FunctionCodegen {
@NotNull FunctionDescriptor descriptor,
@NotNull Type returnType,
@Nullable Type[] delegateParameterTypes,
@NotNull KotlinTypeMapper typeMapper,
boolean isReleaseCoroutines
@NotNull KotlinTypeMapper typeMapper
) {
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
@@ -1512,7 +1507,7 @@ public class FunctionCodegen {
} else {
targetBoxedType = boxType(delegateParameterTypes[i]);
}
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType, isReleaseCoroutines);
CodegenUtilKt.generateIsCheck(iv, kotlinType, targetBoxedType);
iv.ifeq(defaultBranch);
}
}
@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.coroutines.isSuspendLambdaOrLocalFunction
import org.jetbrains.kotlin.config.LanguageFeature
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
@@ -33,8 +32,7 @@ class JvmRuntimeTypes(
private val generateOptimizedCallableReferenceSuperClasses: Boolean
) {
private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal"))
private val kotlinCoroutinesJvmInternalPackage =
MutablePackageFragmentDescriptor(module, languageVersionSettings.coroutinesJvmInternalPackageFqName())
private val kotlinCoroutinesJvmInternalPackage = MutablePackageFragmentDescriptor(module, COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME)
private fun internal(className: String, packageFragment: PackageFragmentDescriptor = kotlinJvmInternalPackage): Lazy<ClassDescriptor> =
lazy { createClass(packageFragment, className) }
@@ -53,24 +51,16 @@ class JvmRuntimeTypes(
private val localVariableReference: ClassDescriptor by internal("LocalVariableReference")
private val mutableLocalVariableReference: ClassDescriptor by internal("MutableLocalVariableReference")
private val coroutineImpl: ClassDescriptor by internal("CoroutineImpl", kotlinCoroutinesJvmInternalPackage)
private val continuationImpl: ClassDescriptor by coroutinesInternal("ContinuationImpl")
private val restrictedContinuationImpl: ClassDescriptor by coroutinesInternal("RestrictedContinuationImpl")
private val suspendLambda: ClassDescriptor by coroutinesInternal("SuspendLambda")
private val restrictedSuspendLambda: ClassDescriptor by coroutinesInternal("RestrictedSuspendLambda")
private val suspendFunctionInterface: ClassDescriptor? by lazy {
if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, "SuspendFunction", ClassKind.INTERFACE)
else null
createClass(kotlinCoroutinesJvmInternalPackage, "SuspendFunction", ClassKind.INTERFACE)
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor {
return if (languageVersionSettings.isReleaseCoroutines())
createClass(kotlinCoroutinesJvmInternalPackage, className)
else
coroutineImpl
}
private fun createCoroutineSuperClass(className: String): ClassDescriptor = createClass(kotlinCoroutinesJvmInternalPackage, className)
private val propertyReferences: List<ClassDescriptor> by propertyClasses("PropertyReference", "")
private val mutablePropertyReferences: List<ClassDescriptor> by propertyClasses("MutablePropertyReference", "")
@@ -94,7 +84,7 @@ class JvmRuntimeTypes(
fun getSupertypesForClosure(descriptor: FunctionDescriptor): Collection<KotlinType> {
val actualFunctionDescriptor =
if (descriptor.isSuspend)
getOrCreateJvmSuspendFunctionView(descriptor, languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
getOrCreateJvmSuspendFunctionView(descriptor)
else
descriptor
@@ -118,7 +108,7 @@ class JvmRuntimeTypes(
if (descriptor.isSuspend) {
return mutableListOf<KotlinType>().apply {
if (actualFunctionDescriptor.extensionReceiverParameter?.type
?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
?.isRestrictsSuspensionReceiver() == true
) {
if (descriptor.isSuspendLambdaOrLocalFunction()) {
add(restrictedSuspendLambda.defaultType)
@@ -477,7 +477,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
functionDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
this.bindingContext
);
@@ -714,54 +713,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
super.visitCallExpression(expression);
checkSamCall(expression);
checkCrossinlineCall(expression);
recordSuspendFunctionTypeWrapperForArguments(expression);
}
private void recordSuspendFunctionTypeWrapperForArguments(@NotNull KtCallExpression expression) {
ResolvedCall<?> call = CallUtilKt.getResolvedCall(expression, bindingContext);
if (call == null) return;
CallableDescriptor descriptor = call.getResultingDescriptor();
if (!CodegenUtilKt.needsExperimentalCoroutinesWrapper(descriptor)) return;
List<ResolvedValueArgument> argumentsByIndex = call.getValueArgumentsByIndex();
if (argumentsByIndex == null) return;
for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = argumentsByIndex.get(parameter.getIndex());
if (!(resolvedValueArgument instanceof ExpressionValueArgument)) continue;
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
if (valueArgument == null) continue;
KtExpression argumentExpression = valueArgument.getArgumentExpression();
if (argumentExpression == null) continue;
recordSuspendFunctionTypeWrapperForArgument(parameter, argumentExpression);
}
ReceiverValue receiver = call.getExtensionReceiver();
if (descriptor.getExtensionReceiverParameter() != null && receiver instanceof ExpressionReceiver) {
recordSuspendFunctionTypeWrapperForArgument(
descriptor.getExtensionReceiverParameter(),
((ExpressionReceiver) receiver).getExpression()
);
}
}
private void recordSuspendFunctionTypeWrapperForArgument(ParameterDescriptor parameter, KtExpression argumentExpression) {
if (FunctionTypesKt.isSuspendFunctionTypeOrSubtype(parameter.getType())) {
// SuspendFunctionN type is mapped to is mapped to FunctionTypeN+1, but we also need to remove an argument for return type
// So, it could be parameter.getType().getArguments().size() + 1 - 1
int functionTypeArity = parameter.getType().getArguments().size();
Type functionType = Type.getObjectType(NUMBERED_FUNCTION_PREFIX + functionTypeArity);
bindingTrace.record(
FUNCTION_TYPE_FOR_SUSPEND_WRAPPER,
argumentExpression,
functionType
);
}
}
private void checkCrossinlineCall(@NotNull KtCallExpression expression) {
@@ -13,15 +13,13 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
import org.jetbrains.kotlin.codegen.context.MultifileClassFacadeContext
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.codegen.inline.NUMBERED_FUNCTION_PREFIX
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
@@ -45,8 +43,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
@@ -70,8 +66,7 @@ internal val JAVA_LANG_DEPRECATED = Type.getType(Deprecated::class.java).descrip
fun generateIsCheck(
v: InstructionAdapter,
kotlinType: KotlinType,
asmType: Type,
isReleaseCoroutines: Boolean
asmType: Type
) {
if (TypeUtils.isNullableType(kotlinType)) {
val nope = Label()
@@ -82,7 +77,7 @@ fun generateIsCheck(
ifnull(nope)
TypeIntrinsics.instanceOf(this, kotlinType, asmType, isReleaseCoroutines)
TypeIntrinsics.instanceOf(this, kotlinType, asmType)
goTo(end)
@@ -93,7 +88,7 @@ fun generateIsCheck(
mark(end)
}
} else {
TypeIntrinsics.instanceOf(v, kotlinType, asmType, isReleaseCoroutines)
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
}
}
@@ -102,7 +97,6 @@ fun generateAsCast(
kotlinType: KotlinType,
asmType: Type,
isSafe: Boolean,
languageVersionSettings: LanguageVersionSettings,
unifiedNullChecks: Boolean,
) {
if (!isSafe) {
@@ -112,7 +106,7 @@ fun generateAsCast(
} else {
with(v) {
dup()
TypeIntrinsics.instanceOf(v, kotlinType, asmType, languageVersionSettings.isReleaseCoroutines())
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
val ok = Label()
ifne(ok)
pop()
@@ -444,14 +438,10 @@ fun KotlinType.isInlineClassTypeWithPrimitiveEquality(): Boolean {
return false
}
fun CallableDescriptor.needsExperimentalCoroutinesWrapper() =
(this as? DeserializedMemberDescriptor)?.coroutinesExperimentalCompatibilityMode == CoroutinesCompatibilityMode.NEEDS_WRAPPER
fun recordCallLabelForLambdaArgument(declaration: KtFunctionLiteral, bindingTrace: BindingTrace) {
val labelName = getCallLabelForLambdaArgument(declaration, bindingTrace.bindingContext) ?: return
val functionDescriptor = bindingTrace[BindingContext.FUNCTION, declaration] ?: return
bindingTrace.record(CodegenBinding.CALL_LABEL_FOR_LAMBDA_ARGUMENT, functionDescriptor, labelName)
}
fun getCallLabelForLambdaArgument(declaration: KtFunctionLiteral, bindingContext: BindingContext): String? {
@@ -647,7 +637,7 @@ private fun generateLambdaForRunSuspend(
}
visitVarInsn(ALOAD, 1)
val continuationInternalName = state.languageVersionSettings.continuationAsmType().internalName
val continuationInternalName = CONTINUATION_ASM_TYPE.internalName
visitTypeInsn(
CHECKCAST,
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.codegen.context
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.config.coroutinesPackageFqName
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
@@ -17,25 +17,26 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall
import org.jetbrains.kotlin.resolve.source.getPsi
class InlineLambdaContext(
functionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>,
closure: MutableClosure?,
val isCrossInline: Boolean,
private val isPropertyReference: Boolean
functionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>,
closure: MutableClosure?,
val isCrossInline: Boolean,
private val isPropertyReference: Boolean
) : MethodContext(functionDescriptor, contextKind, parentContext, closure, false) {
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
if (isCrossInline && !isSuspendIntrinsicParameter()) return this
val parent = if (isPropertyReference) parentContext as? AnonymousClassContext else { parentContext as? ClosureContext } ?:
throw AssertionError(
"Parent of inlining lambda body should be " +
"${if (isPropertyReference) "ClosureContext" else "AnonymousClassContext"}, but: $parentContext"
)
val parent = if (isPropertyReference) parentContext as? AnonymousClassContext else {
parentContext as? ClosureContext
} ?: throw AssertionError(
"Parent of inlining lambda body should be " +
"${if (isPropertyReference) "ClosureContext" else "AnonymousClassContext"}, but: $parentContext"
)
val grandParent = parent.parentContext ?:
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
val grandParent =
parent.parentContext ?: throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
return grandParent.firstCrossInlineOrNonInlineContext
}
@@ -44,7 +45,7 @@ class InlineLambdaContext(
if (contextDescriptor !is AnonymousFunctionDescriptor) return false
val resolvedCall = (contextDescriptor.source.getPsi() as? KtElement).getParentResolvedCall(state.bindingContext) ?: return false
val descriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return false
return descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(state.languageVersionSettings)
|| descriptor.isTopLevelInPackage("suspendCoroutine", state.languageVersionSettings.coroutinesPackageFqName().asString())
return descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn()
|| descriptor.isTopLevelInPackage("suspendCoroutine", StandardNames.COROUTINES_PACKAGE_FQ_NAME.asString())
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.coroutines
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.optimization.boxing.isPrimitiveBoxing
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -15,10 +16,9 @@ import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("Boxing")).topLevelClassInternalName()
@OptIn(ExperimentalStdlibApi::class)
object ChangeBoxingMethodTransformer : MethodTransformer() {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
@@ -17,8 +18,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHO
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConfigurationKeys
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.AnonymousFunctionDescriptor
@@ -41,7 +40,6 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -56,7 +54,7 @@ abstract class AbstractCoroutineCodegen(
element: KtElement,
closureContext: ClosureContext,
classBuilder: ClassBuilder,
private val userDataForDoResume: Map<out CallableDescriptor.UserDataKey<*>, *>? = null
private val userDataForInvokeSuspend: Map<out CallableDescriptor.UserDataKey<*>, *>? = null
) : ClosureCodegen(
outerExpressionCodegen.state,
element, null, closureContext, null,
@@ -67,17 +65,10 @@ abstract class AbstractCoroutineCodegen(
protected val languageVersionSettings = outerExpressionCodegen.state.languageVersionSettings
protected val methodToImplement =
if (languageVersionSettings.isReleaseCoroutines())
createImplMethod(
INVOKE_SUSPEND_METHOD_NAME,
SUSPEND_CALL_RESULT_NAME to classDescriptor.module.getResult(classDescriptor.builtIns.anyType)
)
else
createImplMethod(
DO_RESUME_METHOD_NAME,
"data" to classDescriptor.builtIns.nullableAnyType,
"throwable" to classDescriptor.builtIns.throwable.defaultType.makeNullable()
)
createImplMethod(
INVOKE_SUSPEND_METHOD_NAME,
SUSPEND_CALL_RESULT_NAME to classDescriptor.module.getResult(classDescriptor.builtIns.anyType)
)
private fun createImplMethod(name: String, vararg parameters: Pair<String, KotlinType>) =
SimpleFunctionDescriptorImpl.create(
@@ -94,7 +85,7 @@ abstract class AbstractCoroutineCodegen(
builtIns.nullableAnyType,
Modality.FINAL,
DescriptorVisibilities.PUBLIC,
userDataForDoResume
userDataForInvokeSuspend
)
}
@@ -109,7 +100,7 @@ abstract class AbstractCoroutineCodegen(
override fun generateConstructor(): Method {
val args = calculateConstructorParameters(typeMapper, languageVersionSettings, closure, asmType)
val argTypes = args.map { it.fieldType }.plus(languageVersionSettings.continuationAsmType()).toTypedArray()
val argTypes = args.map { it.fieldType }.plus(CONTINUATION_ASM_TYPE).toTypedArray()
val constructor = Method("<init>", Type.VOID_TYPE, argTypes)
val mv = v.newMethod(
@@ -124,18 +115,17 @@ abstract class AbstractCoroutineCodegen(
iv.generateClosureFieldsInitializationFromParameters(closure, args)
iv.load(0, AsmTypes.OBJECT_TYPE)
val hasArityParameter = !languageVersionSettings.isReleaseCoroutines() || passArityToSuperClass
if (hasArityParameter) {
iv.iconst(if (passArityToSuperClass) funDescriptor.arity else 0)
if (passArityToSuperClass) {
iv.iconst(funDescriptor.arity)
}
iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE)
val parameters =
if (hasArityParameter)
listOf(Type.INT_TYPE, languageVersionSettings.continuationAsmType())
if (passArityToSuperClass)
listOf(Type.INT_TYPE, CONTINUATION_ASM_TYPE)
else
listOf(languageVersionSettings.continuationAsmType())
listOf(CONTINUATION_ASM_TYPE)
val superClassConstructorDescriptor = Type.getMethodDescriptor(
Type.VOID_TYPE,
@@ -148,9 +138,7 @@ 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)
}
v.newField(JvmDeclarationOrigin.NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "label", "I", null, null)
return constructor
}
@@ -167,7 +155,7 @@ class CoroutineCodegenForLambda private constructor(
private val forInline: Boolean
) : AbstractCoroutineCodegen(
outerExpressionCodegen, element, closureContext, classBuilder,
userDataForDoResume = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME to originalSuspendFunctionDescriptor)
userDataForInvokeSuspend = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND to originalSuspendFunctionDescriptor)
) {
private val builtIns = funDescriptor.builtIns
@@ -215,8 +203,7 @@ class CoroutineCodegenForLambda private constructor(
funDescriptor.typeParameters,
funDescriptor.valueParameters,
funDescriptor.module.getContinuationOfTypeOrAny(
builtIns.unitType,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
builtIns.unitType
),
funDescriptor.modality,
DescriptorVisibilities.PUBLIC
@@ -231,14 +218,11 @@ class CoroutineCodegenForLambda private constructor(
"too many arguments of create to have an erased signature: $argumentsNum: $typedCreate"
}
return typedCreate.module.resolveClassByFqName(
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(
if (languageVersionSettings.isReleaseCoroutines())
Name.identifier("BaseContinuationImpl")
else
Name.identifier("CoroutineImpl")
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(
Name.identifier("BaseContinuationImpl")
),
NoLookupLocation.FROM_BACKEND
).sure { "BaseContinuationImpl or CoroutineImpl is not found" }.defaultType.memberScope
).sure { "BaseContinuationImpl is not found" }.defaultType.memberScope
.getContributedFunctions(typedCreate.name, NoLookupLocation.FROM_BACKEND)
.find { it.valueParameters.size == argumentsNum }
.sure { "erased parent of $typedCreate is not found" }
@@ -365,7 +349,7 @@ class CoroutineCodegenForLambda private constructor(
v.thisName,
typeMapper.mapFunctionName(createCoroutineDescriptor, null),
Type.getMethodDescriptor(
languageVersionSettings.continuationAsmType(),
CONTINUATION_ASM_TYPE,
*createArgumentTypes.toTypedArray()
),
false
@@ -373,11 +357,7 @@ class CoroutineCodegenForLambda private constructor(
checkcast(Type.getObjectType(v.thisName))
// .doResume(Unit)
if (languageVersionSettings.isReleaseCoroutines()) {
invokeInvokeSuspendWithUnit(v.thisName)
} else {
invokeDoResumeWithUnit(v.thisName)
}
invokeInvokeSuspendWithUnit(v.thisName)
areturn(AsmTypes.OBJECT_TYPE)
}
@@ -540,15 +520,14 @@ class CoroutineCodegenForLambda private constructor(
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null,
containingClassInternalName = v.thisName,
obtainClassBuilderForCoroutineState = { v },
isForNamedFunction = false,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = false,
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element, state, it) },
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
sourceFile = element.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = v.thisName,
isForNamedFunction = false,
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS),
initialVarsCountByType = varsCountByType
)
@@ -625,7 +604,7 @@ class CoroutineCodegenForNamedFunction private constructor(
private val labelFieldStackValue by lazy {
StackValue.field(
FieldInfo.createForHiddenField(
computeLabelOwner(languageVersionSettings, v.thisName),
Type.getObjectType(v.thisName),
Type.INT_TYPE,
COROUTINE_LABEL_FIELD_NAME
),
@@ -647,44 +626,25 @@ class CoroutineCodegenForNamedFunction private constructor(
}
override fun generateClosureBody() {
generateResumeImpl()
if (!languageVersionSettings.isReleaseCoroutines()) {
generateGetLabelMethod()
generateSetLabelMethod()
}
generateInvokeSuspend()
v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_SYNTHETIC or AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
languageVersionSettings.dataFieldName(), AsmTypes.OBJECT_TYPE.descriptor, null, null
CONTINUATION_RESULT_FIELD_NAME, AsmTypes.OBJECT_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 generateResumeImpl() {
private fun generateInvokeSuspend() {
functionCodegen.generateMethod(
OtherOrigin(element),
methodToImplement,
object : FunctionGenerationStrategy.CodegenBased(state) {
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
StackValue.field(
AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), languageVersionSettings.dataFieldName(), false,
AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), CONTINUATION_RESULT_FIELD_NAME, false,
StackValue.LOCAL_0
).store(StackValue.local(1, AsmTypes.OBJECT_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) {
labelFieldStackValue.put(Type.INT_TYPE, it)
@@ -736,7 +696,7 @@ class CoroutineCodegenForNamedFunction private constructor(
with(codegen.v) {
// We need to box the returned inline class in resume path.
// But first, check for COROUTINE_SUSPENDED, since the function can return it
generateCoroutineSuspendedCheck(languageVersionSettings)
generateCoroutineSuspendedCheck()
// Now we box the inline class
StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this)
StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this, typeMapper)
@@ -9,15 +9,10 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
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
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
@@ -49,7 +44,6 @@ class CoroutineTransformerMethodVisitor(
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
private val isForNamedFunction: Boolean,
private val shouldPreserveClassInitialization: Boolean,
private val languageVersionSettings: LanguageVersionSettings,
// Since tail-call optimization of functions with Unit return type relies on ability of call-site to recognize them,
// in order to ignore return value and push Unit, when we cannot ensure this ability, for example, when the function overrides function,
// returning Any, we need to disable tail-call optimization for these functions.
@@ -73,7 +67,6 @@ class CoroutineTransformerMethodVisitor(
private var continuationIndex = if (isForNamedFunction) -1 else 0
private var dataIndex = if (isForNamedFunction) -1 else 1
private var exceptionIndex = if (isForNamedFunction || languageVersionSettings.isReleaseCoroutines()) -1 else 2
override fun performTransformations(methodNode: MethodNode) {
removeFakeContinuationConstructorCall(methodNode)
@@ -89,9 +82,7 @@ class CoroutineTransformerMethodVisitor(
val suspensionPoints = collectSuspensionPoints(methodNode)
RedundantLocalsEliminationMethodTransformer(suspensionPoints)
.transform(containingClassInternalName, methodNode)
if (languageVersionSettings.isReleaseCoroutines()) {
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
}
ChangeBoxingMethodTransformer.transform(containingClassInternalName, methodNode)
updateMaxStack(methodNode)
checkForSuspensionPointInsideMonitor(methodNode, suspensionPoints)
@@ -105,7 +96,6 @@ class CoroutineTransformerMethodVisitor(
}
val examiner = MethodNodeExaminer(
languageVersionSettings,
containingClassInternalName,
methodNode,
suspensionPoints,
@@ -119,9 +109,6 @@ class CoroutineTransformerMethodVisitor(
}
dataIndex = methodNode.maxLocals++
if (!languageVersionSettings.isReleaseCoroutines()) {
exceptionIndex = methodNode.maxLocals++
}
continuationIndex = methodNode.maxLocals++
prepareMethodNodePreludeForNamedFunction(methodNode)
@@ -158,7 +145,7 @@ class CoroutineTransformerMethodVisitor(
insertBefore(
actualCoroutineStart,
insnListOf(
*withInstructionAdapter { loadCoroutineSuspendedMarker(languageVersionSettings) }.toArray(),
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(),
tableSwitchLabel,
// Allow debugger to stop on enter into suspend function
LineNumberNode(lineNumber, tableSwitchLabel),
@@ -176,7 +163,7 @@ class CoroutineTransformerMethodVisitor(
)
insert(firstStateLabel, withInstructionAdapter {
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
generateResumeWithExceptionCheck(dataIndex)
})
insert(last, defaultLabel)
@@ -194,9 +181,7 @@ class CoroutineTransformerMethodVisitor(
updateLvtAccordingToLiveness(methodNode, isForNamedFunction, stateLabels)
if (languageVersionSettings.isReleaseCoroutines()) {
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping)
}
// When suspension point is inlined, it is in range of fake inliner variables.
@@ -263,7 +248,7 @@ class CoroutineTransformerMethodVisitor(
methodNode.localVariables.add(
LocalVariableNode(
SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME,
languageVersionSettings.continuationAsmType().descriptor,
CONTINUATION_ASM_TYPE.descriptor,
null,
startLabel,
endLabel,
@@ -402,7 +387,7 @@ class CoroutineTransformerMethodVisitor(
methodNode.instructions.add(withInstructionAdapter { mark(endLabel) })
methodNode.visitLocalVariable(
CONTINUATION_VARIABLE_NAME,
languageVersionSettings.continuationAsmType().descriptor,
CONTINUATION_ASM_TYPE.descriptor,
null,
startLabel,
endLabel,
@@ -430,33 +415,17 @@ class CoroutineTransformerMethodVisitor(
}
private fun InstructionAdapter.getLabel() {
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
invokevirtual(
classBuilderForCoroutineState.thisName,
"getLabel",
Type.getMethodDescriptor(Type.INT_TYPE),
false
)
else
getfield(
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
getfield(
Type.getObjectType(classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
}
private fun InstructionAdapter.setLabel() {
if (isForNamedFunction && !languageVersionSettings.isReleaseCoroutines())
invokevirtual(
classBuilderForCoroutineState.thisName,
"setLabel",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE),
false
)
else
putfield(
computeLabelOwner(languageVersionSettings, classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
putfield(
Type.getObjectType(classBuilderForCoroutineState.thisName).internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
)
}
private fun updateMaxStack(methodNode: MethodNode) {
@@ -534,8 +503,7 @@ class CoroutineTransformerMethodVisitor(
needDispatchReceiver,
internalNameForDispatchReceiver,
containingClassInternalName,
classBuilderForCoroutineState,
languageVersionSettings
classBuilderForCoroutineState
)
visitVarInsn(Opcodes.ASTORE, continuationIndex)
@@ -543,19 +511,13 @@ class CoroutineTransformerMethodVisitor(
visitLabel(afterCoroutineStateCreated)
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, languageVersionSettings.dataFieldName(), AsmTypes.OBJECT_TYPE.descriptor)
getfield(classBuilderForCoroutineState.thisName, CONTINUATION_RESULT_FIELD_NAME, AsmTypes.OBJECT_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, dataIndex)
val resultStartLabel = Label()
visitLabel(resultStartLabel)
addContinuationAndResultToLvt(methodNode, afterCoroutineStateCreated, resultStartLabel)
if (!languageVersionSettings.isReleaseCoroutines()) {
visitVarInsn(Opcodes.ALOAD, continuationIndex)
getfield(classBuilderForCoroutineState.thisName, EXCEPTION_FIELD_NAME, AsmTypes.JAVA_THROWABLE_TYPE.descriptor)
visitVarInsn(Opcodes.ASTORE, exceptionIndex)
}
})
}
@@ -692,7 +654,7 @@ class CoroutineTransformerMethodVisitor(
// k + 1 - data
// k + 2 - exception
for (slot in 0 until localsCount) {
if (slot == continuationIndex || slot == dataIndex || slot == exceptionIndex) continue
if (slot == continuationIndex || slot == dataIndex) continue
val value = frame.getLocal(slot)
if (value.type == null || !livenessFrame.isAlive(slot)) continue
@@ -992,7 +954,7 @@ class CoroutineTransformerMethodVisitor(
insert(possibleTryCatchBlockStart, withInstructionAdapter {
nop()
generateResumeWithExceptionCheck(languageVersionSettings.isReleaseCoroutines(), dataIndex, exceptionIndex)
generateResumeWithExceptionCheck(dataIndex)
// Load continuation argument just like suspending function returns it
load(dataIndex, AsmTypes.OBJECT_TYPE)
@@ -1118,8 +1080,7 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
needDispatchReceiver: Boolean,
internalNameForDispatchReceiver: String?,
containingClassInternalName: String,
classBuilderForCoroutineState: ClassBuilder,
languageVersionSettings: LanguageVersionSettings
classBuilderForCoroutineState: ClassBuilder
) {
anew(objectTypeForState)
dup()
@@ -1128,8 +1089,7 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
getParameterTypesIndicesForCoroutineConstructor(
methodNode.desc,
methodNode.access,
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName,
languageVersionSettings
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
)
for ((type, index) in parameterTypesAndIndices) {
load(index, type)
@@ -1149,22 +1109,11 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
)
}
private fun InstructionAdapter.generateResumeWithExceptionCheck(isReleaseCoroutines: Boolean, dataIndex: Int, exceptionIndex: Int) {
private fun InstructionAdapter.generateResumeWithExceptionCheck(dataIndex: Int) {
// Check if resumeWithException has been called
if (isReleaseCoroutines) {
load(dataIndex, AsmTypes.OBJECT_TYPE)
invokestatic("kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V", false)
} else {
load(exceptionIndex, AsmTypes.OBJECT_TYPE)
dup()
val noExceptionLabel = Label()
ifnull(noExceptionLabel)
athrow()
mark(noExceptionLabel)
pop()
}
load(dataIndex, AsmTypes.OBJECT_TYPE)
invokestatic("kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V", false)
}
private fun Type.fieldNameForVar(index: Int) = descriptor.first() + "$" + index
@@ -1235,16 +1184,15 @@ private fun getParameterTypesIndicesForCoroutineConstructor(
desc: String,
containingFunctionAccess: Int,
needDispatchReceiver: Boolean,
thisName: String,
languageVersionSettings: LanguageVersionSettings
thisName: String
): Collection<Pair<Type, Int>> {
return mutableListOf<Pair<Type, Int>>().apply {
if (needDispatchReceiver) {
add(Type.getObjectType(thisName) to 0)
}
val continuationIndex =
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum()
add(languageVersionSettings.continuationAsmType() to continuationIndex)
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).sumOf(Type::getSize)
add(CONTINUATION_ASM_TYPE to continuationIndex)
}
}
@@ -88,18 +88,17 @@ class SuspendFunctionGenerationStrategy(
return CoroutineTransformerMethodVisitor(
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
isForNamedFunction = true,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
!originalSuspendDescriptor.allOverriddenFunctionsReturnUnit(),
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(declaration, state, it) },
lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0,
sourceFile = declaration.containingKtFile.name,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
internalNameForDispatchReceiver = (originalSuspendDescriptor.containingDeclaration as? ClassDescriptor)?.let {
if (it.isInlineClass()) state.typeMapper.mapType(it).internalName else null
} ?: containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings,
disableTailCallOptimizationForFunctionReturningUnit = originalSuspendDescriptor.returnType?.isUnit() == true &&
originalSuspendDescriptor.overriddenDescriptors.isNotEmpty() &&
!originalSuspendDescriptor.allOverriddenFunctionsReturnUnit(),
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
}
@@ -155,8 +154,7 @@ class SuspendFunctionGenerationStrategy(
needDispatchReceiver,
internalNameForDispatchReceiver,
containingClassInternalName,
classBuilderForCoroutineState,
languageVersionSettings
classBuilderForCoroutineState
)
addFakeContinuationConstructorCallMarker(this, false)
pop() // Otherwise stack-transformation breaks
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
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.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Label
@@ -27,7 +26,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
internal class MethodNodeExaminer(
val languageVersionSettings: LanguageVersionSettings,
containingClassInternalName: String,
val methodNode: MethodNode,
suspensionPoints: List<SuspensionPoint>,
@@ -116,7 +114,7 @@ internal class MethodNodeExaminer(
val label = Label()
methodNode.instructions.insertBefore(pop, withInstructionAdapter {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
loadCoroutineSuspendedMarker()
ifacmpne(label)
areturn(AsmTypes.OBJECT_TYPE)
mark(label)
@@ -9,6 +9,8 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalClassDescriptor
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -54,67 +56,27 @@ 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 EXCEPTION_FIELD_NAME = "exception"
const val CONTINUATION_RESULT_FIELD_NAME = "result"
val RELEASE_COROUTINES_VERSION_SETTINGS = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)
private const val GET_CONTEXT_METHOD_NAME = "getContext"
fun LanguageVersionSettings.isResumeImplMethodName(name: String) =
if (isReleaseCoroutines())
name == INVOKE_SUSPEND_METHOD_NAME
else
name == DO_RESUME_METHOD_NAME
val DEBUG_METADATA_ANNOTATION_ASM_TYPE: Type =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("DebugMetadata")).topLevelClassAsmType()
fun LanguageVersionSettings.dataFieldName(): String = if (isReleaseCoroutines()) "result" else "data"
fun coroutineContextAsmType(): Type =
StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
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"))
val DEBUG_METADATA_ANNOTATION_ASM_TYPE = RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName()
.child(Name.identifier("DebugMetadata")).topLevelClassAsmType()
fun LanguageVersionSettings.continuationAsmType() =
continuationInterfaceFqName().topLevelClassAsmType()
fun continuationAsmTypes() = listOf(
LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3).continuationAsmType(),
LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_2, ApiVersion.KOTLIN_1_2).continuationAsmType()
)
fun LanguageVersionSettings.coroutineContextAsmType() =
coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).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
}
fun String.isCoroutineSuperClass(): Boolean =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("ContinuationImpl") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("RestrictedContinuationImpl") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("SuspendLambda") == this ||
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.identifiedChild("RestrictedSuspendLambda") == this
private fun FqName.identifiedChild(name: String) = child(Name.identifier(name)).topLevelClassInternalName()
private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName() =
coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
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 const val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
private const val GET_CONTEXT_METHOD_NAME = "getContext"
private val coroutinesIntrinsicsFileFacadeInternalName: Type =
COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeContinuationExpression: KtExpression)
@@ -122,7 +84,7 @@ data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val
val INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
@JvmField
val INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
val INITIAL_SUSPEND_DESCRIPTOR_FOR_INVOKE_SUSPEND = object : CallableDescriptor.UserDataKey<FunctionDescriptor> {}
val CONTINUATION_PARAMETER_NAME = Name.identifier("continuation")
@@ -158,9 +120,9 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
val newCandidateDescriptor =
when (function) {
is FunctionImportedFromObject ->
getOrCreateJvmSuspendFunctionView(function.callableFromObject, isReleaseCoroutines, bindingContext).asImportedFromObject()
getOrCreateJvmSuspendFunctionView(function.callableFromObject, bindingContext).asImportedFromObject()
is SimpleFunctionDescriptor ->
getOrCreateJvmSuspendFunctionView(function, isReleaseCoroutines, bindingContext)
getOrCreateJvmSuspendFunctionView(function, bindingContext)
else ->
throw AssertionError("Unexpected suspend function descriptor: $function")
}
@@ -223,10 +185,10 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
enum class SuspensionPointKind { NEVER, NOT_INLINE, ALWAYS }
fun ResolvedCall<*>.isSuspensionPoint(codegen: ExpressionCodegen, languageVersionSettings: LanguageVersionSettings): SuspensionPointKind {
fun ResolvedCall<*>.isSuspensionPoint(codegen: ExpressionCodegen): SuspensionPointKind {
val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return SuspensionPointKind.NEVER
if (!functionDescriptor.unwrapInitialDescriptorForSuspendFunction().isSuspend) return SuspensionPointKind.NEVER
if (functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings)) return SuspensionPointKind.ALWAYS
if (functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return SuspensionPointKind.ALWAYS
if (functionDescriptor.isInline) return SuspensionPointKind.NEVER
val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>()
@@ -242,7 +204,6 @@ fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, state: GenerationState): D = getOrCreateJvmSuspendFunctionView(
function,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
state.bindingContext
)
@@ -252,7 +213,6 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, stat
@JvmOverloads
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
function: D,
isReleaseCoroutines: Boolean,
bindingContext: BindingContext? = null
): D {
assert(function.isSuspend) {
@@ -272,7 +232,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.isBuiltinFunctionalClassDescriptor == true)
function.builtIns.nullableAnyType
else
function.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines),
function.getContinuationParameterTypeOfSuspendFunction(),
declaresDefaultValue = false, isCrossinline = false,
isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
@@ -309,8 +269,7 @@ fun <D : FunctionDescriptor> D.createCustomCopy(
return result as D
}
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines: Boolean) =
module.getContinuationOfTypeOrAny(returnType!!, if (this.needsExperimentalCoroutinesWrapper()) false else isReleaseCoroutines)
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() = module.getContinuationOfTypeOrAny(returnType!!)
fun ModuleDescriptor.getResult(kotlinType: KotlinType) =
module.resolveTopLevelClass(
@@ -323,44 +282,11 @@ fun ModuleDescriptor.getResult(kotlinType: KotlinType) =
)
} ?: ErrorUtils.createErrorType("For Result")
private fun MethodNode.invokeNormalizeContinuation(languageVersionSettings: LanguageVersionSettings) {
visitMethodInsn(
Opcodes.INVOKESTATIC,
languageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName(),
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType()),
false
)
}
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) == true
fun createMethodNodeForIntercepted(languageVersionSettings: LanguageVersionSettings): MethodNode {
val node =
MethodNode(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType()),
null, null
)
node.visitVarInsn(Opcodes.ALOAD, 0)
node.invokeNormalizeContinuation(languageVersionSettings)
node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1)
return node
}
fun createMethodNodeForCoroutineContext(
functionDescriptor: FunctionDescriptor,
languageVersionSettings: LanguageVersionSettings
): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext(languageVersionSettings)) {
fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext()) {
"functionDescriptor must be kotlin.coroutines.intrinsics.coroutineContext property getter"
}
@@ -369,7 +295,7 @@ fun createMethodNodeForCoroutineContext(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType()),
Type.getMethodDescriptor(coroutineContextAsmType()),
null, null
)
@@ -377,20 +303,20 @@ fun createMethodNodeForCoroutineContext(
addFakeContinuationMarker(v)
v.invokeGetContext(languageVersionSettings)
v.invokeGetContext()
node.visitMaxs(1, 1)
return node
}
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): MethodNode {
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(): MethodNode {
val node =
MethodNode(
Opcodes.API_VERSION,
Opcodes.ACC_STATIC,
"fake",
Type.getMethodDescriptor(OBJECT_TYPE, AsmTypes.FUNCTION1, languageVersionSettings.continuationAsmType()),
Type.getMethodDescriptor(OBJECT_TYPE, AsmTypes.FUNCTION1, CONTINUATION_ASM_TYPE),
null, null
)
@@ -405,25 +331,22 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSett
"($OBJECT_TYPE)$OBJECT_TYPE"
)
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) {
val elseLabel = Label()
// if (result === COROUTINE_SUSPENDED) {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
ifacmpne(elseLabel)
// DebugProbesKt.probeCoroutineSuspended(continuation)
load(1, OBJECT_TYPE) // continuation
checkcast(languageVersionSettings.continuationAsmType())
invokestatic(
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("DebugProbesKt"))
.topLevelClassAsmType().internalName,
"probeCoroutineSuspended",
"(${languageVersionSettings.continuationAsmType()})V",
false
)
// }
mark(elseLabel)
}
val elseLabel = Label()
// if (result === COROUTINE_SUSPENDED) {
dup()
loadCoroutineSuspendedMarker()
ifacmpne(elseLabel)
// DebugProbesKt.probeCoroutineSuspended(continuation)
load(1, OBJECT_TYPE) // continuation
checkcast(CONTINUATION_ASM_TYPE)
invokestatic(
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("DebugProbesKt")).topLevelClassAsmType().internalName,
"probeCoroutineSuspended",
"($CONTINUATION_ASM_TYPE)V",
false
)
// }
mark(elseLabel)
}
node.visitInsn(Opcodes.ARETURN)
@@ -433,13 +356,13 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSett
}
private fun InstructionAdapter.invokeGetContext(languageVersionSettings: LanguageVersionSettings) {
private fun InstructionAdapter.invokeGetContext() {
invokeinterface(
languageVersionSettings.continuationAsmType().internalName,
CONTINUATION_ASM_TYPE.internalName,
GET_CONTEXT_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType())
Type.getMethodDescriptor(coroutineContextAsmType())
)
areturn(languageVersionSettings.coroutineContextAsmType())
areturn(coroutineContextAsmType())
}
@Suppress("UNCHECKED_CAST")
@@ -447,15 +370,12 @@ fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, isReleaseCoroutines: Boolean): FunctionDescriptor =
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor =
if (isSuspend)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, isReleaseCoroutines, bindingContext)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext)
else
this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, state: GenerationState) =
getOriginalSuspendFunctionView(bindingContext, state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
// For each suspend function, we have a corresponding JVM view function that has an extra continuation parameter,
// and, more importantly, returns 'kotlin.Any' (so that it can return as a reference value or a special COROUTINE_SUSPENDED object).
// This also causes boxing of primitives and inline class values.
@@ -482,38 +402,24 @@ fun FunctionDescriptor.originalReturnTypeOfSuspendFunctionReturningUnboxedInline
return originalReturnType
}
fun InstructionAdapter.loadCoroutineSuspendedMarker(languageVersionSettings: LanguageVersionSettings) {
fun InstructionAdapter.loadCoroutineSuspendedMarker() {
invokestatic(
languageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName().internalName,
coroutinesIntrinsicsFileFacadeInternalName.internalName,
"get$COROUTINE_SUSPENDED_NAME",
Type.getMethodDescriptor(OBJECT_TYPE),
false
)
}
fun InstructionAdapter.generateCoroutineSuspendedCheck(languageVersionSettings: LanguageVersionSettings) {
fun InstructionAdapter.generateCoroutineSuspendedCheck() {
dup()
loadCoroutineSuspendedMarker(languageVersionSettings)
loadCoroutineSuspendedMarker()
val elseLabel = Label()
ifacmpne(elseLabel)
areturn(OBJECT_TYPE)
mark(elseLabel)
}
fun InstructionAdapter.invokeDoResumeWithUnit(thisName: String) {
// .doResume(Unit, null)
StackValue.putUnitInstance(this)
aconst(null)
invokevirtual(
thisName,
DO_RESUME_METHOD_NAME,
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, AsmTypes.JAVA_THROWABLE_TYPE),
false
)
}
fun InstructionAdapter.invokeInvokeSuspendWithUnit(thisName: String) {
StackValue.putUnitInstance(this)
@@ -537,18 +443,14 @@ fun FunctionDescriptor.isSuspendLambdaOrLocalFunction() = this.isSuspend && when
}
fun FunctionDescriptor.isLocalSuspendFunctionNotSuspendLambda() = isSuspendLambdaOrLocalFunction() && this !is AnonymousFunctionDescriptor
@JvmField
val EXPERIMENTAL_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL.topLevelClassAsmType()
@JvmField
val RELEASE_CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.topLevelClassAsmType()
val CONTINUATION_ASM_TYPE = StandardNames.CONTINUATION_INTERFACE_FQ_NAME.topLevelClassAsmType()
fun FunctionDescriptor.isInvokeSuspendOfLambda(): Boolean {
if (this !is SimpleFunctionDescriptor) return false
if (valueParameters.size != 1 ||
valueParameters[0].name.asString() != SUSPEND_CALL_RESULT_NAME ||
name.asString() != "invokeSuspend"
name.asString() != INVOKE_SUSPEND_METHOD_NAME
) return false
return containingDeclaration is SyntheticClassDescriptorForLambda
}
@@ -62,7 +62,7 @@ class AnonymousObjectTransformer(
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
classBuilder.defineClass(null, maxOf(version, state.classFileVersion), access, name, signature, superName, interfaces)
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
if (superName.isCoroutineSuperClass()) {
inliningContext.isContinuation = true
}
superClassName = superName
@@ -104,7 +104,7 @@ class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompiler
// TODO: suspend lambdas are their own continuations, so the body is pre-inlined into `invokeSuspend`
// and thus can't be detangled from the state machine. To make them inlinable, this needs to be redesigned.
// See `SuspendLambdaLowering`.
require(!sourceCompiler.state.languageVersionSettings.isCoroutineSuperClass(superName)) {
require(!superName.isCoroutineSuperClass()) {
"suspend default lambda ${lambdaClassType.internalName} cannot be inlined; use a function reference instead"
}
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.inline.coroutines.markNoinlineLambdaIfSuspend
@@ -688,7 +688,7 @@ class MethodInliner(
}
for ((index, param) in paramTypes.reversed().withIndex()) {
if (param != languageVersionSettings.continuationAsmType() && param != OBJECT_TYPE) continue
if (param != CONTINUATION_ASM_TYPE && param != OBJECT_TYPE) continue
val sourceIndices = (frame.getStack(frame.stackSize - index - 1) as? Aload0BasicValue)?.indices ?: continue
for (sourceIndex in sourceIndices) {
val src = processingNode.instructions[sourceIndex]
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.psi.*
@@ -158,8 +157,7 @@ class PsiSourceCompilerForInline(
}
FunctionCodegen.generateMethodBody(
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode,
state.languageVersionSettings.isReleaseCoroutines()
adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode
)
if (isLambda) {
@@ -235,7 +233,7 @@ class PsiSourceCompilerForInline(
}
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
generateInlineIntrinsic(state.languageVersionSettings, functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
generateInlineIntrinsic(functionDescriptor, jvmSignature.asmMethod, codegen.typeSystem)?.let {
return it
}
@@ -22,8 +22,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType
@@ -233,7 +231,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
if (stubCheckcast !is TypeInsnNode) return false
val newMethodNode = MethodNode(Opcodes.API_VERSION)
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, languageVersionSettings, unifiedNullChecks)
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, unifiedNullChecks)
instructions.insert(insn, newMethodNode.instructions)
// Keep stubCheckcast to avoid VerifyErrors on 1.8+ bytecode,
@@ -257,7 +255,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
if (stubInstanceOf !is TypeInsnNode) return false
val newMethodNode = MethodNode(Opcodes.API_VERSION)
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType, languageVersionSettings.isReleaseCoroutines())
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType)
instructions.insert(insn, newMethodNode.instructions)
instructions.remove(stubInstanceOf)
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.MethodVisitor
@@ -49,18 +48,16 @@ class CoroutineTransformer(
fun suspendLambdaWithGeneratedStateMachine(node: MethodNode): Boolean =
!isContinuationNotLambda() && isSuspendLambda(node) && isStateMachine(node)
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
if (state.languageVersionSettings.isReleaseCoroutines()) superClassName.endsWith("ContinuationImpl")
else methods.any { it.name == "getLabel" }
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation && superClassName.endsWith("ContinuationImpl")
private fun isStateMachine(node: MethodNode): Boolean =
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
private fun isSuspendLambda(node: MethodNode) = isInvokeSuspend(node)
fun newMethod(node: MethodNode): DeferredMethodVisitor {
return when {
isResumeImpl(node) -> {
isInvokeSuspend(node) -> {
assert(!isStateMachine(node)) {
"Inlining/transforming state-machine"
}
@@ -71,9 +68,8 @@ class CoroutineTransformer(
}
}
private fun isResumeImpl(node: MethodNode): Boolean =
state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
inliningContext.isContinuation
private fun isInvokeSuspend(node: MethodNode): Boolean =
node.name.removeSuffix(FOR_INLINE_SUFFIX) == INVOKE_SUSPEND_METHOD_NAME && inliningContext.isContinuation
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
@@ -88,16 +84,15 @@ class CoroutineTransformer(
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
containingClassInternalName = classBuilder.thisName,
obtainClassBuilderForCoroutineState = { classBuilder },
isForNamedFunction = false,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = false,
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
// TODO: this linenumbers might not be correct and since they are used only for step-over, check them.
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
isForNamedFunction = false,
disableTailCallOptimizationForFunctionReturningUnit = false,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
@@ -123,17 +118,16 @@ class CoroutineTransformer(
val sourceCompilerForInline = inliningContext.root.sourceCompilerForInline
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
containingClassInternalName = classBuilder.thisName,
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
isForNamedFunction = true,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
reportSuspensionPointInsideMonitor = { sourceCompilerForInline.reportSuspensionPointInsideMonitor(it) },
lineNumber = inliningContext.callSiteInfo.lineNumber,
sourceFile = inliningContext.callSiteInfo.file?.name ?: "",
languageVersionSettings = state.languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classBuilder.thisName,
isForNamedFunction = true,
needDispatchReceiver = true,
internalNameForDispatchReceiver = classBuilder.thisName,
disableTailCallOptimizationForFunctionReturningUnit = disableTailCallOptimization,
putContinuationParameterToLvt = !state.isIrBackend,
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS)
)
@@ -5,13 +5,11 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForCoroutineContext
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForIntercepted
import org.jetbrains.kotlin.codegen.coroutines.createMethodNodeForSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.codegen.createMethodNodeForAlwaysEnabledAssert
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
@@ -30,25 +28,22 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.Method
import org.jetbrains.org.objectweb.asm.tree.MethodNode
fun generateInlineIntrinsicForIr(languageVersionSettings: LanguageVersionSettings, descriptor: FunctionDescriptor): SMAPAndMethodNode? =
fun generateInlineIntrinsicForIr(descriptor: FunctionDescriptor): SMAPAndMethodNode? =
when {
// TODO: implement these as codegen intrinsics (see IrIntrinsicMethods)
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
createMethodNodeForIntercepted(languageVersionSettings)
descriptor.isBuiltInCoroutineContext(languageVersionSettings) ->
createMethodNodeForCoroutineContext(descriptor, languageVersionSettings)
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSettings)
descriptor.isBuiltInCoroutineContext() ->
createMethodNodeForCoroutineContext(descriptor)
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn() ->
createMethodNodeForSuspendCoroutineUninterceptedOrReturn()
else -> null
}?.let { SMAPAndMethodNode(it, SMAP(listOf())) }
internal fun generateInlineIntrinsic(
languageVersionSettings: LanguageVersionSettings,
descriptor: FunctionDescriptor,
asmMethod: Method,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode? {
return generateInlineIntrinsicForIr(languageVersionSettings, descriptor) ?: when {
return generateInlineIntrinsicForIr(descriptor) ?: when {
isSpecialEnumMethod(descriptor) ->
createSpecialEnumMethodBody(descriptor.name.asString(), descriptor.original.typeParameters.single(), typeSystem)
TypeOfChecker.isTypeOf(descriptor) ->
@@ -19,7 +19,7 @@ import org.jetbrains.org.objectweb.asm.tree.*
object TypeIntrinsics {
@JvmStatic
fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type, isReleaseCoroutines: Boolean) {
fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type) {
val functionTypeArity = getFunctionTypeArity(jetType)
if (functionTypeArity >= 0) {
v.iconst(functionTypeArity)
@@ -27,28 +27,26 @@ object TypeIntrinsics {
return
}
if (isReleaseCoroutines) {
val suspendFunctionTypeArity = getSuspendFunctionTypeArity(jetType)
if (suspendFunctionTypeArity >= 0) {
val notSuspendLambda = Label()
val end = Label()
val suspendFunctionTypeArity = getSuspendFunctionTypeArity(jetType)
if (suspendFunctionTypeArity >= 0) {
val notSuspendLambda = Label()
val end = Label()
with(v) {
dup()
instanceOf(AsmTypes.SUSPEND_FUNCTION_TYPE)
ifeq(notSuspendLambda)
iconst(suspendFunctionTypeArity + 1)
typeIntrinsic(IS_FUNCTON_OF_ARITY_METHOD_NAME, IS_FUNCTON_OF_ARITY_DESCRIPTOR)
goTo(end)
with(v) {
dup()
instanceOf(AsmTypes.SUSPEND_FUNCTION_TYPE)
ifeq(notSuspendLambda)
iconst(suspendFunctionTypeArity + 1)
typeIntrinsic(IS_FUNCTON_OF_ARITY_METHOD_NAME, IS_FUNCTON_OF_ARITY_DESCRIPTOR)
goTo(end)
mark(notSuspendLambda)
pop()
iconst(0)
mark(notSuspendLambda)
pop()
iconst(0)
mark(end)
}
return
mark(end)
}
return
}
val isMutableCollectionMethodName = getIsMutableCollectionMethodName(jetType)
@@ -17,9 +17,8 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.RELEASE_COROUTINES_VERSION_SETTINGS
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
@@ -216,7 +215,7 @@ fun AbstractInsnNode.isPrimitiveBoxing() =
}
private val BOXING_CLASS_INTERNAL_NAME =
RELEASE_COROUTINES_VERSION_SETTINGS.coroutinesJvmInternalPackageFqName().child(Name.identifier("Boxing")).topLevelClassInternalName()
StandardNames.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("Boxing")).topLevelClassInternalName()
private fun isJvmPrimitiveName(name: String) = JvmPrimitiveType.values().any { it.javaKeywordName == name }
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.diagnostics.PrecomputedSuppressCache
@@ -158,8 +157,7 @@ class GenerationState private constructor(
CompilerDeserializationConfiguration(languageVersionSettings)
val deprecationProvider = DeprecationResolver(
LockBasedStorageManager.NO_LOCKS, languageVersionSettings, CoroutineCompatibilitySupport.ENABLED,
JavaDeprecationSettings
LockBasedStorageManager.NO_LOCKS, languageVersionSettings, JavaDeprecationSettings
)
init {
@@ -193,7 +193,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
if (descriptor.isSuspendFunctionNotSuspensionView()) {
return mapReturnType(getOrCreateJvmSuspendFunctionView(descriptor as SimpleFunctionDescriptor, isReleaseCoroutines), sw)
return mapReturnType(getOrCreateJvmSuspendFunctionView(descriptor as SimpleFunctionDescriptor), sw)
}
if (hasVoidReturnType(descriptor)) {
@@ -804,7 +804,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
if (f.isSuspendFunctionNotSuspensionView()) {
return mapSignature(getOrCreateJvmSuspendFunctionView(f, isReleaseCoroutines), kind, skipGenericSignature)
return mapSignature(getOrCreateJvmSuspendFunctionView(f), kind, skipGenericSignature)
}
if (isDeclarationOfBigArityFunctionInvoke(f) || isDeclarationOfBigArityCreateCoroutineMethod(f)) {
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.load.java.components.JavaDeprecationSettings
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType
@@ -84,7 +83,6 @@ class CliLightClassGenerationSupport(
get() = DeprecationResolver(
LockBasedStorageManager.NO_LOCKS,
languageVersionSettings,
CoroutineCompatibilitySupport.ENABLED,
JavaDeprecationSettings
)
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
fun LanguageVersionSettings.coroutinesPackageFqName(): FqName {
return coroutinesPackageFqName(isReleaseCoroutines())
}
fun LanguageVersionSettings.isReleaseCoroutines() = supportsFeature(LanguageFeature.ReleaseCoroutines)
private fun coroutinesPackageFqName(isReleaseCoroutines: Boolean): FqName {
return if (isReleaseCoroutines)
StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
else
StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL
}
fun LanguageVersionSettings.coroutinesIntrinsicsPackageFqName() =
coroutinesPackageFqName().child(Name.identifier("intrinsics"))
fun LanguageVersionSettings.continuationInterfaceFqName() =
coroutinesPackageFqName().child(Name.identifier("Continuation"))
fun LanguageVersionSettings.restrictsSuspensionFqName() =
coroutinesPackageFqName().child(Name.identifier("RestrictsSuspension"))
fun FqName.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
this == StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
else
this == StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext")) ||
this == StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
@@ -33,13 +33,13 @@ import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_3_FQ_NAME
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_FQ_NAME
import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
private val RESTRICTS_SUSPENSION_CLASS_ID =
ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, Name.identifier("RestrictsSuspension"))
ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME, Name.identifier("RestrictsSuspension"))
private val BUILTIN_SUSPEND_NAME = KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME.shortName()
@@ -56,7 +56,7 @@ object FirSuspendCallChecker : FirQualifiedAccessExpressionChecker() {
if (reference is FirResolvedCallableReference) return
when (symbol) {
is FirNamedFunctionSymbol -> if (!symbol.isSuspend) return
is FirPropertySymbol -> if (symbol.callableId.asSingleFqName() != COROUTINE_CONTEXT_1_3_FQ_NAME) return
is FirPropertySymbol -> if (symbol.callableId.asSingleFqName() != COROUTINE_CONTEXT_FQ_NAME) return
else -> return
}
val enclosingSuspendFunction = findEnclosingSuspendFunction(context)
@@ -9,4 +9,4 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.name.ClassId
val CONTINUATION_INTERFACE_CLASS_ID = ClassId.topLevel(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE)
val CONTINUATION_INTERFACE_CLASS_ID = ClassId.topLevel(StandardNames.CONTINUATION_INTERFACE_FQ_NAME)
@@ -26,6 +26,4 @@ class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVers
override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName)
override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts)
override val releaseCoroutines: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtExpression
@@ -33,20 +34,17 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val COROUTINE_CONTEXT_1_2_20_FQ_NAME =
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
val COROUTINE_CONTEXT_FQ_NAME =
StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext"))
val COROUTINE_CONTEXT_1_2_30_FQ_NAME =
StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
fun FqName.isBuiltInCoroutineContext(): Boolean =
this == StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext"))
val COROUTINE_CONTEXT_1_3_FQ_NAME =
StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
fun FunctionDescriptor.isBuiltInCoroutineContext() =
(this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe?.isBuiltInCoroutineContext() == true
fun FunctionDescriptor.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
(this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe?.isBuiltInCoroutineContext(languageVersionSettings) == true
fun PropertyDescriptor.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
this.fqNameSafe.isBuiltInCoroutineContext(languageVersionSettings)
fun PropertyDescriptor.isBuiltInCoroutineContext() =
fqNameSafe.isBuiltInCoroutineContext()
private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING)
@@ -60,11 +58,7 @@ object CoroutineSuspendCallChecker : CallChecker {
val descriptor = resolvedCall.candidateDescriptor
when (descriptor) {
is FunctionDescriptor -> if (!descriptor.isSuspend) return
is PropertyDescriptor -> when (descriptor.fqNameSafe) {
COROUTINE_CONTEXT_1_2_20_FQ_NAME, COROUTINE_CONTEXT_1_2_30_FQ_NAME, COROUTINE_CONTEXT_1_3_FQ_NAME -> {
}
else -> return
}
is PropertyDescriptor -> if (descriptor.fqNameSafe != COROUTINE_CONTEXT_FQ_NAME) return
else -> return
}
@@ -92,17 +86,6 @@ object CoroutineSuspendCallChecker : CallChecker {
context.trace.report(Errors.UNSUPPORTED.on(reportOn, "suspend function calls in a context of default parameter value"))
}
if ((descriptor.fqNameSafe == COROUTINE_CONTEXT_1_2_20_FQ_NAME || descriptor.fqNameSafe == COROUTINE_CONTEXT_1_2_30_FQ_NAME) &&
context.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
) {
context.trace.report(
Errors.UNSUPPORTED.on(
reportOn,
"experimental coroutineContext of release coroutine: use kotlin.coroutines.coroutineContext instead"
)
)
}
context.trace.record(
BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL,
resolvedCall.call,
@@ -169,8 +152,10 @@ fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, dia
}
}
fun KotlinType.isRestrictsSuspensionReceiver(languageVersionSettings: LanguageVersionSettings) = (listOf(this) + this.supertypes()).any {
it.constructor.declarationDescriptor?.annotations?.hasAnnotation(languageVersionSettings.restrictsSuspensionFqName()) == true
fun KotlinType.isRestrictsSuspensionReceiver() = (listOf(this) + this.supertypes()).any {
it.constructor.declarationDescriptor?.annotations?.hasAnnotation(
StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("RestrictsSuspension"))
) == true
}
private fun checkRestrictsSuspension(
@@ -179,7 +164,7 @@ private fun checkRestrictsSuspension(
reportOn: PsiElement,
context: CallCheckerContext
) {
fun ReceiverValue.isRestrictsSuspensionReceiver() = type.isRestrictsSuspensionReceiver(context.languageVersionSettings)
fun ReceiverValue.isRestrictsSuspensionReceiver() = type.isRestrictsSuspensionReceiver()
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
if (other == null) return false
@@ -47,7 +47,6 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.deprecation.DeprecationSettings
@@ -338,7 +337,6 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
val deprecationResolver = DeprecationResolver(
LockBasedStorageManager("ExperimentalUsageChecker"),
languageVersionSettings,
CoroutineCompatibilitySupport.ENABLED,
DeprecationSettings.Default
)
@@ -132,17 +132,6 @@ internal data class DeprecatedByOverridden(private val deprecations: Collection<
"Overrides deprecated member in '${DescriptorUtils.getContainingClass(target)!!.fqNameSafe.asString()}'"
}
internal data class DeprecatedExperimentalCoroutine(
override val target: DeclarationDescriptor,
override val deprecationLevel: DeprecationLevelValue
) : Deprecation {
override val message: String? =
if (deprecationLevel == WARNING)
"Experimental coroutines support will be dropped in 1.4"
else
"Experimental coroutine cannot be used with API version 1.3"
}
internal data class DeprecatedOperatorMod(
val languageVersionSettings: LanguageVersionSettings,
val currentDeprecation: Deprecation
@@ -27,8 +27,6 @@ import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode.COMPATIBLE
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode.NEEDS_WRAPPER
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -38,7 +36,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class DeprecationResolver(
storageManager: StorageManager,
private val languageVersionSettings: LanguageVersionSettings,
private val coroutineCompatibilitySupport: CoroutineCompatibilitySupport,
private val deprecationSettings: DeprecationSettings
) {
private val deprecations = storageManager.createMemoizedFunction { descriptor: DeclarationDescriptor ->
@@ -226,7 +223,6 @@ class DeprecationResolver(
for (deprecation in getDeprecationByVersionRequirement(this)) {
result.add(deprecation)
}
getDeprecationByCoroutinesVersion(this)?.let(result::add)
getDeprecationFromUserData(this)?.let(result::add)
}
@@ -242,19 +238,6 @@ class DeprecationResolver(
descriptor.valueParameters.singleOrNull()?.type?.let(KotlinBuiltIns::isInt) == true &&
languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_3
private fun getDeprecationByCoroutinesVersion(target: DeclarationDescriptor): DeprecatedExperimentalCoroutine? {
if (target !is DeserializedMemberDescriptor) return null
target.coroutinesExperimentalCompatibilityMode.let { mode ->
return when {
mode == COMPATIBLE -> null
mode == NEEDS_WRAPPER && coroutineCompatibilitySupport.enabled ->
DeprecatedExperimentalCoroutine(target, DeprecationLevelValue.WARNING)
else -> DeprecatedExperimentalCoroutine(target, DeprecationLevelValue.ERROR)
}
}
}
private fun getDeprecationFromUserData(target: DeclarationDescriptor): Deprecation? =
target.safeAs<CallableDescriptor>()?.getUserData(DEPRECATED_FUNCTION_KEY)
@@ -73,18 +73,6 @@ internal fun createDeprecationDiagnostic(
}
}
@DefaultImplementation(CoroutineCompatibilitySupport::class)
class CoroutineCompatibilitySupport private constructor(val enabled: Boolean) : PlatformSpecificExtension<CoroutineCompatibilitySupport>{
@Suppress("unused")
constructor() : this(true)
companion object {
val ENABLED = CoroutineCompatibilitySupport(true)
val DISABLED = CoroutineCompatibilitySupport(false)
}
}
@DefaultImplementation(DeprecationSettings.Default::class)
interface DeprecationSettings {
fun propagatedToOverrides(deprecationAnnotation: AnnotationDescriptor): Boolean
@@ -700,7 +700,7 @@ class DoubleColonExpressionResolver(
) {
val descriptor =
if (resolutionResults?.isSingleResult == true) resolutionResults.resultingDescriptor else null
if (descriptor is PropertyDescriptor && descriptor.isBuiltInCoroutineContext(languageVersionSettings)) {
if (descriptor is PropertyDescriptor && descriptor.isBuiltInCoroutineContext()) {
context.trace.report(UNSUPPORTED.on(expression.callableReference, "Callable reference to suspend property"))
} else if (descriptor is FunctionDescriptor && descriptor.isSuspend
&& !context.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
@@ -14,9 +14,9 @@ import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.ir.isPure
import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -54,26 +54,18 @@ fun IrFunction.isTopLevelInPackage(name: String, packageName: String): Boolean {
return packageName == packageFqName
}
fun IrFunction.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean =
!languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) &&
isTopLevelInPackage("intercepted", languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString())
fun IrFunction.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean =
fun IrFunction.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean =
isTopLevelInPackage(
"suspendCoroutineUninterceptedOrReturn",
languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString()
StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.asString()
)
open class DefaultInlineFunctionResolver(open val context: CommonBackendContext) : InlineFunctionResolver {
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
val function = symbol.owner
val languageVersionSettings = context.configuration.languageVersionSettings
// TODO: Remove these hacks when coroutine intrinsics are fixed.
return when {
function.isBuiltInIntercepted(languageVersionSettings) ->
error("Continuation.intercepted is not available with release coroutines")
function.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
function.isBuiltInSuspendCoroutineUninterceptedOrReturn() ->
context.ir.symbols.suspendCoroutineUninterceptedOrReturn.owner
symbol == context.ir.symbols.coroutineContextGetter ->
@@ -248,7 +248,7 @@ class JvmSymbols(
val assertionErrorConstructor = javaLangAssertionError.constructors.single()
val continuationClass: IrClassSymbol =
createClass(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE, ClassKind.INTERFACE) { klass ->
createClass(StandardNames.CONTINUATION_INTERFACE_FQ_NAME, ClassKind.INTERFACE) { klass ->
klass.addTypeParameter("T", irBuiltIns.anyNType, Variance.IN_VARIANCE)
}
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
@@ -45,7 +45,7 @@ internal fun MethodNode.acceptWithStateMachine(
) {
val state = classCodegen.context.state
val languageVersionSettings = state.languageVersionSettings
assert(languageVersionSettings.isReleaseCoroutines()) { "Experimental coroutines are unsupported in JVM_IR backend" }
assert(languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)) { "Experimental coroutines are unsupported in JVM_IR backend" }
val element = if (irFunction.isSuspend)
irFunction.psiElement ?: classCodegen.irClass.psiElement
else
@@ -67,21 +67,20 @@ internal fun MethodNode.acceptWithStateMachine(
val visitor = CoroutineTransformerMethodVisitor(
methodVisitor, access, name, desc, signature, exceptions.toTypedArray(),
containingClassInternalName = classCodegen.type.internalName,
obtainClassBuilderForCoroutineState = obtainContinuationClassBuilder,
isForNamedFunction = irFunction.isSuspend,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
disableTailCallOptimizationForFunctionReturningUnit = irFunction.isSuspend && irFunction.suspendFunctionOriginal().let {
it.returnType.isUnit() && it.anyOfOverriddenFunctionsReturnsNonUnit()
},
reportSuspensionPointInsideMonitor = { reportSuspensionPointInsideMonitor(element as KtElement, state, it) },
lineNumber = lineNumber,
sourceFile = classCodegen.irClass.file.name,
languageVersionSettings = languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = classCodegen.type.internalName,
isForNamedFunction = irFunction.isSuspend, // SuspendLambda.invokeSuspend is not suspend
sourceFile = classCodegen.irClass.file.name, // SuspendLambda.invokeSuspend is not suspend
needDispatchReceiver = irFunction.isSuspend && (irFunction.dispatchReceiverParameter != null
|| irFunction.origin == JvmLoweredDeclarationOrigin.SUSPEND_IMPL_STATIC_FUNCTION),
internalNameForDispatchReceiver = classCodegen.type.internalName,
putContinuationParameterToLvt = false,
disableTailCallOptimizationForFunctionReturningUnit = irFunction.isSuspend && irFunction.suspendFunctionOriginal().let {
it.returnType.isUnit() && it.anyOfOverriddenFunctionsReturnsNonUnit()
},
useOldSpilledVarTypeAnalysis = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS),
initialVarsCountByType = varsCountByType,
)
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.isReleaseCoroutines
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.diagnostics.Errors
@@ -534,7 +533,7 @@ class ExpressionCodegen(
MaterialValue(this, unboxedInlineClassIrType.asmType, unboxedInlineClassIrType).apply {
if (!irFunction.shouldContainSuspendMarkers()) {
// Since the coroutine transformer won't run, we need to do this manually.
mv.generateCoroutineSuspendedCheck(state.languageVersionSettings)
mv.generateCoroutineSuspendedCheck()
}
mv.checkcast(type)
}
@@ -1050,7 +1049,7 @@ class ExpressionCodegen(
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS)
mv.instanceOf(type)
} else {
TypeIntrinsics.instanceOf(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
TypeIntrinsics.instanceOf(mv, kotlinType, type)
}
expression.onStack
}
@@ -68,7 +68,7 @@ class IrSourceCompilerForInline(
}
override fun compileInlineFunction(jvmSignature: JvmMethodSignature): SMAPAndMethodNode {
generateInlineIntrinsicForIr(state.languageVersionSettings, callee.toIrBasedDescriptor())?.let {
generateInlineIntrinsicForIr(callee.toIrBasedDescriptor())?.let {
return it
}
if (jvmSignature.asmMethod.name != callee.name.asString()) {
@@ -104,7 +104,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
copyTypeParametersFrom(irFunction)
val resultField = addField {
origin = JvmLoweredDeclarationOrigin.CONTINUATION_CLASS_RESULT_FIELD
name = Name.identifier(context.state.languageVersionSettings.dataFieldName())
name = Name.identifier(CONTINUATION_RESULT_FIELD_NAME)
type = context.ir.symbols.resultOfAnyType
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
}
@@ -41,7 +41,7 @@ object IdSignatureValues {
@JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Comparable")
@JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "CharSequence")
@JvmField val iterable = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Iterable")
@JvmField val continuation = getPublicSignature(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, "Continuation")
@JvmField val continuation = getPublicSignature(StandardNames.COROUTINES_PACKAGE_FQ_NAME, "Continuation")
@JvmField val result = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Result")
@JvmField val sequence = IdSignature.CommonSignature("kotlin.sequences", "Sequence", null, 0)
}
@@ -157,7 +157,7 @@ fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean): Boolean
fun IrType.isKotlinResult(): Boolean = isClassType(StandardNames.RESULT_FQ_NAME.toUnsafe(), false)
fun IrType.isNullableContinuation(): Boolean = isClassType(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.toUnsafe(), true)
fun IrType.isNullableContinuation(): Boolean = isClassType(StandardNames.CONTINUATION_INTERFACE_FQ_NAME.toUnsafe(), true)
// FIR and backend instances have different mask.
fun IrType.isKClass(): Boolean = isClassType(StandardNames.FqNames.kClass, false)
@@ -46,7 +46,7 @@ internal class KtUltraLightSuspendContinuationParameter(
get() {
val descriptor = ktFunction.resolve() as? FunctionDescriptor
val returnType = descriptor?.returnType ?: return null
return support.moduleDescriptor.getContinuationOfTypeOrAny(returnType, support.isReleasedCoroutine)
return support.moduleDescriptor.getContinuationOfTypeOrAny(returnType)
}
private val psiType by lazyPub {
@@ -624,7 +624,7 @@ class DescriptorSerializer private constructor(
}
if (type.isSuspendFunctionType) {
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines()))
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type))
functionType.flags = Flags.getTypeFlags(true, false)
return functionType
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen
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.load.java.JvmAbi
@@ -137,10 +136,6 @@ object InlineTestUtil {
return null
}
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
}
@@ -22,15 +22,13 @@ object StandardNames {
@JvmField val CHAR_CODE = Name.identifier("code")
@JvmField val COROUTINES_PACKAGE_FQ_NAME_RELEASE = FqName("kotlin.coroutines")
@JvmField val COROUTINES_PACKAGE_FQ_NAME = FqName("kotlin.coroutines")
@JvmField val COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("experimental"))
@JvmField val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME = FqName("kotlin.coroutines.jvm.internal")
@JvmField val COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("intrinsics"))
@JvmField val COROUTINES_INTRINSICS_PACKAGE_FQ_NAME = FqName("kotlin.coroutines.intrinsics")
@JvmField val CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL = COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("Continuation"))
@JvmField val CONTINUATION_INTERFACE_FQ_NAME_RELEASE = COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("Continuation"))
@JvmField val CONTINUATION_INTERFACE_FQ_NAME = COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("Continuation"))
@JvmField val RESULT_FQ_NAME = FqName("kotlin.Result")
@@ -68,7 +66,7 @@ object StandardNames {
ANNOTATION_PACKAGE_FQ_NAME,
KOTLIN_REFLECT_FQ_NAME,
BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal")),
COROUTINES_PACKAGE_FQ_NAME_RELEASE
COROUTINES_PACKAGE_FQ_NAME
)
object FqNames {
@@ -237,7 +235,7 @@ object StandardNames {
@JvmStatic
fun getSuspendFunctionClassId(parameterCount: Int): ClassId {
return ClassId(COROUTINES_PACKAGE_FQ_NAME_RELEASE, Name.identifier(getSuspendFunctionName(parameterCount)))
return ClassId(COROUTINES_PACKAGE_FQ_NAME, Name.identifier(getSuspendFunctionName(parameterCount)))
}
@JvmStatic
@@ -16,7 +16,7 @@ enum class FunctionClassKind(
val isReflectType: Boolean
) {
Function(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Function", isSuspendType = false, isReflectType = false),
SuspendFunction(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, "SuspendFunction", isSuspendType = true, isReflectType = false),
SuspendFunction(StandardNames.COROUTINES_PACKAGE_FQ_NAME, "SuspendFunction", isSuspendType = true, isReflectType = false),
KFunction(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KFunction", isSuspendType = false, isReflectType = true),
KSuspendFunction(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KSuspendFunction", isSuspendType = true, isReflectType = true);
@@ -75,7 +75,7 @@ object StandardClassIds {
val constantAllowedTypes = primitiveTypes + unsignedTypes + String
val Continuation =
ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.shortName())
ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME, StandardNames.CONTINUATION_INTERFACE_FQ_NAME.shortName())
@Suppress("FunctionName")
fun FunctionN(n: Int): ClassId {
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.load.java.lazy.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isContinuation
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
@@ -228,10 +228,8 @@ class LazyJavaClassMemberScope(
private fun SimpleFunctionDescriptor.createSuspendView(): SimpleFunctionDescriptor? {
val continuationParameter = valueParameters.lastOrNull()?.takeIf {
isContinuation(
it.type.constructor.declarationDescriptor?.fqNameUnsafe?.takeIf(FqNameUnsafe::isSafe)?.toSafe(),
c.components.settings.isReleaseCoroutines
)
it.type.constructor.declarationDescriptor?.fqNameUnsafe?.takeIf(FqNameUnsafe::isSafe)
?.toSafe() == CONTINUATION_INTERFACE_FQ_NAME
} ?: return null
val functionDescriptor = newCopyBuilder()
@@ -699,7 +697,11 @@ class LazyJavaClassMemberScope(
classDescriptor.declaredTypeParameters +
constructor.typeParameters.map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
constructorDescriptor.initialize(valueParameters.descriptors, constructor.visibility.toDescriptorVisibility(), constructorTypeParameters)
constructorDescriptor.initialize(
valueParameters.descriptors,
constructor.visibility.toDescriptorVisibility(),
constructorTypeParameters
)
constructorDescriptor.setHasStableParameterNames(false)
constructorDescriptor.setHasSynthesizedParameterNames(valueParameters.hasSynthesizedNames)
@@ -44,7 +44,7 @@ fun <T : Any> mapType(
if (kotlinType.isSuspendFunctionType) {
return mapType(
transformSuspendFunctionToRuntimeFunctionType(kotlinType, typeMappingConfiguration.releaseCoroutines()),
transformSuspendFunctionToRuntimeFunctionType(kotlinType),
factory, mode, typeMappingConfiguration, descriptorTypeWriter, writeGenericType
)
}
@@ -305,7 +305,7 @@ public abstract class KotlinBuiltIns {
@NotNull
public ClassDescriptor getSuspendFunction(int parameterCount) {
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier(getSuspendFunctionName(parameterCount))));
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier(getSuspendFunctionName(parameterCount))));
}
@NotNull
@@ -316,7 +316,7 @@ public abstract class KotlinBuiltIns {
@NotNull
public ClassDescriptor getKSuspendFunction(int parameterCount) {
Name name = Name.identifier(FunctionClassKind.KSuspendFunction.getClassNamePrefix() + parameterCount);
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(name));
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME.child(name));
}
@NotNull
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.K_FUNCTION_PREFIX
import org.jetbrains.kotlin.builtins.StandardNames.K_SUSPEND_FUNCTION_PREFIX
@@ -204,7 +204,7 @@ class ReflectionTypes(module: ModuleDescriptor, private val notFoundClasses: Not
|| shortName == "KCallable" || shortName == "KAnnotatedElement"
}
if (packageName == BUILT_INS_PACKAGE_FQ_NAME || packageName == COROUTINES_PACKAGE_FQ_NAME_RELEASE) {
if (packageName == BUILT_INS_PACKAGE_FQ_NAME || packageName == COROUTINES_PACKAGE_FQ_NAME) {
return shortName.startsWith("Function") // FunctionN, Function
|| shortName.startsWith("SuspendFunction")
}
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.builtins.functions
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -102,7 +102,7 @@ class FunctionClassDescriptor(
FunctionClassKind.SuspendFunction -> // SuspendFunction$N<...> <: Function
listOf(functionClassId)
FunctionClassKind.KSuspendFunction -> // KSuspendFunction$N<...> <: KFunction
listOf(kFunctionClassId, ClassId(COROUTINES_PACKAGE_FQ_NAME_RELEASE, FunctionClassKind.SuspendFunction.numberedClassName(arity)))
listOf(kFunctionClassId, ClassId(COROUTINES_PACKAGE_FQ_NAME, FunctionClassKind.SuspendFunction.numberedClassName(arity)))
}
val moduleDescriptor = containingDeclaration.containingDeclaration
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.builtins.functions
import org.jetbrains.kotlin.builtins.FunctionInterfacePackageFragment
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory
@@ -79,7 +79,7 @@ fun functionInterfacePackageFragmentProvider(
val fragments = listOf(
KOTLIN_REFLECT_FQ_NAME,
BUILT_INS_PACKAGE_FQ_NAME,
COROUTINES_PACKAGE_FQ_NAME_RELEASE
COROUTINES_PACKAGE_FQ_NAME
).map { fqName ->
FunctionInterfacePackageFragmentImpl(classFactory, module, fqName)
}
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
@@ -17,18 +15,17 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
private val FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL =
private val FAKE_CONTINUATION_CLASS_DESCRIPTOR =
MutableClassDescriptor(
EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL),
EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), COROUTINES_PACKAGE_FQ_NAME),
ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false,
CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL.shortName(), SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
CONTINUATION_INTERFACE_FQ_NAME.shortName(), SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
).apply {
modality = Modality.ABSTRACT
visibility = DescriptorVisibilities.PUBLIC
@@ -40,48 +37,26 @@ private val FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL =
createTypeConstructor()
}
private val FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE =
MutableClassDescriptor(
EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), COROUTINES_PACKAGE_FQ_NAME_RELEASE),
ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false,
CONTINUATION_INTERFACE_FQ_NAME_RELEASE.shortName(), SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
).apply {
modality = Modality.ABSTRACT
visibility = DescriptorVisibilities.PUBLIC
setTypeParameterDescriptors(
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0, LockBasedStorageManager.NO_LOCKS
).let(::listOf)
)
createTypeConstructor()
}
fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType, isReleaseCoroutines: Boolean): SimpleType {
fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType): SimpleType {
assert(suspendFunType.isSuspendFunctionType) {
"This type should be suspend function type: $suspendFunType"
}
return createFunctionType(
suspendFunType.builtIns,
suspendFunType.annotations,
suspendFunType.getReceiverTypeFromFunctionType(),
suspendFunType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType) +
KotlinTypeFactory.simpleType(
suspendFunType.builtIns,
suspendFunType.annotations,
suspendFunType.getReceiverTypeFromFunctionType(),
suspendFunType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType) +
KotlinTypeFactory.simpleType(
Annotations.EMPTY,
// Continuation interface is not a part of built-ins anymore, it has been moved to stdlib.
// While it must be somewhere in the dependencies, but here we don't have a reference to the module,
// and it's rather complicated to inject it by now, so we just use a fake class descriptor.
if (isReleaseCoroutines) FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE.typeConstructor
else FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL.typeConstructor,
FAKE_CONTINUATION_CLASS_DESCRIPTOR.typeConstructor,
listOf(suspendFunType.getReturnTypeFromFunctionType().asTypeProjection()), nullable = false
),
// TODO: names
null,
suspendFunType.builtIns.nullableAnyType
),
// TODO: names
null,
suspendFunType.builtIns.nullableAnyType
).makeNullableAsSpecified(suspendFunType.isMarkedNullable)
}
fun isContinuation(name: FqName?, isReleaseCoroutines: Boolean): Boolean {
return if (isReleaseCoroutines) name == CONTINUATION_INTERFACE_FQ_NAME_RELEASE
else name == CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
}
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -30,19 +29,15 @@ fun ModuleDescriptor.resolveClassByFqName(fqName: FqName, lookupLocation: Lookup
?.getContributedClassifier(fqName.shortName(), lookupLocation) as? ClassDescriptor
}
fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: LookupLocation, releaseCoroutines: Boolean) =
if (releaseCoroutines)
resolveClassByFqName(CONTINUATION_INTERFACE_FQ_NAME_RELEASE, lookupLocation)
else
resolveClassByFqName(CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL, lookupLocation)
fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: LookupLocation): ClassDescriptor? =
resolveClassByFqName(CONTINUATION_INTERFACE_FQ_NAME, lookupLocation)
fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation, releaseCoroutines: Boolean) =
findContinuationClassDescriptorOrNull(lookupLocation, releaseCoroutines).sure { "Continuation interface is not found" }
fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation) =
findContinuationClassDescriptorOrNull(lookupLocation).sure { "Continuation interface is not found" }
fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) =
fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType) =
module.findContinuationClassDescriptorOrNull(
NoLookupLocation.FROM_DESERIALIZATION,
isReleaseCoroutines
NoLookupLocation.FROM_DESERIALIZATION
)?.defaultType?.let {
KotlinTypeFactory.simpleType(
it,
@@ -27,9 +27,6 @@ interface DeserializationConfiguration {
val readDeserializedContracts: Boolean
get() = false
val releaseCoroutines: Boolean
get() = false
/**
* We may want to preserve the order of the declarations the same as in the serialized object
* (for example, to later create a decompiled code with the original order of declarations).
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.FieldDescriptorImpl
@@ -16,13 +15,9 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.contains
class MemberDeserializer(private val c: DeserializationContext) {
private val annotationDeserializer = AnnotationDeserializer(c.components.moduleDescriptor, c.components.notFoundClasses)
@@ -147,40 +142,21 @@ class MemberDeserializer(private val c: DeserializationContext) {
property.initialize(
getter, setter,
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = false), property),
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = true), property),
property.checkExperimentalCoroutine(local.typeDeserializer)
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = true), property)
)
return property
}
private fun DeserializedMemberDescriptor.checkExperimentalCoroutine(
typeDeserializer: TypeDeserializer
): DeserializedMemberDescriptor.CoroutinesCompatibilityMode {
if (!versionAndReleaseCoroutinesMismatch()) return CoroutinesCompatibilityMode.COMPATIBLE
forceUpperBoundsComputation(typeDeserializer)
return if (typeDeserializer.experimentalSuspendFunctionTypeEncountered)
CoroutinesCompatibilityMode.INCOMPATIBLE
else
CoroutinesCompatibilityMode.COMPATIBLE
}
private fun forceUpperBoundsComputation(typeDeserializer: TypeDeserializer) {
typeDeserializer.ownTypeParameters.forEach { it.upperBounds }
}
private fun DeserializedSimpleFunctionDescriptor.initializeWithCoroutinesExperimentalityStatus(
extensionReceiverParameter: ReceiverParameterDescriptor?,
dispatchReceiverParameter: ReceiverParameterDescriptor?,
typeParameters: List<TypeParameterDescriptor>,
unsubstitutedValueParameters: List<ValueParameterDescriptor>,
unsubstitutedReturnType: KotlinType?,
modality: Modality?,
visibility: DescriptorVisibility,
userDataMap: Map<out CallableDescriptor.UserDataKey<*>, *>,
isSuspend: Boolean
extensionReceiverParameter: ReceiverParameterDescriptor?,
dispatchReceiverParameter: ReceiverParameterDescriptor?,
typeParameters: List<TypeParameterDescriptor>,
unsubstitutedValueParameters: List<ValueParameterDescriptor>,
unsubstitutedReturnType: KotlinType?,
modality: Modality?,
visibility: DescriptorVisibility,
userDataMap: Map<out CallableDescriptor.UserDataKey<*>, *>
) {
initialize(
extensionReceiverParameter,
@@ -190,63 +166,12 @@ class MemberDeserializer(private val c: DeserializationContext) {
unsubstitutedReturnType,
modality,
visibility,
userDataMap,
computeExperimentalityModeForFunctions(
extensionReceiverParameter,
unsubstitutedValueParameters,
typeParameters,
unsubstitutedReturnType,
isSuspend
)
userDataMap
)
}
private fun DeserializedCallableMemberDescriptor.computeExperimentalityModeForFunctions(
extensionReceiverParameter: ReceiverParameterDescriptor?,
parameters: Collection<ValueParameterDescriptor>,
typeParameters: Collection<TypeParameterDescriptor>,
returnType: KotlinType?,
isSuspend: Boolean
): DeserializedMemberDescriptor.CoroutinesCompatibilityMode {
if (!versionAndReleaseCoroutinesMismatch()) return CoroutinesCompatibilityMode.COMPATIBLE
if (fqNameOrNull() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME) return CoroutinesCompatibilityMode.COMPATIBLE
val types = parameters.map { it.type } + listOfNotNull(extensionReceiverParameter?.type)
if (returnType?.containsSuspendFunctionType() == true) return CoroutinesCompatibilityMode.INCOMPATIBLE
if (typeParameters.any { typeParameter -> typeParameter.upperBounds.any { it.containsSuspendFunctionType() } }) {
return CoroutinesCompatibilityMode.INCOMPATIBLE
}
val maxFromParameters = types.map { type ->
when {
type.isSuspendFunctionType && type.arguments.size <= 3 ->
if (type.arguments.any { it.type.containsSuspendFunctionType() })
CoroutinesCompatibilityMode.INCOMPATIBLE
else
CoroutinesCompatibilityMode.NEEDS_WRAPPER
type.containsSuspendFunctionType() -> CoroutinesCompatibilityMode.INCOMPATIBLE
else -> CoroutinesCompatibilityMode.COMPATIBLE
}
}.maxOrNull() ?: CoroutinesCompatibilityMode.COMPATIBLE
return maxOf(
if (isSuspend)
CoroutinesCompatibilityMode.NEEDS_WRAPPER
else
CoroutinesCompatibilityMode.COMPATIBLE,
maxFromParameters
)
}
private fun KotlinType.containsSuspendFunctionType() = contains(UnwrappedType::isSuspendFunctionType)
private fun DeserializedMemberDescriptor.versionAndReleaseCoroutinesMismatch(): Boolean =
c.components.configuration.releaseCoroutines && versionRequirements.none {
versionRequirements.none {
it.version == VersionRequirement.Version(1, 3) && it.kind == ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION
}
@@ -285,8 +210,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
local.typeDeserializer.type(proto.returnType(c.typeTable)),
ProtoEnumFlags.modality(Flags.MODALITY.get(flags)),
ProtoEnumFlags.descriptorVisibility(Flags.VISIBILITY.get(flags)),
emptyMap<CallableDescriptor.UserDataKey<*>, Any?>(),
Flags.IS_SUSPEND.get(flags)
emptyMap<CallableDescriptor.UserDataKey<*>, Any?>()
)
function.isOperator = Flags.IS_OPERATOR.get(flags)
function.isInfix = Flags.IS_INFIX.get(flags)
@@ -321,8 +245,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
typeAlias.initialize(
local.typeDeserializer.ownTypeParameters,
local.typeDeserializer.simpleType(proto.underlyingType(c.typeTable), expandTypeAliases = false),
local.typeDeserializer.simpleType(proto.expandedType(c.typeTable), expandTypeAliases = false),
typeAlias.checkExperimentalCoroutine(local.typeDeserializer)
local.typeDeserializer.simpleType(proto.expandedType(c.typeTable), expandTypeAliases = false)
)
return typeAlias
@@ -349,19 +272,6 @@ class MemberDeserializer(private val c: DeserializationContext) {
descriptor.setHasStableParameterNames(!Flags.IS_CONSTRUCTOR_WITH_NON_STABLE_PARAMETER_NAMES.get(proto.flags))
val doesClassContainIncompatibility =
(c.containingDeclaration as? DeserializedClassDescriptor)
?.c?.typeDeserializer?.experimentalSuspendFunctionTypeEncountered == true
&& descriptor.versionAndReleaseCoroutinesMismatch()
descriptor.coroutinesExperimentalCompatibilityMode =
if (doesClassContainIncompatibility)
CoroutinesCompatibilityMode.INCOMPATIBLE
else descriptor.computeExperimentalityModeForFunctions(
null, descriptor.valueParameters, descriptor.typeParameters,
descriptor.returnType, isSuspend = false
)
return descriptor
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.builtins.StandardNames.CONTINUATION_INTERFACE_FQ_NAME
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -25,8 +26,7 @@ class TypeDeserializer(
private val parent: TypeDeserializer?,
typeParameterProtos: List<ProtoBuf.TypeParameter>,
private val debugName: String,
private val containerPresentableName: String,
var experimentalSuspendFunctionTypeEncountered: Boolean = false
private val containerPresentableName: String
) {
private val classifierDescriptors: (Int) -> ClassifierDescriptor? =
c.storageManager.createMemoizedFunctionWithNullableValues { fqNameIndex ->
@@ -195,13 +195,9 @@ class TypeDeserializer(
}
private fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType): SimpleType? {
val isReleaseCoroutines = c.components.configuration.releaseCoroutines
val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null
val continuationArgumentFqName = continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe
if (continuationArgumentType.arguments.size != 1 || !(isContinuation(continuationArgumentFqName, true) ||
isContinuation(continuationArgumentFqName, false))
) {
if (continuationArgumentType.arguments.size != 1 || continuationArgumentFqName != CONTINUATION_INTERFACE_FQ_NAME) {
return funType as SimpleType?
}
@@ -212,10 +208,6 @@ class TypeDeserializer(
return createSimpleSuspendFunctionType(funType, suspendReturnType)
}
// Load experimental suspend function type as suspend function type
experimentalSuspendFunctionTypeEncountered = experimentalSuspendFunctionTypeEncountered ||
(isReleaseCoroutines && isContinuation(continuationArgumentFqName, !isReleaseCoroutines))
return createSimpleSuspendFunctionType(funType, suspendReturnType)
}
@@ -34,14 +34,6 @@ interface DeserializedMemberDescriptor : DeserializedDescriptor, MemberDescripto
// Information about the origin of this callable's container (class or package part on JVM) or null if there's no such information.
// TODO: merge with sourceElement of containingDeclaration
override val containerSource: DeserializedContainerSource?
val coroutinesExperimentalCompatibilityMode: CoroutinesCompatibilityMode
enum class CoroutinesCompatibilityMode {
COMPATIBLE,
NEEDS_WRAPPER,
INCOMPATIBLE
}
}
interface DeserializedCallableMemberDescriptor : DeserializedMemberDescriptor, CallableMemberDescriptor
@@ -64,34 +56,6 @@ class DeserializedSimpleFunctionDescriptor(
source ?: SourceElement.NO_SOURCE
) {
override var coroutinesExperimentalCompatibilityMode = DeserializedMemberDescriptor.CoroutinesCompatibilityMode.COMPATIBLE
private set
fun initialize(
extensionReceiverParameter: ReceiverParameterDescriptor?,
dispatchReceiverParameter: ReceiverParameterDescriptor?,
typeParameters: List<TypeParameterDescriptor>,
unsubstitutedValueParameters: List<ValueParameterDescriptor>,
unsubstitutedReturnType: KotlinType?,
modality: Modality?,
visibility: DescriptorVisibility,
userDataMap: Map<out CallableDescriptor.UserDataKey<*>, *>,
isExperimentalCoroutineInReleaseEnvironment: DeserializedMemberDescriptor.CoroutinesCompatibilityMode
): SimpleFunctionDescriptorImpl {
return super.initialize(
extensionReceiverParameter,
dispatchReceiverParameter,
typeParameters,
unsubstitutedValueParameters,
unsubstitutedReturnType,
modality,
visibility,
userDataMap
).also {
this.coroutinesExperimentalCompatibilityMode = isExperimentalCoroutineInReleaseEnvironment
}
}
override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor,
original: FunctionDescriptor?,
@@ -105,7 +69,6 @@ class DeserializedSimpleFunctionDescriptor(
proto, nameResolver, typeTable, versionRequirementTable, containerSource, source
).also {
it.setHasStableParameterNames(hasStableParameterNames())
it.coroutinesExperimentalCompatibilityMode = coroutinesExperimentalCompatibilityMode
}
}
}
@@ -133,20 +96,6 @@ class DeserializedPropertyDescriptor(
containingDeclaration, original, annotations, modality, visibility, isVar, name, kind, SourceElement.NO_SOURCE,
isLateInit, isConst, isExpect, false, isExternal, isDelegated
) {
override var coroutinesExperimentalCompatibilityMode = DeserializedMemberDescriptor.CoroutinesCompatibilityMode.COMPATIBLE
private set
fun initialize(
getter: PropertyGetterDescriptorImpl?,
setter: PropertySetterDescriptor?,
backingField: FieldDescriptor?,
delegateField: FieldDescriptor?,
isExperimentalCoroutineInReleaseEnvironment: DeserializedMemberDescriptor.CoroutinesCompatibilityMode
) {
super.initialize(getter, setter, backingField, delegateField)
.also { this.coroutinesExperimentalCompatibilityMode = isExperimentalCoroutineInReleaseEnvironment }
}
override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor,
newModality: Modality,
@@ -180,9 +129,6 @@ class DeserializedClassConstructorDescriptor(
) : DeserializedCallableMemberDescriptor,
ClassConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, source ?: SourceElement.NO_SOURCE) {
override var coroutinesExperimentalCompatibilityMode = DeserializedMemberDescriptor.CoroutinesCompatibilityMode.COMPATIBLE
internal set
override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor,
original: FunctionDescriptor?,
@@ -196,7 +142,6 @@ class DeserializedClassConstructorDescriptor(
proto, nameResolver, typeTable, versionRequirementTable, containerSource, source
).also {
it.setHasStableParameterNames(hasStableParameterNames())
it.coroutinesExperimentalCompatibilityMode = coroutinesExperimentalCompatibilityMode
}
}
@@ -229,14 +174,10 @@ class DeserializedTypeAliasDescriptor(
private lateinit var typeConstructorParameters: List<TypeParameterDescriptor>
private lateinit var defaultTypeImpl: SimpleType
override var coroutinesExperimentalCompatibilityMode = DeserializedMemberDescriptor.CoroutinesCompatibilityMode.COMPATIBLE
private set
fun initialize(
declaredTypeParameters: List<TypeParameterDescriptor>,
underlyingType: SimpleType,
expandedType: SimpleType,
isExperimentalCoroutineInReleaseEnvironment: DeserializedMemberDescriptor.CoroutinesCompatibilityMode
expandedType: SimpleType
) {
initialize(declaredTypeParameters)
this.underlyingType = underlyingType
@@ -244,7 +185,6 @@ class DeserializedTypeAliasDescriptor(
typeConstructorParameters = computeConstructorTypeParameters()
defaultTypeImpl = computeDefaultType()
constructors = getTypeAliasConstructors()
this.coroutinesExperimentalCompatibilityMode = isExperimentalCoroutineInReleaseEnvironment
}
override val classDescriptor: ClassDescriptor?
@@ -261,8 +201,7 @@ class DeserializedTypeAliasDescriptor(
substituted.initialize(
declaredTypeParameters,
substitutor.safeSubstitute(underlyingType, Variance.INVARIANT).asSimpleType(),
substitutor.safeSubstitute(expandedType, Variance.INVARIANT).asSimpleType(),
coroutinesExperimentalCompatibilityMode
substitutor.safeSubstitute(expandedType, Variance.INVARIANT).asSimpleType()
)
return substituted
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.*
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
import org.jetbrains.kotlin.resolve.calls.checkers.InstantiationOfAnnotationClassesCallChecker
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.deprecation.CoroutineCompatibilitySupport
import org.jetbrains.kotlin.types.DynamicTypesAllowed
object JsPlatformConfigurator : PlatformConfiguratorBase(
@@ -51,7 +50,6 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
container.useInstance(ExtensionFunctionToExternalIsInlinable)
container.useInstance(JsQualifierChecker)
container.useInstance(JsNativeDiagnosticSuppressor)
container.useInstance(CoroutineCompatibilitySupport.DISABLED)
}
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
@@ -131,8 +131,8 @@ public class TranslationContext {
if (function.isSuspend()) {
ClassDescriptor continuationDescriptor =
DescriptorUtilKt.findContinuationClassDescriptor(
getCurrentModule(), NoLookupLocation.FROM_BACKEND,
getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
getCurrentModule(), NoLookupLocation.FROM_BACKEND
);
return new ValueParameterDescriptorImpl(function, null, function.getValueParameters().size(),
Annotations.Companion.getEMPTY(), Name.identifier("continuation"),
@@ -38,7 +38,6 @@ class FunctionIntrinsics {
AsDynamicFIF,
CoroutineContextFIF,
SuspendCoroutineUninterceptedOrReturnFIF,
InterceptedFIF,
TypeOfFIF
)
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext
object CoroutineContextFIF : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInCoroutineContext(context.languageVersionSettings)) return null
if (!descriptor.isBuiltInCoroutineContext()) return null
return Intrinsic
}
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
object InterceptedFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInIntercepted(context.languageVersionSettings)) return null
return Intrinsic
}
object Intrinsic: FunctionIntrinsic() {
override fun apply(callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
val continuation = callInfo.extensionReceiver ?: error("intercepted shall be extension function")
val facadeName = context.getNameForDescriptor(TranslationUtils.getCoroutineProperty(context, "facade"))
return JsAstUtils.pureFqn(facadeName, continuation)
}
}
}
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntri
object SuspendCoroutineUninterceptedOrReturnFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.languageVersionSettings)) return null
if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn()) return null
return Intrinsic
}
object Intrinsic: FunctionIntrinsic() {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.builtins.FunctionTypesKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.StandardNames;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.config.CoroutineLanguageVersionSettingsUtilKt;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
@@ -397,8 +396,7 @@ public final class TranslationUtils {
@NotNull
public static ClassDescriptor getCoroutineBaseClass(@NotNull TranslationContext context) {
FqName className = CoroutineLanguageVersionSettingsUtilKt.coroutinesPackageFqName(context.getLanguageVersionSettings())
.child(Name.identifier("CoroutineImpl"));
FqName className = StandardNames.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl"));
ClassDescriptor descriptor = FindClassInModuleKt.findClassAcrossModuleDependencies(
context.getCurrentModule(), ClassId.topLevel(className));
assert descriptor != null;
@@ -11,8 +11,8 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.util.SmartList
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -185,7 +185,7 @@ fun JsFunction.fillCoroutineMetadata(
descriptor: FunctionDescriptor,
hasController: Boolean
) {
val suspendPropertyDescriptor = context.currentModule.getPackage(context.languageVersionSettings.coroutinesIntrinsicsPackageFqName())
val suspendPropertyDescriptor = context.currentModule.getPackage(StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME)
.memberScope
.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first()
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.kotlinNativeInternal
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.coroutinesPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
@@ -359,11 +357,11 @@ internal class KonanSymbols(
override val suspendCoroutineUninterceptedOrReturn = internalFunction("suspendCoroutineUninterceptedOrReturn")
private val coroutinesIntrinsicsPackage = context.builtIns.builtInsModule.getPackage(
context.config.configuration.languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
private val coroutinesIntrinsicsPackage =
context.builtIns.builtInsModule.getPackage(StandardNames.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope
private val coroutinesPackage = context.builtIns.builtInsModule.getPackage(
context.config.configuration.languageVersionSettings.coroutinesPackageFqName()).memberScope
private val coroutinesPackage =
context.builtIns.builtInsModule.getPackage(StandardNames.COROUTINES_PACKAGE_FQ_NAME).memberScope
override val coroutineContextGetter = symbolTable.referenceSimpleFunction(
coroutinesPackage
@@ -36,7 +36,7 @@ internal class NativeSuspendFunctionsLowering(ctx: Context): AbstractSuspendFunc
override val stateMachineMethodName = Name.identifier("invokeSuspend")
override fun getCoroutineBaseClass(function: IrFunction): IrClassSymbol =
(if (function.isRestrictedSuspendFunction(context.irBuiltIns.languageVersionSettings)) {
(if (function.isRestrictedSuspendFunction()) {
symbols.restrictedContinuationImpl
} else {
symbols.continuationImpl
@@ -374,8 +374,8 @@ val IrType.isSimpleTypeWithQuestionMark: Boolean
fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) =
if (hasQuestionMark) this.defaultType.makeNullable() else this.defaultType
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
fun IrFunction.isRestrictedSuspendFunction(): Boolean =
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver() == true
fun IrBuilderWithScope.irByte(value: Byte) =
IrConstImpl.byte(startOffset, endOffset, context.irBuiltIns.byteType, value)
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.builtins.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE
import org.jetbrains.kotlin.builtins.StandardNames.COROUTINES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -18,7 +18,7 @@ class KonanBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageMana
override fun getSuspendFunction(parameterCount: Int) =
builtInsModule.findClassAcrossModuleDependencies(
ClassId(
COROUTINES_PACKAGE_FQ_NAME_RELEASE,
COROUTINES_PACKAGE_FQ_NAME,
Name.identifier("SuspendFunction$parameterCount")
)
)!!
@@ -28,8 +28,6 @@ import org.jetbrains.kotlin.base.kapt3.KaptFlag
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_PARAMETER_NAME
import org.jetbrains.kotlin.codegen.needsExperimentalCoroutinesWrapper
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -1022,7 +1020,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
if (sourceElement == null) return@getNonErrorType null
if (sourceElement.hasDeclaredReturnType() && isContinuationParameter(parameterDescriptor)) {
val continuationTypeFqName = getContinuationTypeFqName(descriptor)
val continuationTypeFqName = StandardNames.CONTINUATION_INTERFACE_FQ_NAME
val functionReturnType = sourceElement.typeReference!!.text
KtPsiFactory(kaptContext.project).createType("$continuationTypeFqName<$functionReturnType>")
} else {
@@ -1056,19 +1054,9 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
val containingCallable = descriptor.containingDeclaration
return containingCallable.valueParameters.lastOrNull() == descriptor
&& descriptor.name == CONTINUATION_PARAMETER_NAME
&& descriptor.source == SourceElement.NO_SOURCE
&& descriptor.type.constructor.declarationDescriptor?.fqNameSafe == getContinuationTypeFqName(containingCallable)
}
private fun getContinuationTypeFqName(descriptor: CallableDescriptor): FqName {
val areCoroutinesReleased = !descriptor.needsExperimentalCoroutinesWrapper()
&& kaptContext.generationState.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
return when (areCoroutinesReleased) {
true -> StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
false -> StandardNames.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
}
&& descriptor.name == CONTINUATION_PARAMETER_NAME
&& descriptor.source == SourceElement.NO_SOURCE
&& descriptor.type.constructor.declarationDescriptor?.fqNameSafe == StandardNames.CONTINUATION_INTERFACE_FQ_NAME
}
private fun <T : JCExpression?> getNonErrorType(