Implemented intrinsic <coroutineContext> + tests

This commit is contained in:
Igor Chevdar
2018-06-22 18:46:20 +03:00
parent 8edc17d3e6
commit 17608ecb98
6 changed files with 93 additions and 16 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.coroutinesPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -326,21 +327,32 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
val konanSuspendCoroutineUninterceptedOrReturn = symbolTable.referenceSimpleFunction(
context.getInternalFunctions("suspendCoroutineUninterceptedOrReturn").single())
private val coroutinesPackage = context.builtIns.builtInsModule.getPackage(
val konanCoroutineContextGetter = symbolTable.referenceSimpleFunction(
context.getInternalFunctions("getCoroutineContext").single())
private val coroutinesIntrinsicsPackage = context.builtIns.builtInsModule.getPackage(
context.config.configuration.languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
val intercepted = coroutinesPackage
private val coroutinesPackage = context.builtIns.builtInsModule.getPackage(
context.config.configuration.languageVersionSettings.coroutinesPackageFqName()).memberScope
val intercepted = coroutinesIntrinsicsPackage
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
.single()
val suspendCoroutineUninterceptedOrReturn = coroutinesPackage
val suspendCoroutineUninterceptedOrReturn = coroutinesIntrinsicsPackage
.getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
.single()
val coroutineContextGetter = coroutinesPackage
.getContributedVariables(Name.identifier("coroutineContext"), NoLookupLocation.FROM_BACKEND)
.single()
.getter!!
override val coroutineImpl = symbolTable.referenceClass(context.getInternalClass("CoroutineImpl"))
override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction(
coroutinesPackage
coroutinesIntrinsicsPackage
.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND)
.single().getter!!
)
@@ -94,18 +94,26 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------//
private fun getFunctionDeclaration(descriptor: FunctionDescriptor): IrFunction? {
val originalDescriptor = descriptor.resolveFakeOverride().original
if (originalDescriptor == context.ir.symbols.intercepted)
return getFunctionDeclaration(context.ir.symbols.konanIntercepted.descriptor)
if (originalDescriptor == context.ir.symbols.suspendCoroutineUninterceptedOrReturn) {
return getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
}
val functionDeclaration =
context.ir.originalModuleIndex.functions[originalDescriptor] ?: // If function is declared in the current module.
deserializer.deserializeInlineBody(originalDescriptor) // Function is declared in another module.
return functionDeclaration as IrFunction?
}
private fun getFunctionDeclaration(descriptor: FunctionDescriptor): IrFunction? =
descriptor.resolveFakeOverride().original.let {
when (it) {
context.ir.symbols.intercepted ->
getFunctionDeclaration(context.ir.symbols.konanIntercepted.descriptor)
context.ir.symbols.suspendCoroutineUninterceptedOrReturn ->
getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
context.ir.symbols.coroutineContextGetter ->
getFunctionDeclaration(context.ir.symbols.konanCoroutineContextGetter.descriptor)
else -> {
val functionDeclaration =
context.ir.originalModuleIndex.functions[it] ?: // If function is declared in the current module.
deserializer.deserializeInlineBody(it) // Function is declared in another module.
functionDeclaration as IrFunction?
}
}
}
//-------------------------------------------------------------------------//
+10
View File
@@ -1309,6 +1309,16 @@ task coroutines_returnsUnit1(type: RunKonanTest) {
source = "codegen/coroutines/returnsUnit1.kt"
}
task coroutines_coroutineContext1(type: RunKonanTest) {
goldValue = "EmptyCoroutineContext\n"
source = "codegen/coroutines/coroutineContext1.kt"
}
task coroutines_coroutineContext2(type: RunKonanTest) {
goldValue = "EmptyCoroutineContext\n"
source = "codegen/coroutines/coroutineContext2.kt"
}
task AbstractMutableCollection(type: RunKonanTest) {
expectedExitStatus = 0
source = "runtime/collections/AbstractMutableCollection.kt"
@@ -0,0 +1,20 @@
package codegen.coroutines.coroutineContext1
import kotlin.test.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
companion object : EmptyContinuation()
override fun resume(value: Any?) {}
override fun resumeWithException(exception: Throwable) { throw exception }
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@Test fun runTest() {
builder { println(coroutineContext) }
}
@@ -0,0 +1,22 @@
package codegen.coroutines.coroutineContext2
import kotlin.test.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
companion object : EmptyContinuation()
override fun resume(value: Any?) {}
override fun resumeWithException(exception: Throwable) { throw exception }
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
suspend fun foo() = coroutineContext
@Test fun runTest() {
builder { println(foo()) }
}
@@ -33,6 +33,11 @@ internal inline fun <T> Continuation<T>.intercepted(): Continuation<T> =
@PublishedApi
internal external fun <T> getContinuation(): Continuation<T>
@kotlin.internal.InlineOnly
@PublishedApi
internal inline suspend fun getCoroutineContext(): CoroutineContext =
getContinuation<Any?>().context
@Intrinsic
@PublishedApi
internal external suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T