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 c797fdfb535..3353cefaa1e 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 @@ -66,6 +66,8 @@ object BinaryOptions : BinaryOptionRegistry() { val disableMmap by booleanOption() val disableAllocatorOverheadEstimate by booleanOption() + + val enableSafepointSignposts by booleanOption() } open class BinaryOption( 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 f89127cc0b0..d614ad9edf1 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 @@ -242,6 +242,12 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration configuration.get(BinaryOptions.objcDisposeOnMain) ?: true } + val enableSafepointSignposts: Boolean = configuration.get(BinaryOptions.enableSafepointSignposts)?.also { + if (it && !target.supportsSignposts) { + configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Signposts are not available on $target. The setting will have no effect.") + } + } ?: false + init { if (!platformManager.isEnabled(target)) { error("Target ${target.visibleName} is not available on the ${HostManager.hostName} host") diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 3690d8e4d5b..398f43f072a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -2833,6 +2833,7 @@ internal class CodeGeneratorVisitor( overrideRuntimeGlobal("Kotlin_mimallocUseDefaultOptions", llvm.constInt32(if (context.config.mimallocUseDefaultOptions) 1 else 0)) overrideRuntimeGlobal("Kotlin_mimallocUseCompaction", llvm.constInt32(if (context.config.mimallocUseCompaction) 1 else 0)) overrideRuntimeGlobal("Kotlin_objcDisposeOnMain", llvm.constInt32(if (context.config.objcDisposeOnMain) 1 else 0)) + overrideRuntimeGlobal("Kotlin_enableSafepointSignposts", llvm.constInt32(if (context.config.enableSafepointSignposts) 1 else 0)) } //-------------------------------------------------------------------------// diff --git a/kotlin-native/runtime/src/main/cpp/CompilerConstants.cpp b/kotlin-native/runtime/src/main/cpp/CompilerConstants.cpp index dbe578da169..83575e9ec8e 100644 --- a/kotlin-native/runtime/src/main/cpp/CompilerConstants.cpp +++ b/kotlin-native/runtime/src/main/cpp/CompilerConstants.cpp @@ -32,6 +32,7 @@ RUNTIME_WEAK int32_t Kotlin_appStateTracking = 0; RUNTIME_WEAK int32_t Kotlin_mimallocUseDefaultOptions = 1; RUNTIME_WEAK int32_t Kotlin_mimallocUseCompaction = 0; RUNTIME_WEAK int32_t Kotlin_objcDisposeOnMain = 0; +RUNTIME_WEAK int32_t Kotlin_enableSafepointSignposts = 0; ALWAYS_INLINE compiler::DestroyRuntimeMode compiler::destroyRuntimeMode() noexcept { return static_cast(Kotlin_destroyRuntimeMode); @@ -83,3 +84,7 @@ ALWAYS_INLINE bool compiler::mimallocUseCompaction() noexcept { ALWAYS_INLINE bool compiler::objcDisposeOnMain() noexcept { return Kotlin_objcDisposeOnMain != 0; } + +ALWAYS_INLINE bool compiler::enableSafepointSignposts() noexcept { + return Kotlin_enableSafepointSignposts != 0; +} diff --git a/kotlin-native/runtime/src/main/cpp/CompilerConstants.hpp b/kotlin-native/runtime/src/main/cpp/CompilerConstants.hpp index a4cead9608d..ae0611f2852 100644 --- a/kotlin-native/runtime/src/main/cpp/CompilerConstants.hpp +++ b/kotlin-native/runtime/src/main/cpp/CompilerConstants.hpp @@ -113,6 +113,7 @@ int getSourceInfo(void* addr, SourceInfo *result, int result_size) noexcept; bool mimallocUseDefaultOptions() noexcept; bool mimallocUseCompaction() noexcept; bool objcDisposeOnMain() noexcept; +bool enableSafepointSignposts() noexcept; #ifdef KONAN_ANDROID bool printToAndroidLogcat() noexcept; diff --git a/kotlin-native/runtime/src/mm/cpp/SafePoint.cpp b/kotlin-native/runtime/src/mm/cpp/SafePoint.cpp index 0e1c2277a25..a7d5774cbfb 100644 --- a/kotlin-native/runtime/src/mm/cpp/SafePoint.cpp +++ b/kotlin-native/runtime/src/mm/cpp/SafePoint.cpp @@ -13,6 +13,16 @@ #include "ThreadData.hpp" #include "ThreadState.hpp" +// TODO: Remove after the bootstrap that brings changes in ClangArgs.kt +#ifndef KONAN_SUPPORTS_SIGNPOSTS +#define KONAN_SUPPORTS_SIGNPOSTS KONAN_MACOSX || KONAN_IOS || KONAN_WATCHOS || KONAN_TVOS +#endif + +#if KONAN_SUPPORTS_SIGNPOSTS +#include +#include +#endif + using namespace kotlin; namespace { @@ -21,11 +31,45 @@ namespace { int64_t activeCount = 0; std::atomic safePointAction = nullptr; +#if KONAN_SUPPORTS_SIGNPOSTS + +#define SAFEPOINT_SIGNPOST_NAME "Safepoint" // signpost API requires strings be literals + +class SafePointSignpostInterval : private Pinned { +public: + explicit SafePointSignpostInterval(mm::ThreadData& threadData) noexcept : id_(os_signpost_id_make_with_pointer(logObject, &threadData)) { + os_signpost_interval_begin(logObject, id_, SAFEPOINT_SIGNPOST_NAME, "thread id: %d", threadData.threadId()); + } + + ~SafePointSignpostInterval() { + os_signpost_interval_end(logObject, id_, SAFEPOINT_SIGNPOST_NAME); + } + +private: + static os_log_t logObject; + uint64_t id_; +}; + +#undef SAFEPOINT_SIGNPOST_NAME + +// static +os_log_t SafePointSignpostInterval::logObject = os_log_create("org.kotlinlang.native.runtime", "safepoint"); +#else +class SafePointSignpostInterval : private Pinned { +public: + explicit SafePointSignpostInterval(mm::ThreadData& threadData) noexcept {} +}; +#endif + void safePointActionImpl(mm::ThreadData& threadData) noexcept { static thread_local bool recursion = false; RuntimeAssert(!recursion, "Recursive safepoint"); AutoReset guard(&recursion, true); + std::optional signpost; + if (compiler::enableSafepointSignposts()) { + signpost.emplace(threadData); + } threadData.gcScheduler().safePoint(); threadData.gc().safePoint(); threadData.suspensionData().suspendIfRequested(); diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/ClangArgs.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/ClangArgs.kt index ff092803110..45a1ff9d312 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/ClangArgs.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/ClangArgs.kt @@ -53,6 +53,7 @@ sealed class ClangArgs( "REPORT_BACKTRACE_TO_IOS_CRASH_LOG".takeIf { target.supportsIosCrashLog() }, "NEED_SMALL_BINARY".takeIf { target.needSmallBinary() }, "SUPPORTS_GRAND_CENTRAL_DISPATCH".takeIf { target.supportsGrandCentralDispatch }, + "SUPPORTS_SIGNPOSTS".takeIf { target.supportsSignposts }, ).map { "KONAN_$it=1" } val otherOptions = listOfNotNull( "USE_ELF_SYMBOLS=1".takeIf { target.binaryFormat() == BinaryFormat.ELF }, diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt index 53f628b2d3c..ef3497441b9 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/KonanTargetExtenstions.kt @@ -165,7 +165,7 @@ fun KonanTarget.hasAddressDependencyInMemoryModel(): Boolean = } val KonanTarget.supportsGrandCentralDispatch - get() = when(family) { - Family.WATCHOS, Family.IOS, Family.TVOS, Family.OSX -> true - else -> false - } + get() = family.isAppleFamily + +val KonanTarget.supportsSignposts + get() = family.isAppleFamily \ No newline at end of file