From f312315346f129e65f63b1d036b88fadc77ed56e Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Tue, 2 Feb 2021 18:48:54 +0300 Subject: [PATCH] Call initRuntimeIfNeeded before EnterFrame in interop adapters. (#4672) --- .../jetbrains/kotlin/backend/konan/CAdapterGenerator.kt | 6 +++--- .../jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt | 7 +++++++ .../konan/llvm/objcexport/ObjCExportCodeGenerator.kt | 2 +- kotlin-native/runtime/src/main/cpp/Runtime.cpp | 2 +- kotlin-native/runtime/src/main/cpp/Runtime.h | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index 5e74fb8b6c3..620f75582f6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -361,8 +361,8 @@ private class ExportedElement(val kind: ElementKind, | |extern "C" KObjHeader* ${cname}_instance(KObjHeader**); |static $objectClassC ${cname}_instance_impl(void) { - | KObjHolder result_holder; | Kotlin_initRuntimeIfNeeded(); + | KObjHolder result_holder; | KObjHeader* result = ${cname}_instance(result_holder.slot()); | return $objectClassC { .pinned = CreateStablePointer(result)}; |} @@ -379,8 +379,8 @@ private class ExportedElement(val kind: ElementKind, return """ |extern "C" KObjHeader* $cname(KObjHeader**); |static $enumClassC ${cname}_impl(void) { - | KObjHolder result_holder; | Kotlin_initRuntimeIfNeeded(); + | KObjHolder result_holder; | KObjHeader* result = $cname(result_holder.slot()); | return $enumClassC { .pinned = CreateStablePointer(result)}; |} @@ -996,8 +996,8 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi val argument = if (needArgument) "value, " else "" output("extern \"C\" KObjHeader* Kotlin_box${it.shortNameForPredefinedType}($parameter$maybeComma KObjHeader**);") output("static ${translateType(nullableIt)} ${it.createNullableNameForPredefinedType}Impl($parameter) {") - output("KObjHolder result_holder;", 1) output("Kotlin_initRuntimeIfNeeded();", 1) + output("KObjHolder result_holder;", 1) output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1) output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1) output("}") diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 40ff28394a7..3f610a1ea0f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -341,6 +341,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, */ var forwardingForeignExceptionsTerminatedWith: LLVMValueRef? = null + // Whether the generating function needs to initialize Kotlin runtime before execution. Useful for interop bridges, + // for example. + var needsRuntimeInit = false + init { irFunction?.let { if (!irFunction.isExported()) { @@ -1207,6 +1211,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, internal fun epilogue() { appendingTo(prologueBb) { + if (needsRuntimeInit) { + call(context.llvm.initRuntimeIfNeeded, emptyList()) + } val slots = if (needSlotsPhi) LLVMBuildArrayAlloca(builder, kObjHeaderPtr, Int32(slotCount).llvm, "")!! else diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 77a6b2c0cec..a91dbeae6c5 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -208,7 +208,7 @@ internal class ObjCExportCodeGenerator( } fun FunctionGenerationContext.initRuntimeIfNeeded() { - callFromBridge(context.llvm.initRuntimeIfNeeded, emptyList()) + this.needsRuntimeInit = true } inline fun FunctionGenerationContext.convertKotlin( diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp index debbf00455f..2e44c794952 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.cpp +++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp @@ -189,7 +189,7 @@ void AppendToInitializersTail(InitNode *next) { initTailNode = next; } -void Kotlin_initRuntimeIfNeeded() { +RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeeded() { if (!isValidRuntime()) { initRuntime(); // Register runtime deinit function at thread cleanup. diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.h b/kotlin-native/runtime/src/main/cpp/Runtime.h index d5779db9b10..1f420e714d2 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.h +++ b/kotlin-native/runtime/src/main/cpp/Runtime.h @@ -33,7 +33,7 @@ enum DestroyRuntimeMode { DestroyRuntimeMode Kotlin_getDestroyRuntimeMode(); -void Kotlin_initRuntimeIfNeeded(); +RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeeded(); void Kotlin_deinitRuntimeIfNeeded(); // Can only be called once.