From e45b13d58272c1015e79eaf237e5b3dbed73ce2d Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Thu, 29 Jul 2021 15:31:50 +0700 Subject: [PATCH] [K/N][New MM] Check if asserts are enabled in thread state asserts --- kotlin-native/runtime/src/main/cpp/Memory.h | 10 +++++-- .../runtime/src/mm/cpp/ThreadState.cpp | 10 +++++-- .../runtime/src/mm/cpp/ThreadState.hpp | 27 +++++++++++++------ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/kotlin-native/runtime/src/main/cpp/Memory.h b/kotlin-native/runtime/src/main/cpp/Memory.h index da642951597..f0592878284 100644 --- a/kotlin-native/runtime/src/main/cpp/Memory.h +++ b/kotlin-native/runtime/src/main/cpp/Memory.h @@ -414,11 +414,17 @@ ALWAYS_INLINE void AssertThreadState(MemoryState* thread, std::initializer_list< // Asserts that the current thread is in the the given state. ALWAYS_INLINE inline void AssertThreadState(ThreadState expected) noexcept { - AssertThreadState(mm::GetMemoryState(), expected); + // Avoid redundant TLS access in GetMemoryState if runtime asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + AssertThreadState(mm::GetMemoryState(), expected); + } } ALWAYS_INLINE inline void AssertThreadState(std::initializer_list expected) noexcept { - AssertThreadState(mm::GetMemoryState(), expected); + // Avoid redundant TLS access in GetMemoryState if runtime asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + AssertThreadState(mm::GetMemoryState(), expected); + } } // Scopely sets the given thread state for the given thread. diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadState.cpp b/kotlin-native/runtime/src/mm/cpp/ThreadState.cpp index 32a487eb4f7..bcae03fc76e 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadState.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadState.cpp @@ -33,11 +33,17 @@ ALWAYS_INLINE ThreadState kotlin::SwitchThreadState(MemoryState* thread, ThreadS } ALWAYS_INLINE void kotlin::AssertThreadState(MemoryState* thread, ThreadState expected) noexcept { - AssertThreadState(thread->GetThreadData(), expected); + // Avoid redundant read in GetThreadData if runtime asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + AssertThreadState(thread->GetThreadData(), expected); + } } ALWAYS_INLINE void kotlin::AssertThreadState(MemoryState* thread, std::initializer_list expected) noexcept { - AssertThreadState(thread->GetThreadData(), expected); + // Avoid redundant read in GetThreadData if runtime asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + AssertThreadState(thread->GetThreadData(), expected); + } } ThreadState kotlin::GetThreadState(MemoryState* thread) noexcept { diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadState.hpp b/kotlin-native/runtime/src/mm/cpp/ThreadState.hpp index b13e26ba610..6c0e1904bfe 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadState.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadState.hpp @@ -38,17 +38,28 @@ ALWAYS_INLINE inline ThreadState SwitchThreadState(mm::ThreadData* threadData, T // Asserts that the given thread is in the given state. ALWAYS_INLINE inline void AssertThreadState(mm::ThreadData* threadData, ThreadState expected) noexcept { - auto actual = threadData->state(); - RuntimeAssert(actual == expected, - "Unexpected thread state. Expected: %s. Actual: %s.", - ThreadStateName(expected), ThreadStateName(actual)); + // The read of the thread state is atomic, thus the compiler cannot eliminate it + // even if its result is unused due to disabled runtime asserts. + // So we explicitly avoid the read if asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + auto actual = threadData->state(); + RuntimeAssert( + actual == expected, "Unexpected thread state. Expected: %s. Actual: %s.", ThreadStateName(expected), + ThreadStateName(actual)); + } } ALWAYS_INLINE inline void AssertThreadState(mm::ThreadData* threadData, std::initializer_list expected) noexcept { - auto actual = threadData->state(); - RuntimeAssert(std::any_of(expected.begin(), expected.end(), [actual](ThreadState expected) { return expected == actual; }), - "Unexpected thread state. Expected one of: %s. Actual: %s", - internal::statesToString(expected).c_str(), ThreadStateName(actual)); + // The read of the thread state is atomic, thus the compiler cannot eliminate it + // even if its result is unused due to disabled runtime asserts. + // So we explicitly avoid the read if asserts are disabled. + if (compiler::runtimeAssertsMode() != compiler::RuntimeAssertsMode::kIgnore) { + auto actual = threadData->state(); + RuntimeAssert( + std::any_of(expected.begin(), expected.end(), [actual](ThreadState expected) { return expected == actual; }), + "Unexpected thread state. Expected one of: %s. Actual: %s", internal::statesToString(expected).c_str(), + ThreadStateName(actual)); + } } } // namespace kotlin