From 17608ecb981650df5559aff5d903c3963269ef14 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 22 Jun 2018 18:46:20 +0300 Subject: [PATCH] Implemented intrinsic + tests --- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 20 +++++++++--- .../backend/konan/lower/FunctionInlining.kt | 32 ++++++++++++------- backend.native/tests/build.gradle | 10 ++++++ .../codegen/coroutines/coroutineContext1.kt | 20 ++++++++++++ .../codegen/coroutines/coroutineContext2.kt | 22 +++++++++++++ .../main/kotlin/konan/internal/Coroutines.kt | 5 +++ 6 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 backend.native/tests/codegen/coroutines/coroutineContext1.kt create mode 100644 backend.native/tests/codegen/coroutines/coroutineContext2.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index f3fb2c28197..2c3c618e059 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -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!! ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index f5462b88579..6af981498bf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -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? + } + } + } //-------------------------------------------------------------------------// diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 0829f730b7c..5faa49e3afc 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -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" diff --git a/backend.native/tests/codegen/coroutines/coroutineContext1.kt b/backend.native/tests/codegen/coroutines/coroutineContext1.kt new file mode 100644 index 00000000000..774499926a8 --- /dev/null +++ b/backend.native/tests/codegen/coroutines/coroutineContext1.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 { + 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) } +} \ No newline at end of file diff --git a/backend.native/tests/codegen/coroutines/coroutineContext2.kt b/backend.native/tests/codegen/coroutines/coroutineContext2.kt new file mode 100644 index 00000000000..178241502f2 --- /dev/null +++ b/backend.native/tests/codegen/coroutines/coroutineContext2.kt @@ -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 { + 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()) } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/konan/internal/Coroutines.kt b/runtime/src/main/kotlin/konan/internal/Coroutines.kt index 4c66378844c..2d8e421df29 100644 --- a/runtime/src/main/kotlin/konan/internal/Coroutines.kt +++ b/runtime/src/main/kotlin/konan/internal/Coroutines.kt @@ -33,6 +33,11 @@ internal inline fun Continuation.intercepted(): Continuation = @PublishedApi internal external fun getContinuation(): Continuation +@kotlin.internal.InlineOnly +@PublishedApi +internal inline suspend fun getCoroutineContext(): CoroutineContext = + getContinuation().context + @Intrinsic @PublishedApi internal external suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T