Refine coroutine/suspend functions ABI
- `invoke` method must always start a suspend functions - For creation of coroutine that has not been started yet, there are two special internal interfaces `SuspendFunction0`/`SuspendFunction1`
This commit is contained in:
@@ -304,7 +304,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
);
|
||||
}
|
||||
|
||||
private void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
|
||||
protected void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
|
||||
if (bridge.equals(delegate)) return;
|
||||
|
||||
MethodVisitor mv =
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.codegen.coroutines.createJvmSuspendFunctionView
|
||||
import org.jetbrains.kotlin.coroutines.isSuspendLambda
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal"))
|
||||
@@ -48,8 +50,16 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
(0..2).map { i -> createClass(kotlinJvmInternalPackage, "MutablePropertyReference$i") }
|
||||
}
|
||||
|
||||
private fun createClass(packageFragment: PackageFragmentDescriptor, name: String): ClassDescriptor =
|
||||
MutableClassDescriptor(packageFragment, ClassKind.CLASS, /* isInner = */ false, /* isExternal = */ false,
|
||||
private val suspendFunctions: List<ClassDescriptor> by lazy {
|
||||
(0..1).map { i -> createClass(kotlinJvmInternalPackage, "SuspendFunction$i", ClassKind.INTERFACE) }
|
||||
}
|
||||
|
||||
private fun createClass(
|
||||
packageFragment: PackageFragmentDescriptor,
|
||||
name: String,
|
||||
classKind: ClassKind = ClassKind.CLASS
|
||||
): ClassDescriptor =
|
||||
MutableClassDescriptor(packageFragment, classKind, /* isInner = */ false, /* isExternal = */ false,
|
||||
Name.identifier(name), SourceElement.NO_SOURCE).apply {
|
||||
modality = Modality.FINAL
|
||||
visibility = Visibilities.PUBLIC
|
||||
@@ -75,7 +85,15 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
||||
)
|
||||
|
||||
if (descriptor.isSuspendLambda) {
|
||||
return listOf(coroutineImplClass.defaultType, functionType)
|
||||
return mutableListOf<KotlinType>().apply {
|
||||
add(coroutineImplClass.defaultType)
|
||||
add(functionType)
|
||||
|
||||
val parametersNumber =
|
||||
descriptor.valueParameters.size + (if (functionType.isExtensionFunctionType) 1 else 0)
|
||||
|
||||
addIfNotNull(suspendFunctions.getOrNull(parametersNumber)?.defaultType)
|
||||
}
|
||||
}
|
||||
|
||||
return listOf(lambda.defaultType, functionType)
|
||||
|
||||
@@ -300,6 +300,14 @@ fun KtExpression?.asmType(typeMapper: KotlinTypeMapper, bindingContext: BindingC
|
||||
|
||||
fun KtExpression?.kotlinType(bindingContext: BindingContext) = this?.let(bindingContext::getType)
|
||||
|
||||
fun Collection<Type>.withVariableIndices(): List<Pair<Int, Type>> = mutableListOf<Pair<Int, Type>>().apply {
|
||||
var index = 0
|
||||
for (type in this@withVariableIndices) {
|
||||
add(index to type)
|
||||
index += type.size
|
||||
}
|
||||
}
|
||||
|
||||
fun FunctionDescriptor.isGenericToArray(): Boolean {
|
||||
if (valueParameters.size != 1 || typeParameters.size != 1) return false
|
||||
|
||||
@@ -330,4 +338,4 @@ fun MemberDescriptor.isToArrayFromCollection(): Boolean {
|
||||
if (!isSubclass(containingClassDescriptor, collectionClass)) return false
|
||||
|
||||
return isGenericToArray() || isNonGenericToArray()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CONTINUATION_RESUME_METHOD_NAME
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
@@ -36,6 +37,8 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
@@ -91,6 +94,19 @@ class CoroutineCodegen(
|
||||
)
|
||||
}
|
||||
|
||||
private val createCoroutineDescriptor =
|
||||
funDescriptor.createCustomCopy {
|
||||
setName(Name.identifier("create"))
|
||||
setReturnType(
|
||||
KotlinTypeFactory.simpleNotNullType(
|
||||
Annotations.EMPTY,
|
||||
funDescriptor.builtIns.continuationClassDescriptor,
|
||||
listOf(funDescriptor.builtIns.unitType.asTypeProjection())
|
||||
)
|
||||
)
|
||||
setVisibility(Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
override fun generateClosureBody() {
|
||||
for (parameter in allLambdaParameters()) {
|
||||
val fieldInfo = parameter.getFieldInfoForCoroutineLambdaParameter()
|
||||
@@ -108,14 +124,65 @@ class CoroutineCodegen(
|
||||
override fun generateBody() {
|
||||
super.generateBody()
|
||||
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, createCoroutineDescriptor,
|
||||
object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
generateCreateCoroutineMethod(codegen)
|
||||
}
|
||||
})
|
||||
|
||||
// invoke(..) = create(..).resume(Unit)
|
||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, funDescriptor,
|
||||
object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
generateInvokeMethod(codegen)
|
||||
codegen.v.generateInvokeMethod(signature)
|
||||
}
|
||||
})
|
||||
|
||||
if (allLambdaParameters().size <= 1) {
|
||||
val delegate = typeMapper.mapSignatureSkipGeneric(createCoroutineDescriptor).asmMethod
|
||||
|
||||
val bridgeParameters = (1..delegate.argumentTypes.size - 1).map { AsmTypes.OBJECT_TYPE } + delegate.argumentTypes.last()
|
||||
val bridge = Method(delegate.name, delegate.returnType, bridgeParameters.toTypedArray())
|
||||
|
||||
generateBridge(bridge, delegate)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.generateInvokeMethod(signature: JvmMethodSignature) {
|
||||
// this
|
||||
load(0, AsmTypes.OBJECT_TYPE)
|
||||
val parameterTypes = signature.valueParameters.map { it.asmType }
|
||||
parameterTypes.withVariableIndices().forEach {
|
||||
(index, type) -> load(index + 1, type)
|
||||
}
|
||||
|
||||
// this.create(..)
|
||||
invokevirtual(
|
||||
v.thisName,
|
||||
createCoroutineDescriptor.name.identifier,
|
||||
Type.getMethodDescriptor(
|
||||
AsmTypes.CONTINUATION,
|
||||
*parameterTypes.toTypedArray()
|
||||
),
|
||||
false
|
||||
)
|
||||
checkcast(Type.getObjectType(v.thisName))
|
||||
|
||||
// .resume(Unit)
|
||||
StackValue.putUnitInstance(this)
|
||||
invokevirtual(
|
||||
AsmTypes.RESTRICTED_COROUTINE_IMPL.internalName,
|
||||
CONTINUATION_RESUME_METHOD_NAME.identifier,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, AsmTypes.OBJECT_TYPE),
|
||||
false
|
||||
)
|
||||
|
||||
loadSuspendMarker()
|
||||
areturn(AsmTypes.OBJECT_TYPE)
|
||||
}
|
||||
|
||||
|
||||
override fun generateConstructor(): Method {
|
||||
val args = calculateConstructorParameters(typeMapper, closure, asmType)
|
||||
val argTypes = args.map { it.fieldType }.plus(AsmTypes.CONTINUATION).toTypedArray()
|
||||
@@ -149,7 +216,7 @@ class CoroutineCodegen(
|
||||
return constructor
|
||||
}
|
||||
|
||||
private fun generateInvokeMethod(codegen: ExpressionCodegen) {
|
||||
private fun generateCreateCoroutineMethod(codegen: ExpressionCodegen) {
|
||||
val classDescriptor = closureContext.contextDescriptor
|
||||
val owner = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ typealias FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder =
|
||||
FunctionDescriptor.CopyBuilder<out FunctionDescriptor>.(FunctionDescriptor)
|
||||
-> FunctionDescriptor.CopyBuilder<out FunctionDescriptor>
|
||||
|
||||
private fun <D : FunctionDescriptor> D.createCustomCopy(
|
||||
fun <D : FunctionDescriptor> D.createCustomCopy(
|
||||
copySettings: FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder
|
||||
): D {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user