Support sanitizers in runtime tests (#4622)
This commit is contained in:
committed by
Nikolay Krasko
parent
3ee8d98726
commit
6cc60ad6a2
@@ -5,6 +5,8 @@
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.testing.native.*
|
||||
import org.jetbrains.kotlin.bitcode.CompileToBitcode
|
||||
import org.jetbrains.kotlin.bitcode.CompileToBitcodeExtension
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
plugins {
|
||||
id("compile-to-bitcode")
|
||||
@@ -42,6 +44,7 @@ bitcode {
|
||||
"${target}ExperimentalMemoryManager"
|
||||
)
|
||||
includeRuntime()
|
||||
// TODO: Should depend on the sanitizer.
|
||||
linkerArgs.add(project.file("../common/build/bitcode/main/$target/hash.bc").path)
|
||||
}
|
||||
|
||||
@@ -107,9 +110,11 @@ bitcode {
|
||||
}
|
||||
|
||||
targetList.forEach { targetName ->
|
||||
createTestTask(
|
||||
val allTests = mutableListOf<Task>()
|
||||
|
||||
allTests.addAll(createTestTasks(
|
||||
project,
|
||||
"StdAlloc",
|
||||
targetName,
|
||||
"${targetName}StdAllocRuntimeTests",
|
||||
listOf(
|
||||
"${targetName}Runtime",
|
||||
@@ -120,11 +125,11 @@ targetList.forEach { targetName ->
|
||||
)
|
||||
) {
|
||||
includeRuntime()
|
||||
}
|
||||
})
|
||||
|
||||
createTestTask(
|
||||
allTests.addAll(createTestTasks(
|
||||
project,
|
||||
"Mimalloc",
|
||||
targetName,
|
||||
"${targetName}MimallocRuntimeTests",
|
||||
listOf(
|
||||
"${targetName}Runtime",
|
||||
@@ -136,11 +141,11 @@ targetList.forEach { targetName ->
|
||||
)
|
||||
) {
|
||||
includeRuntime()
|
||||
}
|
||||
})
|
||||
|
||||
createTestTask(
|
||||
allTests.addAll(createTestTasks(
|
||||
project,
|
||||
"ExperimentalMMMimalloc",
|
||||
targetName,
|
||||
"${targetName}ExperimentalMMMimallocRuntimeTests",
|
||||
listOf(
|
||||
"${targetName}Runtime",
|
||||
@@ -151,11 +156,11 @@ targetList.forEach { targetName ->
|
||||
)
|
||||
) {
|
||||
includeRuntime()
|
||||
}
|
||||
})
|
||||
|
||||
createTestTask(
|
||||
allTests.addAll(createTestTasks(
|
||||
project,
|
||||
"ExperimentalMMStdAlloc",
|
||||
targetName,
|
||||
"${targetName}ExperimentalMMStdAllocRuntimeTests",
|
||||
listOf(
|
||||
"${targetName}Runtime",
|
||||
@@ -165,13 +170,11 @@ targetList.forEach { targetName ->
|
||||
)
|
||||
) {
|
||||
includeRuntime()
|
||||
}
|
||||
})
|
||||
|
||||
// TODO: This "all tests" tasks should be provided by `CompileToBitcodeExtension`
|
||||
tasks.register("${targetName}RuntimeTests") {
|
||||
dependsOn("${targetName}StdAllocRuntimeTests")
|
||||
dependsOn("${targetName}MimallocRuntimeTests")
|
||||
dependsOn("${targetName}ExperimentalMMStdAllocRuntimeTests")
|
||||
dependsOn("${targetName}ExperimentalMMMimallocRuntimeTests")
|
||||
dependsOn(allTests)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,9 @@ TEST_F(KonanAllocatorAwareTest, PlacementAllocated) {
|
||||
|
||||
TEST_F(KonanAllocatorAwareTest, PlacementConstructedArray) {
|
||||
constexpr size_t kCount = 5;
|
||||
std::array<uint8_t, sizeof(A) * kCount> buffer;
|
||||
// TODO: Consider removing support for placement new[] altogether, since there's no
|
||||
// portable way to know needed storage size ahead of time.
|
||||
alignas(A) std::array<uint8_t, sizeof(A) * kCount + sizeof(size_t)> buffer;
|
||||
A* as = new (buffer.data()) A[kCount];
|
||||
|
||||
std::vector<int> actual;
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace kotlin {
|
||||
#if KONAN_WINDOWS
|
||||
// TODO: Figure out why creating many threads on windows is so slow.
|
||||
constexpr int kDefaultThreadCount = 10;
|
||||
#elif __has_feature(thread_sanitizer)
|
||||
// TSAN has a huge overhead.
|
||||
constexpr int kDefaultThreadCount = 10;
|
||||
#else
|
||||
constexpr int kDefaultThreadCount = 100;
|
||||
#endif
|
||||
|
||||
@@ -14,9 +14,27 @@
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
ALWAYS_INLINE T UnsafeRead(T* location) noexcept {
|
||||
#if __has_feature(thread_sanitizer)
|
||||
// Make TSAN think that this load is fine.
|
||||
return __atomic_load_n(location, __ATOMIC_ACQUIRE);
|
||||
#else
|
||||
return *location;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
mm::ExtraObjectData& mm::ExtraObjectData::Install(ObjHeader* object) noexcept {
|
||||
TypeInfo* typeInfo = object->typeInfoOrMeta_;
|
||||
// TODO: Consider extracting initialization scheme with speculative load.
|
||||
// `object->typeInfoOrMeta_` is assigned at most once. If we read some old value (i.e. not a meta object),
|
||||
// we will fail at CAS below. If we read the new value, we will immediately return it.
|
||||
TypeInfo* typeInfo = UnsafeRead(&object->typeInfoOrMeta_);
|
||||
|
||||
if (auto* metaObject = ObjHeader::AsMetaObject(typeInfo)) {
|
||||
return mm::ExtraObjectData::FromMetaObjHeader(metaObject);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user