JVM_IR: Support is/as SuspendFunction operators
This commit is contained in:
@@ -40,6 +40,7 @@ class JvmSymbols(
|
|||||||
private val storageManager = LockBasedStorageManager(this::class.java.simpleName)
|
private val storageManager = LockBasedStorageManager(this::class.java.simpleName)
|
||||||
private val kotlinPackage: IrPackageFragment = createPackage(FqName("kotlin"))
|
private val kotlinPackage: IrPackageFragment = createPackage(FqName("kotlin"))
|
||||||
private val kotlinCoroutinesPackage: IrPackageFragment = createPackage(FqName("kotlin.coroutines"))
|
private val kotlinCoroutinesPackage: IrPackageFragment = createPackage(FqName("kotlin.coroutines"))
|
||||||
|
private val kotlinCoroutinesJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.coroutines.jvm.internal"))
|
||||||
private val kotlinJvmPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm"))
|
private val kotlinJvmPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm"))
|
||||||
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
|
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
|
||||||
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
||||||
@@ -81,6 +82,7 @@ class JvmSymbols(
|
|||||||
parent = when (fqName.parent().asString()) {
|
parent = when (fqName.parent().asString()) {
|
||||||
"kotlin" -> kotlinPackage
|
"kotlin" -> kotlinPackage
|
||||||
"kotlin.coroutines" -> kotlinCoroutinesPackage
|
"kotlin.coroutines" -> kotlinCoroutinesPackage
|
||||||
|
"kotlin.coroutines.jvm.internal" -> kotlinCoroutinesJvmInternalPackage
|
||||||
"kotlin.jvm.internal" -> kotlinJvmInternalPackage
|
"kotlin.jvm.internal" -> kotlinJvmInternalPackage
|
||||||
"kotlin.jvm.functions" -> kotlinJvmFunctionsPackage
|
"kotlin.jvm.functions" -> kotlinJvmFunctionsPackage
|
||||||
"java.lang" -> javaLangPackage
|
"java.lang" -> javaLangPackage
|
||||||
@@ -169,6 +171,8 @@ class JvmSymbols(
|
|||||||
klass.addTypeParameter("T", irBuiltIns.anyNType, Variance.IN_VARIANCE)
|
klass.addTypeParameter("T", irBuiltIns.anyNType, Variance.IN_VARIANCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val suspendFunctionInterface: IrClassSymbol = createClass(FqName("kotlin.coroutines.jvm.internal.SuspendFunction"), ClassKind.INTERFACE)
|
||||||
|
|
||||||
val lambdaClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.Lambda")) { klass ->
|
val lambdaClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.Lambda")) { klass ->
|
||||||
klass.addConstructor().apply {
|
klass.addConstructor().apply {
|
||||||
addValueParameter("arity", irBuiltIns.intType)
|
addValueParameter("arity", irBuiltIns.intType)
|
||||||
|
|||||||
+3
-5
@@ -103,14 +103,12 @@ internal fun IrFunction.isInvokeOfSuspendLambda(context: JvmBackendContext): Boo
|
|||||||
internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext): Boolean =
|
internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext): Boolean =
|
||||||
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass in context.suspendFunctionContinuations.values
|
name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass in context.suspendFunctionContinuations.values
|
||||||
|
|
||||||
internal fun IrFunction.isInvokeOfCallableReference(): Boolean = isSuspend && name.asString() == "invoke" && (parent as? IrClass)?.let {
|
internal fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspend && name.asString() == "invoke" &&
|
||||||
// TODO: Should we use different origin for lowered callable references?
|
(parent as? IrClass)?.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||||
it.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL && it.functions.any { it.name.asString() == "getSignature" }
|
|
||||||
} == true
|
|
||||||
|
|
||||||
internal fun IrFunction.isKnownToBeTailCall(): Boolean =
|
internal fun IrFunction.isKnownToBeTailCall(): Boolean =
|
||||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
||||||
isInvokeOfCallableReference()
|
isInvokeOfSuspendCallableReference()
|
||||||
|
|
||||||
internal fun IrFunction.shouldNotContainSuspendMarkers(context: JvmBackendContext): Boolean =
|
internal fun IrFunction.shouldNotContainSuspendMarkers(context: JvmBackendContext): Boolean =
|
||||||
isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall()
|
isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall()
|
||||||
|
|||||||
+7
-5
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* that can be found in the license/LICENSE.txt file.
|
* 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.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
@@ -35,6 +35,8 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
|
|
||||||
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase() {
|
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase() {
|
||||||
internal val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
internal val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
||||||
|
private val IrTypeArgument.adjustedType
|
||||||
|
get() = (this as? IrTypeProjection)?.type ?: context.irBuiltIns.anyNType
|
||||||
|
|
||||||
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
||||||
when (classifier) {
|
when (classifier) {
|
||||||
@@ -99,8 +101,8 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
|||||||
|
|
||||||
if (type.isSuspendFunction()) {
|
if (type.isSuspendFunction()) {
|
||||||
val arguments =
|
val arguments =
|
||||||
type.arguments.dropLast(1).map { (it as IrTypeProjection).type } +
|
type.arguments.dropLast(1).map { it.adjustedType } +
|
||||||
context.ir.symbols.continuationClass.typeWith((type.arguments.last() as IrTypeProjection).type) +
|
context.ir.symbols.continuationClass.typeWith(type.arguments.last().adjustedType) +
|
||||||
context.irBuiltIns.anyNType
|
context.irBuiltIns.anyNType
|
||||||
val runtimeFunctionType = context.referenceClass(context.builtIns.getFunction(arguments.size - 1)).typeWith(arguments)
|
val runtimeFunctionType = context.referenceClass(context.builtIns.getFunction(arguments.size - 1)).typeWith(arguments)
|
||||||
return mapType(runtimeFunctionType, mode, sw)
|
return mapType(runtimeFunctionType, mode, sw)
|
||||||
@@ -251,4 +253,4 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
|||||||
|
|
||||||
private fun boxTypeIfNeeded(possiblyPrimitiveType: Type, needBoxedType: Boolean): Type =
|
private fun boxTypeIfNeeded(possiblyPrimitiveType: Type, needBoxedType: Boolean): Type =
|
||||||
if (needBoxedType) AsmUtil.boxType(possiblyPrimitiveType) else possiblyPrimitiveType
|
if (needBoxedType) AsmUtil.boxType(possiblyPrimitiveType) else possiblyPrimitiveType
|
||||||
}
|
}
|
||||||
+2
-2
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.backend.common.pop
|
|||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrBlock
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrBlock
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInvokeOfCallableReference
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInvokeOfSuspendCallableReference
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||||
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -433,7 +433,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(declaration)
|
||||||
if (declaration.isSuspend && declaration !in suspendLambdas && !declaration.isInline &&
|
if (declaration.isSuspend && declaration !in suspendLambdas && !declaration.isInline &&
|
||||||
!declaration.isInvokeOfCallableReference()
|
!declaration.isInvokeOfSuspendCallableReference()
|
||||||
) {
|
) {
|
||||||
result.add(declaration)
|
result.add(declaration)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -188,6 +188,7 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
|
|||||||
superTypes += superType
|
superTypes += superType
|
||||||
if (samSuperType == null)
|
if (samSuperType == null)
|
||||||
superTypes += functionSuperClass.typeWith(parameterTypes)
|
superTypes += functionSuperClass.typeWith(parameterTypes)
|
||||||
|
if (irFunctionReference.isSuspend) superTypes += context.ir.symbols.suspendFunctionInterface.typeWith()
|
||||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||||
copyAttributes(irFunctionReference)
|
copyAttributes(irFunctionReference)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -17,26 +17,26 @@ fun test(f: Function<*>, arity: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun foo(s: String, i: Int) {}
|
suspend fun foo(s: String, i: Int) {}
|
||||||
//class A {
|
class A {
|
||||||
// suspend fun bar(s: String, i: Int) {}
|
suspend fun bar(s: String, i: Int) {}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//suspend fun Double.baz(s: String, i: Int) {}
|
suspend fun Double.baz(s: String, i: Int) {}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
test(::foo, 2 + 1)
|
test(::foo, 2 + 1)
|
||||||
// test(A::bar, 3 + 1)
|
test(A::bar, 3 + 1)
|
||||||
// test(Double::baz, 3 + 1)
|
test(Double::baz, 3 + 1)
|
||||||
//
|
|
||||||
// test(::box, 0)
|
test(::box, 0)
|
||||||
//
|
|
||||||
// suspend fun local(x: Int) {}
|
suspend fun local(x: Int) {}
|
||||||
// test(::local, 1 + 1)
|
test(::local, 1 + 1)
|
||||||
//
|
|
||||||
// // TODO: Uncomment when `suspend fun` will be supported
|
// TODO: Uncomment when `suspend fun` will be supported
|
||||||
// // test(suspend fun(s: String) = s, 1)
|
// test(suspend fun(s: String) = s, 1)
|
||||||
// // test(suspend fun(){}, 0)
|
// test(suspend fun(){}, 0)
|
||||||
// test(suspend {}, 1)
|
test(suspend {}, 1)
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
// IGNORE_BACKEND: JS_IR, JS
|
// IGNORE_BACKEND: JS_IR, JS
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user