From 35cb897bdd586b82f30f79e91f2bbdbf0546ac57 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 13 Jan 2022 15:43:50 +0300 Subject: [PATCH] ObjCExport: use terminatingExceptionHandler by default If something called from an ObjCExport bridge throws a Kotlin exception, treat it as fatal by default and terminate the process. This affects * Runtime calls (managing and converting Kotlin and Obj-C references and other types), that shouldn't throw such exceptions anyway * User code (Kotlin function object throws Kotlin exception when called from Swift/Obj-C). If an exception should be handled non-fatally (e.g. forwarded to the caller), this intention should be expressed in the code generator explicitly. ^KT-50830 This change makes the code more simple and efficient, and the control flow -- more explicit. --- .../kotlin/backend/konan/llvm/ContextUtils.kt | 2 +- .../llvm/objcexport/ObjCExportCodeGenerator.kt | 18 ++++++++---------- .../runtime/src/main/cpp/ObjCExportErrors.mm | 6 ------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index e2e8447986e..0540073a07a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -500,7 +500,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti val Kotlin_ObjCExport_AbstractClassConstructorCalled by lazyRtFunction val Kotlin_ObjCExport_RethrowExceptionAsNSError by lazyRtFunction val Kotlin_ObjCExport_WrapExceptionToNSError by lazyRtFunction - val Kotlin_ObjCExport_RethrowNSErrorAsException by lazyRtFunction + val Kotlin_ObjCExport_NSErrorAsException by lazyRtFunction val Kotlin_ObjCExport_AllocInstanceWithAssociatedObject by lazyRtFunction val Kotlin_ObjCExport_createContinuationArgument by lazyRtFunction val Kotlin_ObjCExport_createUnitContinuationArgument by lazyRtFunction 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 31c9c2179fc..d8b9c301006 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 @@ -169,19 +169,13 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo return callFromBridge(llvmDeclarations, args, resultLifetime) } - // TODO: currently bridges don't have any custom `landingpad`s, - // so it is correct to use [callAtFunctionScope] here. - // However, exception handling probably should be refactored - // (e.g. moved from `IrToBitcode.kt` to [FunctionGenerationContext]). fun ObjCExportFunctionGenerationContext.callFromBridge( function: LlvmCallable, args: List, resultLifetime: Lifetime = Lifetime.IRRELEVANT, ): LLVMValueRef { - - // TODO: it is required only for Kotlin-to-Objective-C bridges. - this.forwardingForeignExceptionsTerminatedWith = objcTerminate - val exceptionHandler = ExceptionHandler.Caller + // All calls that actually do need to forward exceptions to callers should express this explicitly. + val exceptionHandler = terminatingExceptionHandler return call(function, args, resultLifetime, exceptionHandler) } @@ -1251,8 +1245,12 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( fun rethrow() { val error = load(errorOutPtr!!) - callFromBridge(context.llvm.Kotlin_ObjCExport_RethrowNSErrorAsException, listOf(error)) - unreachable() + val exception = callFromBridge( + context.llvm.Kotlin_ObjCExport_NSErrorAsException, + listOf(error), + resultLifetime = Lifetime.THROW + ) + ExceptionHandler.Caller.genThrow(this, exception) } fun genKotlinBaseMethodResult( diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm index ba97fc9320d..d5365cdca8b 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportErrors.mm @@ -138,12 +138,6 @@ extern "C" OBJ_GETTER(Kotlin_ObjCExport_NSErrorAsException, id error) { RETURN_RESULT_OF(Kotlin_ObjCExport_NSErrorAsExceptionImpl, message, kotlinError); } -extern "C" void Kotlin_ObjCExport_RethrowNSErrorAsException(id error) { - ObjHolder holder; - KRef exception = Kotlin_ObjCExport_NSErrorAsException(error, holder.slot()); - ThrowException(exception); -} - @interface NSError (NSErrorKotlinException) @end;