From 3f2584bb02c2380d544846901553425ada65ce69 Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Wed, 3 Jan 2024 14:02:36 +0100 Subject: [PATCH] [K/N] Move calls checker into separate module ^KT-62091 --- .../arguments/K2NativeCompilerArguments.kt | 2 +- .../kotlin/backend/konan/BinaryOptions.kt | 2 + .../kotlin/backend/konan/KonanConfig.kt | 6 + .../backend/konan/KonanConfigurationKeys.kt | 2 - .../backend/konan/SetupConfiguration.kt | 9 +- .../konan/driver/phases/TopLevelPhases.kt | 2 +- kotlin-native/runtime/build.gradle.kts | 103 ++++++++++-------- .../common}/cpp/CallsChecker.hpp | 4 +- .../impl}/cpp/CallsChecker.cpp | 28 +++-- .../noop/cpp/CallsChecker.cpp | 11 ++ kotlin-native/runtime/src/main/cpp/Common.h | 2 - kotlin-native/runtime/src/main/cpp/Mutex.hpp | 1 + .../src/main/cpp/ObjCExportCollectionUtils.mm | 1 + .../runtime/src/main/cpp/Porting.cpp | 1 + .../support/settings/TestProcessSettings.kt | 2 +- 15 files changed, 112 insertions(+), 64 deletions(-) rename kotlin-native/runtime/src/{main => externalCallsChecker/common}/cpp/CallsChecker.hpp (82%) rename kotlin-native/runtime/src/{mm => externalCallsChecker/impl}/cpp/CallsChecker.cpp (94%) create mode 100644 kotlin-native/runtime/src/externalCallsChecker/noop/cpp/CallsChecker.cpp diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt index 91e75b41b2b..bb85474dc58 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt @@ -283,7 +283,7 @@ The default value is 1.""" var printBitCode: Boolean = false @Argument(value = "-Xcheck-state-at-external-calls", description = "Ensure that all calls of possibly long external functions are done in the native thread state.") - var checkExternalCalls: Boolean = false + var checkExternalCalls: Boolean? = null @Argument(value = "-Xprint-ir", deprecatedName = "--print_ir", description = "Print IR.") var printIr: Boolean = false diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt index 11c30e60912..156fd7a502b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BinaryOptions.kt @@ -15,6 +15,8 @@ import kotlin.properties.ReadOnlyProperty object BinaryOptions : BinaryOptionRegistry() { val runtimeAssertionsMode by option() + val checkStateAtExternalCalls by booleanOption() + val memoryModel by option() val freezing by option() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 89cc40086a1..d4449b7ae1f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -95,6 +95,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration private val defaultGC get() = GC.PARALLEL_MARK_CONCURRENT_SWEEP val gc: GC get() = configuration.get(BinaryOptions.gc) ?: defaultGC val runtimeAssertsMode: RuntimeAssertsMode get() = configuration.get(BinaryOptions.runtimeAssertionsMode) ?: RuntimeAssertsMode.IGNORE + val checkStateAtExternalCalls: Boolean get() = configuration.get(BinaryOptions.checkStateAtExternalCalls) ?: false private val defaultDisableMmap get() = target.family == Family.MINGW val disableMmap: Boolean by lazy { when (configuration.get(BinaryOptions.disableMmap)) { @@ -400,6 +401,10 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration add("custom_alloc.bc") } } + when (checkStateAtExternalCalls) { + true -> add("impl_externalCallsChecker.bc") + false -> add("noop_externalCallsChecker.bc") + } }.map { File(distribution.defaultNatives(target)).child(it).absolutePath } @@ -523,6 +528,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration optimizationsEnabled -> "for optimized compilation" sanitizer != null -> "with sanitizers enabled" runtimeLogsEnabled -> "with runtime logs" + checkStateAtExternalCalls -> "with external calls state checker" else -> null } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 09680c4d34d..19d5e81f386 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -101,8 +101,6 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("export KDoc into klib and framework") val PRINT_BITCODE: CompilerConfigurationKey = CompilerConfigurationKey.create("print bitcode") - val CHECK_EXTERNAL_CALLS: CompilerConfigurationKey - = CompilerConfigurationKey.create("check external calls") val PRINT_IR: CompilerConfigurationKey = CompilerConfigurationKey.create("print ir") val PRINT_FILES: CompilerConfigurationKey diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt index ce24db5c8ef..cdfe0166116 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/SetupConfiguration.kt @@ -108,7 +108,6 @@ fun CompilerConfiguration.setupFromArguments(arguments: K2NativeCompilerArgument put(PRINT_IR, arguments.printIr) put(PRINT_BITCODE, arguments.printBitCode) - put(CHECK_EXTERNAL_CALLS, arguments.checkExternalCalls) put(PRINT_FILES, arguments.printFiles) put(PURGE_USER_LIBS, arguments.purgeUserLibs) @@ -242,6 +241,14 @@ fun CompilerConfiguration.setupFromArguments(arguments: K2NativeCompilerArgument putIfNotNull(BinaryOptions.gc, gcFromArgument) } + if (arguments.checkExternalCalls != null) { + report(WARNING, "-Xcheck-state-at-external-calls compiler argument is deprecated. Use -Xbinary=checkStateAtExternalCalls=true instead") + } + // TODO: revise priority and/or report conflicting values. + if (get(BinaryOptions.checkStateAtExternalCalls) == null) { + putIfNotNull(BinaryOptions.checkStateAtExternalCalls, arguments.checkExternalCalls) + } + putIfNotNull(PROPERTY_LAZY_INITIALIZATION, when (arguments.propertyLazyInitialization) { null -> null "enable" -> true diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt index 661d600c334..dfaa633499f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt @@ -249,7 +249,7 @@ internal data class ModuleCompilationOutput( */ internal fun PhaseEngine.compileModule(module: IrModuleFragment, bitcodeFile: java.io.File, cExportFiles: CExportFiles?) { runBackendCodegen(module, cExportFiles) - val checkExternalCalls = context.config.configuration.getBoolean(KonanConfigKeys.CHECK_EXTERNAL_CALLS) + val checkExternalCalls = context.config.checkStateAtExternalCalls if (checkExternalCalls) { runPhase(CheckExternalCallsPhase) } diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index a24c7557040..ef2c329ad58 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -42,6 +42,7 @@ val targetList: List by project bitcode { allTargets { module("main") { + headersDirs.from("src/externalCallsChecker/common/cpp") sourceSets { main { // TODO: Split out out `base` module and merge it together with `main` into `runtime.bc` @@ -133,21 +134,21 @@ bitcode { } module("compiler_interface") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } } module("launcher") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } } module("debug") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -155,7 +156,7 @@ bitcode { module("common_alloc") { srcRoot.set(layout.projectDirectory.dir("src/alloc/common")) - headersDirs.from(files("src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -163,7 +164,7 @@ bitcode { module("std_alloc") { srcRoot.set(layout.projectDirectory.dir("src/alloc/std")) - headersDirs.from(files("src/alloc/common/cpp", "src/alloc/legacy/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/alloc/legacy/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -171,7 +172,7 @@ bitcode { module("custom_alloc") { srcRoot.set(layout.projectDirectory.dir("src/alloc/custom")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} @@ -183,7 +184,7 @@ bitcode { module("mimalloc_alloc") { srcRoot.set(layout.projectDirectory.dir("src/alloc/mimalloc")) - headersDirs.from(files("src/mimalloc/c/include", "src/alloc/common/cpp", "src/alloc/legacy/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/mimalloc/c/include", "src/alloc/common/cpp", "src/alloc/legacy/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -193,7 +194,7 @@ bitcode { module("legacy_alloc") { srcRoot.set(layout.projectDirectory.dir("src/alloc/legacy")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} @@ -203,7 +204,7 @@ bitcode { module("exceptionsSupport") { srcRoot.set(layout.projectDirectory.dir("src/exceptions_support")) - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -211,7 +212,7 @@ bitcode { module("source_info_core_symbolication") { srcRoot.set(layout.projectDirectory.dir("src/source_info/core_symbolication")) - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -221,7 +222,7 @@ bitcode { module("source_info_libbacktrace") { srcRoot.set(layout.projectDirectory.dir("src/source_info/libbacktrace")) - headersDirs.from(files("src/main/cpp", "src/libbacktrace/c/include")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp", "src/libbacktrace/c/include")) sourceSets { main {} } @@ -230,14 +231,14 @@ bitcode { } module("objc") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } } module("test_support") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { testFixtures { inputFiles.include("**/*.cpp", "**/*.mm") @@ -246,7 +247,7 @@ bitcode { } module("mm") { - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} testFixtures {} @@ -256,7 +257,7 @@ bitcode { module("common_gc") { srcRoot.set(layout.projectDirectory.dir("src/gc/common")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} @@ -265,7 +266,7 @@ bitcode { module("noop_gc") { srcRoot.set(layout.projectDirectory.dir("src/gc/noop")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) sourceSets { main {} } @@ -273,7 +274,7 @@ bitcode { module("noop_gc_custom") { srcRoot.set(layout.projectDirectory.dir("src/gc/noop")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/custom/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/custom/cpp")) sourceSets { main {} } @@ -283,7 +284,7 @@ bitcode { module("same_thread_ms_gc") { srcRoot.set(layout.projectDirectory.dir("src/gc/stms")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) sourceSets { main {} test {} @@ -292,7 +293,7 @@ bitcode { module("same_thread_ms_gc_custom") { srcRoot.set(layout.projectDirectory.dir("src/gc/stms")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/custom/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/custom/cpp")) sourceSets { main {} test {} @@ -303,7 +304,7 @@ bitcode { module("pmcs_gc") { srcRoot.set(layout.projectDirectory.dir("src/gc/pmcs")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) sourceSets { main {} test {} @@ -312,7 +313,7 @@ bitcode { module("pmcs_gc_custom") { srcRoot.set(layout.projectDirectory.dir("src/gc/pmcs")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/custom/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/custom/cpp")) sourceSets { main {} test {} @@ -323,7 +324,7 @@ bitcode { module("concurrent_ms_gc") { srcRoot.set(layout.projectDirectory.dir("src/gc/cms")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/legacy/cpp")) sourceSets { main {} test {} @@ -332,7 +333,7 @@ bitcode { module("concurrent_ms_gc_custom") { srcRoot.set(layout.projectDirectory.dir("src/gc/cms")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/alloc/custom/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp", "src/alloc/custom/cpp")) sourceSets { main {} test {} @@ -343,7 +344,7 @@ bitcode { module("common_gcScheduler") { srcRoot.set(layout.projectDirectory.dir("src/gcScheduler/common")) - headersDirs.from(files("src/alloc/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} @@ -352,7 +353,7 @@ bitcode { module("manual_gcScheduler") { srcRoot.set(layout.projectDirectory.dir("src/gcScheduler/manual")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} } @@ -360,7 +361,7 @@ bitcode { module("adaptive_gcScheduler") { srcRoot.set(layout.projectDirectory.dir("src/gcScheduler/adaptive")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} @@ -369,15 +370,31 @@ bitcode { module("aggressive_gcScheduler") { srcRoot.set(layout.projectDirectory.dir("src/gcScheduler/aggressive")) - headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) + headersDirs.from(files("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} test {} } } + module("impl_externalCallsChecker") { + srcRoot.set(layout.projectDirectory.dir("src/externalCallsChecker/impl")) + headersDirs.from("src/alloc/common/cpp", "src/gcScheduler/common/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/externalCallsChecker/common/cpp", "src/main/cpp") + sourceSets { + main {} + } + } + + module("noop_externalCallsChecker") { + srcRoot.set(layout.projectDirectory.dir("src/externalCallsChecker/noop")) + headersDirs.from("src/externalCallsChecker/common/cpp", "src/main/cpp") + sourceSets { + main {} + } + } + module("xctest_launcher") { - headersDirs.from(files("src/main/cpp")) + headersDirs.from(files("src/externalCallsChecker/common/cpp", "src/main/cpp")) sourceSets { main {} @@ -387,69 +404,69 @@ bitcode { testsGroup("custom_alloc_runtime_tests") { testedModules.addAll("custom_alloc") - testSupportModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc_custom", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc_custom", "objc") } testsGroup("experimentalMM_stms_mimalloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "same_thread_ms_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "same_thread_ms_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_stms_std_alloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "same_thread_ms_gc", "std_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "same_thread_ms_gc", "std_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_stms_custom_alloc_runtime_tests") { testedModules.addAll("mm", "same_thread_ms_gc_custom") - testSupportModules.addAll("main", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") } testsGroup("experimentalMM_pmcs_mimalloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "pmcs_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "pmcs_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_pmcs_std_alloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "pmcs_gc", "std_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "pmcs_gc", "std_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_pmcs_custom_alloc_runtime_tests") { testedModules.addAll("mm", "pmcs_gc_custom") - testSupportModules.addAll("main", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") } testsGroup("experimentalMM_cms_mimalloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_cms_std_alloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc", "std_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc", "std_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_cms_custom_alloc_runtime_tests") { testedModules.addAll("mm", "concurrent_ms_gc_custom") - testSupportModules.addAll("main", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") } testsGroup("experimentalMM_noop_mimalloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "noop_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "noop_gc", "mimalloc", "mimalloc_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_noop_std_alloc_runtime_tests") { - testedModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") + testedModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") } testsGroup("experimentalMM_noop_custom_alloc_runtime_tests") { testedModules.addAll("mm", "noop_gc_custom") - testSupportModules.addAll("main", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "custom_alloc", "objc") } testsGroup("aggressive_gcScheduler_runtime_tests") { testedModules.addAll("aggressive_gcScheduler") - testSupportModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") } testsGroup("adaptive_gcScheduler_runtime_tests") { testedModules.addAll("adaptive_gcScheduler") - testSupportModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") + testSupportModules.addAll("main", "noop_externalCallsChecker", "mm", "common_alloc", "common_gc", "common_gcScheduler", "noop_gc", "std_alloc", "legacy_alloc", "objc") } } } diff --git a/kotlin-native/runtime/src/main/cpp/CallsChecker.hpp b/kotlin-native/runtime/src/externalCallsChecker/common/cpp/CallsChecker.hpp similarity index 82% rename from kotlin-native/runtime/src/main/cpp/CallsChecker.hpp rename to kotlin-native/runtime/src/externalCallsChecker/common/cpp/CallsChecker.hpp index e0f84d5798f..c26b278e952 100644 --- a/kotlin-native/runtime/src/main/cpp/CallsChecker.hpp +++ b/kotlin-native/runtime/src/externalCallsChecker/common/cpp/CallsChecker.hpp @@ -8,6 +8,8 @@ #include "Common.h" #include "Utils.hpp" +#define NO_EXTERNAL_CALLS_CHECK __attribute__((annotate("no_external_calls_check"))) + namespace kotlin { // Ignore thread state checker for the scope. @@ -19,4 +21,4 @@ public: ALWAYS_INLINE ~CallsCheckerIgnoreGuard(); }; -} +} // namespace kotlin diff --git a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp b/kotlin-native/runtime/src/externalCallsChecker/impl/cpp/CallsChecker.cpp similarity index 94% rename from kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp rename to kotlin-native/runtime/src/externalCallsChecker/impl/cpp/CallsChecker.cpp index 53c242a54bd..98ae7c388bf 100644 --- a/kotlin-native/runtime/src/mm/cpp/CallsChecker.cpp +++ b/kotlin-native/runtime/src/externalCallsChecker/impl/cpp/CallsChecker.cpp @@ -20,7 +20,7 @@ using namespace kotlin; // this values will be substituted by compiler -extern "C" const void **Kotlin_callsCheckerKnownFunctions = nullptr; +extern "C" const void** Kotlin_callsCheckerKnownFunctions = nullptr; extern "C" int Kotlin_callsCheckerKnownFunctionsCount = 0; extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = { @@ -290,13 +290,13 @@ public: for (int i = 0; i < Kotlin_callsCheckerKnownFunctionsCount; i++) { known_functions_.insert(Kotlin_callsCheckerKnownFunctions[i]); } - std::copy(std::begin(Kotlin_callsCheckerGoodFunctionNames), std::end(Kotlin_callsCheckerGoodFunctionNames), std::begin(good_names_copy_)); + std::copy( + std::begin(Kotlin_callsCheckerGoodFunctionNames), std::end(Kotlin_callsCheckerGoodFunctionNames), + std::begin(good_names_copy_)); std::sort(std::begin(good_names_copy_), std::end(good_names_copy_)); } - bool isKnown(const void* fun) const noexcept { - return known_functions_.find(fun) != known_functions_.end(); - } + bool isKnown(const void* fun) const noexcept { return known_functions_.find(fun) != known_functions_.end(); } bool isSafeByName(std::string_view name) const noexcept { auto it = std::lower_bound(std::begin(good_names_copy_), std::end(good_names_copy_), name); @@ -307,10 +307,10 @@ public: return name.substr(0, banned.size() - 1) == banned.substr(0, banned.size() - 1); }; if (it != std::end(good_names_copy_) && check(*it)) { - return true; + return true; } if (it != std::begin(good_names_copy_) && check(*std::prev(it))) { - return true; + return true; } return false; } @@ -324,13 +324,12 @@ private: [[clang::no_destroy]] const KnownFunctionChecker checker; - constexpr int MSG_SEND_TO_NULL = -1; constexpr int CALLED_LLVM_BUILTIN = -2; thread_local size_t ignoreGuardsCount = 0; -} +} // namespace /** * This function calls is inserted to llvm bitcode automatically, so it can be called almost anywhre. @@ -342,7 +341,8 @@ thread_local size_t ignoreGuardsCount = 0; * should not be accessed. So before guard checking we need to check is thread destructor is running, * which requires special handling of recursive calls from this check. */ -extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFunctionCall(const char* caller, const char *callee, const void *calleePtr) noexcept { +extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFunctionCall( + const char* caller, const char* callee, const void* calleePtr) noexcept { if (reinterpret_cast(calleePtr) == MSG_SEND_TO_NULL) return; // objc_sendMsg called on nil, it does nothing, so it's ok if (ignoreGuardsCount != 0) return; if (konan::isOnThreadExitNotSetOrAlreadyStarted()) return; @@ -375,5 +375,9 @@ extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFu RuntimeFail("Expected kNative thread state at call of function %s by function %s", callee, caller); } -CallsCheckerIgnoreGuard::CallsCheckerIgnoreGuard() noexcept { ++ignoreGuardsCount; } -CallsCheckerIgnoreGuard::~CallsCheckerIgnoreGuard() { --ignoreGuardsCount; } +CallsCheckerIgnoreGuard::CallsCheckerIgnoreGuard() noexcept { + ++ignoreGuardsCount; +} +CallsCheckerIgnoreGuard::~CallsCheckerIgnoreGuard() { + --ignoreGuardsCount; +} diff --git a/kotlin-native/runtime/src/externalCallsChecker/noop/cpp/CallsChecker.cpp b/kotlin-native/runtime/src/externalCallsChecker/noop/cpp/CallsChecker.cpp new file mode 100644 index 00000000000..450f3ff72d0 --- /dev/null +++ b/kotlin-native/runtime/src/externalCallsChecker/noop/cpp/CallsChecker.cpp @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "CallsChecker.hpp" + +using namespace kotlin; + +CallsCheckerIgnoreGuard::CallsCheckerIgnoreGuard() noexcept = default; +CallsCheckerIgnoreGuard::~CallsCheckerIgnoreGuard() = default; \ No newline at end of file diff --git a/kotlin-native/runtime/src/main/cpp/Common.h b/kotlin-native/runtime/src/main/cpp/Common.h index 286075f2696..8609f103b77 100644 --- a/kotlin-native/runtime/src/main/cpp/Common.h +++ b/kotlin-native/runtime/src/main/cpp/Common.h @@ -36,8 +36,6 @@ #endif #define NO_INLINE __attribute__((noinline)) -#define NO_EXTERNAL_CALLS_CHECK __attribute__((annotate("no_external_calls_check"))) - #define OPTNONE __attribute__((optnone)) #define THREAD_LOCAL_VARIABLE __thread diff --git a/kotlin-native/runtime/src/main/cpp/Mutex.hpp b/kotlin-native/runtime/src/main/cpp/Mutex.hpp index 5389be321f2..195f011f1c6 100644 --- a/kotlin-native/runtime/src/main/cpp/Mutex.hpp +++ b/kotlin-native/runtime/src/main/cpp/Mutex.hpp @@ -21,6 +21,7 @@ #include #include +#include "CallsChecker.hpp" #include "KAssert.h" #include "Memory.h" #include "Utils.hpp" diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm b/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm index 1db58b09bc6..a3f1e0fa241 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm +++ b/kotlin-native/runtime/src/main/cpp/ObjCExportCollectionUtils.mm @@ -25,6 +25,7 @@ #import #import +#import "CallsChecker.hpp" #import "Exceptions.h" #import "ObjCExport.h" #import "ObjCExportCollections.h" diff --git a/kotlin-native/runtime/src/main/cpp/Porting.cpp b/kotlin-native/runtime/src/main/cpp/Porting.cpp index 86c580b1bbf..8fbee36c8bf 100644 --- a/kotlin-native/runtime/src/main/cpp/Porting.cpp +++ b/kotlin-native/runtime/src/main/cpp/Porting.cpp @@ -30,6 +30,7 @@ #include +#include "CallsChecker.hpp" #include "Common.h" #include "CompilerConstants.hpp" #include "Porting.h" diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/settings/TestProcessSettings.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/settings/TestProcessSettings.kt index 25c59fefd35..f967214fd46 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/settings/TestProcessSettings.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/settings/TestProcessSettings.kt @@ -127,7 +127,7 @@ internal enum class OptimizationMode(private val description: String, val compil */ internal enum class ThreadStateChecker(val compilerFlag: String?) { DISABLED(null), - ENABLED("-Xcheck-state-at-external-calls"); + ENABLED("-Xbinary=checkStateAtExternalCalls=true"); override fun toString() = compilerFlag?.let { "($it)" }.orEmpty() }