From 5e456ed82b9690c99004a2d58cb3e8228b18faf9 Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Tue, 4 May 2021 10:23:16 +0000 Subject: [PATCH] Put GC implementations into separate modules. The mm module now compiles separately for each GC implementation. --- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 26 ++++++- .../cli/bc/K2NativeCompilerArguments.kt | 3 + .../org/jetbrains/kotlin/backend/konan/GC.kt | 11 +++ .../kotlin/backend/konan/KonanConfig.kt | 13 +++- .../backend/konan/KonanConfigurationKeys.kt | 3 +- kotlin-native/runtime/build.gradle.kts | 75 +++++++++++++++++-- .../src/gc/common/cpp/MarkAndSweepUtils.cpp | 6 ++ .../common/cpp}/MarkAndSweepUtils.hpp | 12 +-- .../common/cpp}/MarkAndSweepUtilsMarkTest.cpp | 2 +- .../cpp}/MarkAndSweepUtilsSweepTest.cpp | 4 +- kotlin-native/runtime/src/gc/noop/cpp/GC.hpp | 19 +++++ .../runtime/src/gc/noop/cpp/NoOpGC.cpp | 6 ++ .../src/{mm/cpp/gc => gc/noop/cpp}/NoOpGC.hpp | 10 +-- kotlin-native/runtime/src/gc/stms/cpp/GC.hpp | 19 +++++ .../stms/cpp}/SingleThreadMarkAndSweep.cpp | 44 +++++------ .../stms/cpp}/SingleThreadMarkAndSweep.hpp | 10 +-- .../cpp}/SingleThreadMarkAndSweepTest.cpp | 16 ++-- kotlin-native/runtime/src/mm/cpp/GC.hpp | 23 ------ .../runtime/src/mm/cpp/GlobalData.hpp | 8 +- .../runtime/src/mm/cpp/ObjectFactoryTest.cpp | 1 - .../runtime/src/mm/cpp/ThreadData.hpp | 8 +- 21 files changed, 230 insertions(+), 89 deletions(-) create mode 100644 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GC.kt create mode 100644 kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp rename kotlin-native/runtime/src/{mm/cpp/gc => gc/common/cpp}/MarkAndSweepUtils.hpp (91%) rename kotlin-native/runtime/src/{mm/cpp/gc => gc/common/cpp}/MarkAndSweepUtilsMarkTest.cpp (99%) rename kotlin-native/runtime/src/{mm/cpp/gc => gc/common/cpp}/MarkAndSweepUtilsSweepTest.cpp (99%) create mode 100644 kotlin-native/runtime/src/gc/noop/cpp/GC.hpp create mode 100644 kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.cpp rename kotlin-native/runtime/src/{mm/cpp/gc => gc/noop/cpp}/NoOpGC.hpp (90%) create mode 100644 kotlin-native/runtime/src/gc/stms/cpp/GC.hpp rename kotlin-native/runtime/src/{mm/cpp/gc => gc/stms/cpp}/SingleThreadMarkAndSweep.cpp (69%) rename kotlin-native/runtime/src/{mm/cpp/gc => gc/stms/cpp}/SingleThreadMarkAndSweep.hpp (91%) rename kotlin-native/runtime/src/{mm/cpp/gc => gc/stms/cpp}/SingleThreadMarkAndSweepTest.cpp (98%) delete mode 100644 kotlin-native/runtime/src/mm/cpp/GC.hpp diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index b745dc4ab41..44986012856 100644 --- a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -206,7 +206,7 @@ class K2Native : CLICompiler() { put(ENABLE_ASSERTIONS, arguments.enableAssertions) - put(MEMORY_MODEL, when (arguments.memoryModel) { + val memoryModel = when (arguments.memoryModel) { "relaxed" -> { configuration.report(STRONG_WARNING, "Relaxed memory model is not yet fully functional") MemoryModel.RELAXED @@ -217,7 +217,9 @@ class K2Native : CLICompiler() { configuration.report(ERROR, "Unsupported memory model ${arguments.memoryModel}") MemoryModel.STRICT } - }) + } + + put(MEMORY_MODEL, memoryModel) when { arguments.generateWorkerTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.WORKER) @@ -271,6 +273,26 @@ class K2Native : CLICompiler() { DestroyRuntimeMode.ON_SHUTDOWN } }) + val assertGcSupported = { + if (memoryModel != MemoryModel.EXPERIMENTAL) { + configuration.report(ERROR, "-Xgc is only supported for -memory-model experimental") + } + } + put(GARBAGE_COLLECTOR, when (arguments.gc) { + null -> GC.SINGLE_THREAD_MARK_SWEEP + "noop" -> { + assertGcSupported() + GC.NOOP + } + "stms" -> { + assertGcSupported() + GC.SINGLE_THREAD_MARK_SWEEP + } + else -> { + configuration.report(ERROR, "Unsupported GC ${arguments.gc}") + GC.SINGLE_THREAD_MARK_SWEEP + } + }) } } } diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index 780f4fb1164..e6422a60f71 100644 --- a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -305,6 +305,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value="-Xdestroy-runtime-mode", valueDescription = "", description = "When to destroy runtime. 'legacy' and 'on-shutdown' are currently supported. NOTE: 'legacy' mode is deprecated and will be removed.") var destroyRuntimeMode: String? = "on-shutdown" + @Argument(value="-Xgc", valueDescription = "", description = "GC to use, 'noop' and 'stms' are currently supported. Works only with -memory-model experimental") + var gc: String? = null + override fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> = super.configureAnalysisFlags(collector).also { val useExperimental = it[AnalysisFlags.useExperimental] as List<*> diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GC.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GC.kt new file mode 100644 index 00000000000..ce4dc57a8b5 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/GC.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.konan + +enum class GC { + NOOP, + SINGLE_THREAD_MARK_SWEEP, +} \ No newline at end of file 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 abbb17440cb..e4b4943c7e9 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 @@ -47,6 +47,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration val memoryModel: MemoryModel get() = configuration.get(KonanConfigKeys.MEMORY_MODEL)!! val destroyRuntimeMode: DestroyRuntimeMode get() = configuration.get(KonanConfigKeys.DESTROY_RUNTIME_MODE)!! + val gc: GC get() = configuration.get(KonanConfigKeys.GARBAGE_COLLECTOR)!! val needVerifyIr: Boolean get() = configuration.get(KonanConfigKeys.VERIFY_IR) == true @@ -161,7 +162,17 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration add("legacy_memory_manager.bc") } MemoryModel.EXPERIMENTAL -> { - add("experimental_memory_manager.bc") + add("common_gc.bc") + when (gc) { + GC.SINGLE_THREAD_MARK_SWEEP -> { + add("experimental_memory_manager_stms.bc") + add("single_thread_ms_gc.bc") + } + GC.NOOP -> { + add("experimental_memory_manager_noop.bc") + add("noop_gc.bc") + } + } } } if (shouldCoverLibraries || shouldCoverSources) add("profileRuntime.bc") 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 305625d5cb4..c72e1adb0ee 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 @@ -68,7 +68,7 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("provide manifest addend file") val MEMORY_MODEL: CompilerConfigurationKey = CompilerConfigurationKey.create("memory model") - val META_INFO: CompilerConfigurationKey> + val META_INFO: CompilerConfigurationKey> = CompilerConfigurationKey.create("generate metadata") val METADATA_KLIB: CompilerConfigurationKey = CompilerConfigurationKey.create("metadata klib") @@ -154,6 +154,7 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("override konan.properties values") val DESTROY_RUNTIME_MODE: CompilerConfigurationKey = CompilerConfigurationKey.create("when to destroy runtime") + val GARBAGE_COLLECTOR: CompilerConfigurationKey = CompilerConfigurationKey.create("gc") } } diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index baf82d35ffa..591e469aac9 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -41,10 +41,13 @@ bitcode { "${target}Objc", "${target}ExceptionsSupport", "${target}LegacyMemoryManager", - "${target}ExperimentalMemoryManager" + "${target}ExperimentalMemoryManagerNoop", + "${target}ExperimentalMemoryManagerStms", + "${target}CommonGc", + "${target}SingleThreadMsGc", + "${target}NoopGc" ) includeRuntime() - // TODO: Should depend on the sanitizer. } create("mimalloc") { @@ -103,7 +106,28 @@ bitcode { includeRuntime() } - create("experimental_memory_manager", file("src/mm")) { + create("experimental_memory_manager_noop", file("src/mm")) { + headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp") + includeRuntime() + } + + create("experimental_memory_manager_stms", file("src/mm")) { + headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp") + includeRuntime() + } + + create("common_gc", file("src/gc/common")) { + headersDirs += files("src/mm/cpp") + includeRuntime() + } + + create("noop_gc", file("src/gc/noop")) { + headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp") + includeRuntime() + } + + create("single_thread_ms_gc", file("src/gc/stms")) { + headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp") includeRuntime() } } @@ -148,12 +172,15 @@ targetList.forEach { targetName -> "${targetName}ExperimentalMMMimallocRuntimeTests", listOf( "${targetName}Runtime", - "${targetName}ExperimentalMemoryManager", + "${targetName}ExperimentalMemoryManagerStms", + "${targetName}CommonGc", + "${targetName}SingleThreadMsGc", "${targetName}Release", "${targetName}Mimalloc", "${targetName}OptAlloc" ) ) { + headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp") includeRuntime() }) @@ -163,11 +190,49 @@ targetList.forEach { targetName -> "${targetName}ExperimentalMMStdAllocRuntimeTests", listOf( "${targetName}Runtime", - "${targetName}ExperimentalMemoryManager", + "${targetName}ExperimentalMemoryManagerStms", + "${targetName}CommonGc", + "${targetName}SingleThreadMsGc", "${targetName}Release", "${targetName}StdAlloc" ) ) { + headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp") + includeRuntime() + }) + + allTests.addAll(createTestTasks( + project, + targetName, + "${targetName}ExperimentalMMNoOpMimallocRuntimeTests", + listOf( + "${targetName}Runtime", + "${targetName}ExperimentalMemoryManagerNoop", + "${targetName}CommonGc", + "${targetName}NoopGc", + "${targetName}Release", + "${targetName}Mimalloc", + "${targetName}OptAlloc" + ) + ) { + headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp") + includeRuntime() + }) + + allTests.addAll(createTestTasks( + project, + targetName, + "${targetName}ExperimentalMMNoOpStdAllocRuntimeTests", + listOf( + "${targetName}Runtime", + "${targetName}ExperimentalMemoryManagerNoop", + "${targetName}CommonGc", + "${targetName}NoopGc", + "${targetName}Release", + "${targetName}StdAlloc" + ) + ) { + headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp") includeRuntime() }) diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp new file mode 100644 index 00000000000..69e6f9c51bf --- /dev/null +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.cpp @@ -0,0 +1,6 @@ +/* + * Copyright 2010-2021 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 "MarkAndSweepUtils.hpp" diff --git a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtils.hpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp similarity index 91% rename from kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtils.hpp rename to kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp index a028e413ec1..1eb97eb8048 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtils.hpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp @@ -3,10 +3,10 @@ * that can be found in the LICENSE file. */ -#ifndef RUNTIME_MM_MARK_AND_SWEEP_UTILS_H -#define RUNTIME_MM_MARK_AND_SWEEP_UTILS_H +#ifndef RUNTIME_GC_COMMON_MARK_AND_SWEEP_UTILS_H +#define RUNTIME_GC_COMMON_MARK_AND_SWEEP_UTILS_H -#include "../ExtraObjectData.hpp" +#include "ExtraObjectData.hpp" #include "FinalizerHooks.hpp" #include "Memory.h" #include "ObjectTraversal.hpp" @@ -14,7 +14,7 @@ #include "Types.h" namespace kotlin { -namespace mm { +namespace gc { // TODO: Because of `graySet` this implementation may allocate heap memory during GC. template @@ -73,7 +73,7 @@ typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFact return finalizerQueue; } -} // namespace mm +} // namespace gc } // namespace kotlin -#endif // RUNTIME_MM_MARK_AND_SWEEP_UTILS_H +#endif // RUNTIME_GC_COMMON_MARK_AND_SWEEP_UTILS_H diff --git a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsMarkTest.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp similarity index 99% rename from kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsMarkTest.cpp rename to kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp index d4fc71a11cd..dc3c5492750 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsMarkTest.cpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsMarkTest.cpp @@ -138,7 +138,7 @@ public: void Mark(std::initializer_list> graySet) { KStdVector objects; for (auto& object : graySet) objects.push_back(object.get().GetObjHeader()); - mm::Mark(std::move(objects)); + gc::Mark(std::move(objects)); } private: diff --git a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsSweepTest.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp similarity index 99% rename from kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsSweepTest.cpp rename to kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp index d991efb5dc0..76ee7a5f7e9 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/MarkAndSweepUtilsSweepTest.cpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "../ObjectFactory.hpp" #include "FinalizerHooksTestSupport.hpp" +#include "ObjectFactory.hpp" #include "ObjectTestSupport.hpp" using namespace kotlin; @@ -184,7 +184,7 @@ public: } KStdVector Sweep() { - auto finalizers = mm::Sweep(objectFactory_); + auto finalizers = gc::Sweep(objectFactory_); KStdVector objects; for (auto node : finalizers.IterForTests()) { objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); diff --git a/kotlin-native/runtime/src/gc/noop/cpp/GC.hpp b/kotlin-native/runtime/src/gc/noop/cpp/GC.hpp new file mode 100644 index 00000000000..4b7678e4682 --- /dev/null +++ b/kotlin-native/runtime/src/gc/noop/cpp/GC.hpp @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2021 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. + */ + +#ifndef RUNTIME_GC_NOOP_GC_H +#define RUNTIME_GC_NOOP_GC_H + +#include "NoOpGC.hpp" + +namespace kotlin { +namespace gc { + +using GC = kotlin::gc::NoOpGC; + +} // namespace gc +} // namespace kotlin + +#endif // RUNTIME_GC_NOOP_GC_H diff --git a/kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.cpp b/kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.cpp new file mode 100644 index 00000000000..0b0f25487af --- /dev/null +++ b/kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.cpp @@ -0,0 +1,6 @@ +/* + * Copyright 2010-2021 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 "NoOpGC.hpp" diff --git a/kotlin-native/runtime/src/mm/cpp/gc/NoOpGC.hpp b/kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.hpp similarity index 90% rename from kotlin-native/runtime/src/mm/cpp/gc/NoOpGC.hpp rename to kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.hpp index 3adf33f7d4a..a5513d22542 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/NoOpGC.hpp +++ b/kotlin-native/runtime/src/gc/noop/cpp/NoOpGC.hpp @@ -3,15 +3,15 @@ * that can be found in the LICENSE file. */ -#ifndef RUNTIME_MM_NOOP_GC_H -#define RUNTIME_MM_NOOP_GC_H +#ifndef RUNTIME_GC_NOOP_NOOP_GC_H +#define RUNTIME_GC_NOOP_NOOP_GC_H #include #include "Utils.hpp" namespace kotlin { -namespace mm { +namespace gc { // No-op GC is a GC that does not free memory. // TODO: It can be made more efficient. @@ -52,7 +52,7 @@ private: size_t allocationThresholdBytes_ = 0; }; -} // namespace mm +} // namespace gc } // namespace kotlin -#endif // RUNTIME_MM_NOOP_GC_H +#endif // RUNTIME_GC_NOOP_NOOP_GC_H diff --git a/kotlin-native/runtime/src/gc/stms/cpp/GC.hpp b/kotlin-native/runtime/src/gc/stms/cpp/GC.hpp new file mode 100644 index 00000000000..281bc4fdd23 --- /dev/null +++ b/kotlin-native/runtime/src/gc/stms/cpp/GC.hpp @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2021 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. + */ + +#ifndef RUNTIME_GC_STMS_GC_H +#define RUNTIME_GC_STMS_GC_H + +#include "SingleThreadMarkAndSweep.hpp" + +namespace kotlin { +namespace gc { + +using GC = kotlin::gc::SingleThreadMarkAndSweep; + +} // namespace gc +} // namespace kotlin + +#endif // RUNTIME_GC_STMS_GC_H diff --git a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.cpp similarity index 69% rename from kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.cpp rename to kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.cpp index 1d1912e6a2b..11b920297a1 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.cpp @@ -5,13 +5,13 @@ #include "SingleThreadMarkAndSweep.hpp" -#include "../GlobalData.hpp" -#include "../RootSet.hpp" -#include "../ThreadData.hpp" -#include "../ThreadRegistry.hpp" +#include "GlobalData.hpp" #include "MarkAndSweepUtils.hpp" #include "Memory.h" +#include "RootSet.hpp" #include "Runtime.h" +#include "ThreadData.hpp" +#include "ThreadRegistry.hpp" using namespace kotlin; @@ -19,57 +19,57 @@ namespace { struct MarkTraits { static bool IsMarked(ObjHeader* object) noexcept { - auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); - return objectData.color() == mm::SingleThreadMarkAndSweep::ObjectData::Color::kBlack; + auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); + return objectData.color() == gc::SingleThreadMarkAndSweep::ObjectData::Color::kBlack; } static bool TryMark(ObjHeader* object) noexcept { - auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); - if (objectData.color() == mm::SingleThreadMarkAndSweep::ObjectData::Color::kBlack) return false; - objectData.setColor(mm::SingleThreadMarkAndSweep::ObjectData::Color::kBlack); + auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); + if (objectData.color() == gc::SingleThreadMarkAndSweep::ObjectData::Color::kBlack) return false; + objectData.setColor(gc::SingleThreadMarkAndSweep::ObjectData::Color::kBlack); return true; }; }; struct SweepTraits { - using ObjectFactory = mm::ObjectFactory; + using ObjectFactory = mm::ObjectFactory; static bool TryResetMark(ObjectFactory::NodeRef node) noexcept { auto& objectData = node.GCObjectData(); - if (objectData.color() == mm::SingleThreadMarkAndSweep::ObjectData::Color::kWhite) return false; - objectData.setColor(mm::SingleThreadMarkAndSweep::ObjectData::Color::kWhite); + if (objectData.color() == gc::SingleThreadMarkAndSweep::ObjectData::Color::kWhite) return false; + objectData.setColor(gc::SingleThreadMarkAndSweep::ObjectData::Color::kWhite); return true; } }; struct FinalizeTraits { - using ObjectFactory = mm::ObjectFactory; + using ObjectFactory = mm::ObjectFactory; }; } // namespace -void mm::SingleThreadMarkAndSweep::ThreadData::SafePointFunctionEpilogue() noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::SafePointFunctionEpilogue() noexcept { if (gc_.GetThreshold() == 0 || safePointsCounter_ % gc_.GetThreshold() == 0) { PerformFullGC(); } ++safePointsCounter_; } -void mm::SingleThreadMarkAndSweep::ThreadData::SafePointLoopBody() noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::SafePointLoopBody() noexcept { if (gc_.GetThreshold() == 0 || safePointsCounter_ % gc_.GetThreshold() == 0) { PerformFullGC(); } ++safePointsCounter_; } -void mm::SingleThreadMarkAndSweep::ThreadData::SafePointExceptionUnwind() noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::SafePointExceptionUnwind() noexcept { if (gc_.GetThreshold() == 0 || safePointsCounter_ % gc_.GetThreshold() == 0) { PerformFullGC(); } ++safePointsCounter_; } -void mm::SingleThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) noexcept { size_t allocationOverhead = gc_.GetAllocationThresholdBytes() == 0 ? allocatedBytes_ : allocatedBytes_ % gc_.GetAllocationThresholdBytes(); if (allocationOverhead + size >= gc_.GetAllocationThresholdBytes()) { @@ -78,15 +78,15 @@ void mm::SingleThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) allocatedBytes_ += size; } -void mm::SingleThreadMarkAndSweep::ThreadData::PerformFullGC() noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::PerformFullGC() noexcept { gc_.PerformFullGC(); } -void mm::SingleThreadMarkAndSweep::ThreadData::OnOOM(size_t size) noexcept { +void gc::SingleThreadMarkAndSweep::ThreadData::OnOOM(size_t size) noexcept { PerformFullGC(); } -void mm::SingleThreadMarkAndSweep::PerformFullGC() noexcept { +void gc::SingleThreadMarkAndSweep::PerformFullGC() noexcept { RuntimeAssert(running_ == false, "Cannot have been called during another collection"); running_ = true; @@ -106,8 +106,8 @@ void mm::SingleThreadMarkAndSweep::PerformFullGC() noexcept { } } - mm::Mark(std::move(graySet)); - auto finalizerQueue = mm::Sweep(mm::GlobalData::Instance().objectFactory()); + gc::Mark(std::move(graySet)); + auto finalizerQueue = gc::Sweep(mm::GlobalData::Instance().objectFactory()); running_ = false; diff --git a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.hpp b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.hpp similarity index 91% rename from kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.hpp rename to kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.hpp index 8c0f77ec96c..117829f0e8c 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweep.hpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweep.hpp @@ -3,8 +3,8 @@ * that can be found in the LICENSE file. */ -#ifndef RUNTIME_MM_GC_SINGLE_THREAD_MARK_AND_SWEEP_H -#define RUNTIME_MM_GC_SINGLE_THREAD_MARK_AND_SWEEP_H +#ifndef RUNTIME_GC_STMS_SINGLE_THREAD_MARK_AND_SWEEP_H +#define RUNTIME_GC_STMS_SINGLE_THREAD_MARK_AND_SWEEP_H #include @@ -12,7 +12,7 @@ #include "Utils.hpp" namespace kotlin { -namespace mm { +namespace gc { // Stop-the-world Mark-and-Sweep for a single mutator class SingleThreadMarkAndSweep : private Pinned { @@ -72,7 +72,7 @@ private: size_t allocationThresholdBytes_ = 10000; }; -} // namespace mm +} // namespace gc } // namespace kotlin -#endif // RUNTIME_MM_GC_SINGLE_THREAD_MARK_AND_SWEEP_H +#endif // RUNTIME_GC_STMS_SINGLE_THREAD_MARK_AND_SWEEP_H diff --git a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweepTest.cpp b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweepTest.cpp similarity index 98% rename from kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweepTest.cpp rename to kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweepTest.cpp index 779bf35716c..fac94e55dd8 100644 --- a/kotlin-native/runtime/src/mm/cpp/gc/SingleThreadMarkAndSweepTest.cpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SingleThreadMarkAndSweepTest.cpp @@ -8,12 +8,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "../ExtraObjectData.hpp" -#include "../GlobalData.hpp" -#include "../ObjectOps.hpp" -#include "../TestSupport.hpp" +#include "ExtraObjectData.hpp" #include "FinalizerHooksTestSupport.hpp" +#include "GlobalData.hpp" +#include "ObjectOps.hpp" #include "ObjectTestSupport.hpp" +#include "TestSupport.hpp" +#include "ThreadData.hpp" using namespace kotlin; @@ -186,10 +187,10 @@ KStdVector Alive(mm::ThreadData& threadData) { return objects; } -using Color = mm::SingleThreadMarkAndSweep::ObjectData::Color; +using Color = gc::SingleThreadMarkAndSweep::ObjectData::Color; Color GetColor(ObjHeader* objHeader) { - auto nodeRef = mm::ObjectFactory::NodeRef::From(objHeader); + auto nodeRef = mm::ObjectFactory::NodeRef::From(objHeader); return nodeRef.GCObjectData().color(); } @@ -591,7 +592,8 @@ TEST_F(SingleThreadMarkAndSweepTest, PermanentObjects) { GlobalPermanentObjectHolder global1{threadData}; GlobalObjectHolder global2{threadData}; test_support::Object permanentObject{typeHolder.typeInfo()}; - permanentObject.header()->typeInfoOrMeta_ = setPointerBits(permanentObject.header()->typeInfoOrMeta_, OBJECT_TAG_PERMANENT_CONTAINER); + permanentObject.header()->typeInfoOrMeta_ = + setPointerBits(permanentObject.header()->typeInfoOrMeta_, OBJECT_TAG_PERMANENT_CONTAINER); RuntimeAssert(permanentObject.header()->permanent(), "Must be permanent"); global1->field1 = permanentObject.header(); diff --git a/kotlin-native/runtime/src/mm/cpp/GC.hpp b/kotlin-native/runtime/src/mm/cpp/GC.hpp deleted file mode 100644 index 2556c829d87..00000000000 --- a/kotlin-native/runtime/src/mm/cpp/GC.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2010-2021 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. - */ - -#ifndef RUNTIME_MM_GC_H -#define RUNTIME_MM_GC_H - -#include "gc/SingleThreadMarkAndSweep.hpp" -#include "gc/NoOpGC.hpp" - -namespace kotlin { -namespace mm { - -// TODO: GC should be extracted into a separate module, so that we can do different GCs without -// the need to redo the entire MM. For now changing GCs can be done by modifying `using` below. - -using GC = SingleThreadMarkAndSweep; - -} // namespace mm -} // namespace kotlin - -#endif // RUNTIME_MM_GC_H diff --git a/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp b/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp index 2b084e45cb8..5427d32f3c4 100644 --- a/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp +++ b/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp @@ -24,8 +24,8 @@ public: ThreadRegistry& threadRegistry() noexcept { return threadRegistry_; } GlobalsRegistry& globalsRegistry() noexcept { return globalsRegistry_; } StableRefRegistry& stableRefRegistry() noexcept { return stableRefRegistry_; } - ObjectFactory& objectFactory() noexcept { return objectFactory_; } - GC& gc() noexcept { return gc_; } + ObjectFactory& objectFactory() noexcept { return objectFactory_; } + gc::GC& gc() noexcept { return gc_; } private: GlobalData(); @@ -37,8 +37,8 @@ private: ThreadRegistry threadRegistry_; GlobalsRegistry globalsRegistry_; StableRefRegistry stableRefRegistry_; - ObjectFactory objectFactory_; - GC gc_; + ObjectFactory objectFactory_; + gc::GC gc_; }; } // namespace mm diff --git a/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp b/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp index 25aaa5e4670..5f619c6da1e 100644 --- a/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp @@ -13,7 +13,6 @@ #include "gtest/gtest.h" #include "FinalizerHooksTestSupport.hpp" -#include "GC.hpp" #include "ObjectTestSupport.hpp" #include "TestSupport.hpp" #include "Types.h" diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp b/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp index 864688d308a..12e6d7e4a68 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp @@ -51,13 +51,13 @@ public: ThreadState setState(ThreadState state) noexcept { return state_.exchange(state); } - ObjectFactory::ThreadQueue& objectFactoryThreadQueue() noexcept { return objectFactoryThreadQueue_; } + ObjectFactory::ThreadQueue& objectFactoryThreadQueue() noexcept { return objectFactoryThreadQueue_; } ShadowStack& shadowStack() noexcept { return shadowStack_; } KStdVector>& initializingSingletons() noexcept { return initializingSingletons_; } - GC::ThreadData& gc() noexcept { return gc_; } + gc::GC::ThreadData& gc() noexcept { return gc_; } void Publish() noexcept { // TODO: These use separate locks, which is inefficient. @@ -79,8 +79,8 @@ private: StableRefRegistry::ThreadQueue stableRefThreadQueue_; std::atomic state_; ShadowStack shadowStack_; - GC::ThreadData gc_; - ObjectFactory::ThreadQueue objectFactoryThreadQueue_; + gc::GC::ThreadData gc_; + ObjectFactory::ThreadQueue objectFactoryThreadQueue_; KStdVector> initializingSingletons_; };