diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index 2872b9d8d75..c0a8f01b850 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -51,7 +51,11 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter( ) val invoke = loadBlockInvoke(blockPtr, bridge) - val result = callFromBridge(invoke, listOf(blockPtr) + args, toNative = true) + switchThreadStateIfExperimentalMM(ThreadState.Native) + // Using terminatingExceptionHandler, so any exception thrown by `invoke` will lead to the termination, + // and switching the thread state back to `Runnable` on exceptional path is not required. + val result = call(invoke, listOf(blockPtr) + args, exceptionHandler = terminatingExceptionHandler) + switchThreadStateIfExperimentalMM(ThreadState.Runnable) val kotlinResult = if (bridge.returnsVoid) { theUnitInstanceRef.llvm 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 9a22c428c66..c149c86fd08 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 @@ -1259,7 +1259,11 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( } } - val targetResult = callFromBridge(objcMsgSend, objCArgs, toNative = true) + switchThreadStateIfExperimentalMM(ThreadState.Native) + // Using terminatingExceptionHandler, so any exception thrown by the method will lead to the termination, + // and switching the thread state back to `Runnable` on exceptional path is not required. + val targetResult = call(objcMsgSend, objCArgs, exceptionHandler = terminatingExceptionHandler) + switchThreadStateIfExperimentalMM(ThreadState.Runnable) assert(baseMethod.symbol !is IrConstructorSymbol) diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index c0d5af93f2c..2826ec0ebae 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -2675,8 +2675,7 @@ __attribute__((swift_name("ValuesKt"))) + (id)createTransformDecimalStringToInt __attribute__((swift_name("createTransformDecimalStringToInt()"))); + (BOOL)runUnitBlockBlock:(void (^)(void))block __attribute__((swift_name("runUnitBlock(block:)"))); + (void (^)(void))asUnitBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asUnitBlock(block:)"))); -+ (BOOL)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); -+ (void (^)(void))asNothingBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asNothingBlock(block:)"))); ++ (void)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); + (void (^ _Nullable)(void))getNullBlock __attribute__((swift_name("getNullBlock()"))); + (BOOL)isBlockNullBlock:(void (^ _Nullable)(void))block __attribute__((swift_name("isBlockNull(block:)"))); + (BOOL)isFunctionObj:(id _Nullable)obj __attribute__((swift_name("isFunction(obj:)"))); diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h index dc754402b25..380ad6b770f 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h @@ -2617,8 +2617,7 @@ __attribute__((swift_name("ValuesKt"))) + (id)createTransformDecimalStringToInt __attribute__((swift_name("createTransformDecimalStringToInt()"))); + (BOOL)runUnitBlockBlock:(void (^)(void))block __attribute__((swift_name("runUnitBlock(block:)"))); + (void (^)(void))asUnitBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asUnitBlock(block:)"))); -+ (BOOL)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); -+ (void (^)(void))asNothingBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asNothingBlock(block:)"))); ++ (void)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); + (void (^ _Nullable)(void))getNullBlock __attribute__((swift_name("getNullBlock()"))); + (BOOL)isBlockNullBlock:(void (^ _Nullable)(void))block __attribute__((swift_name("isBlockNull(block:)"))); + (BOOL)isFunctionObj:(id _Nullable)obj __attribute__((swift_name("isFunction(obj:)"))); diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index fd8308ef6d5..b67af84fb78 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -2617,8 +2617,7 @@ __attribute__((swift_name("ValuesKt"))) + (id)createTransformDecimalStringToInt __attribute__((swift_name("createTransformDecimalStringToInt()"))); + (BOOL)runUnitBlockBlock:(void (^)(void))block __attribute__((swift_name("runUnitBlock(block:)"))); + (void (^)(void))asUnitBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asUnitBlock(block:)"))); -+ (BOOL)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); -+ (void (^)(void))asNothingBlockBlock:(id _Nullable (^)(void))block __attribute__((swift_name("asNothingBlock(block:)"))); ++ (void)runNothingBlockBlock:(void (^)(void))block __attribute__((swift_name("runNothingBlock(block:)"))); + (void (^ _Nullable)(void))getNullBlock __attribute__((swift_name("getNullBlock()"))); + (BOOL)isBlockNullBlock:(void (^ _Nullable)(void))block __attribute__((swift_name("isBlockNull(block:)"))); + (BOOL)isFunctionObj:(id _Nullable)obj __attribute__((swift_name("isFunction(obj:)"))); diff --git a/kotlin-native/backend.native/tests/objcexport/values.kt b/kotlin-native/backend.native/tests/objcexport/values.kt index 70bfc30e9a4..922fce309fe 100644 --- a/kotlin-native/backend.native/tests/objcexport/values.kt +++ b/kotlin-native/backend.native/tests/objcexport/values.kt @@ -504,17 +504,7 @@ fun runUnitBlock(block: () -> Unit): Boolean { fun asUnitBlock(block: () -> Any?): () -> Unit = { block() } -fun runNothingBlock(block: () -> Nothing) = try { - block() - false -} catch (e: Throwable) { - true -} - -fun asNothingBlock(block: () -> Any?): () -> Nothing = { - block() - TODO() -} +fun runNothingBlock(block: () -> Nothing) { (block as () -> Any?)() } fun getNullBlock(): (() -> Unit)? = null fun isBlockNull(block: (() -> Unit)?): Boolean = block == null diff --git a/kotlin-native/backend.native/tests/objcexport/values.swift b/kotlin-native/backend.native/tests/objcexport/values.swift index 660def5d890..e03fa5834bc 100644 --- a/kotlin-native/backend.native/tests/objcexport/values.swift +++ b/kotlin-native/backend.native/tests/objcexport/values.swift @@ -435,8 +435,8 @@ func testLambda() throws { try assertTrue(unitBlock() == Void()) try assertEquals(actual: blockRuns, expected: 2) - let nothingBlock: () -> Void = ValuesKt.asNothingBlock { blockRuns += 1 } - try assertTrue(ValuesKt.runNothingBlock(block: nothingBlock)) + let nothingBlock: () -> Void = { blockRuns += 1 } + ValuesKt.runNothingBlock(block: nothingBlock) try assertEquals(actual: blockRuns, expected: 3) try assertTrue(ValuesKt.getNullBlock() == nil)