[K/N] Add cms related targets and compiler option
This commit is contained in:
@@ -315,6 +315,10 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
assertGcSupported()
|
assertGcSupported()
|
||||||
GC.SAME_THREAD_MARK_AND_SWEEP
|
GC.SAME_THREAD_MARK_AND_SWEEP
|
||||||
}
|
}
|
||||||
|
"cms" -> {
|
||||||
|
assertGcSupported()
|
||||||
|
GC.CONCURRENT_MARK_AND_SWEEP
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
configuration.report(ERROR, "Unsupported GC ${arguments.gc}")
|
configuration.report(ERROR, "Unsupported GC ${arguments.gc}")
|
||||||
GC.SAME_THREAD_MARK_AND_SWEEP
|
GC.SAME_THREAD_MARK_AND_SWEEP
|
||||||
|
|||||||
+1
@@ -8,4 +8,5 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
enum class GC {
|
enum class GC {
|
||||||
NOOP,
|
NOOP,
|
||||||
SAME_THREAD_MARK_AND_SWEEP,
|
SAME_THREAD_MARK_AND_SWEEP,
|
||||||
|
CONCURRENT_MARK_AND_SWEEP
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -235,6 +235,11 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
add("experimental_memory_manager_noop.bc")
|
add("experimental_memory_manager_noop.bc")
|
||||||
add("noop_gc.bc")
|
add("noop_gc.bc")
|
||||||
}
|
}
|
||||||
|
GC.CONCURRENT_MARK_AND_SWEEP -> {
|
||||||
|
add("common_gc_cms.bc")
|
||||||
|
add("experimental_memory_manager_cms.bc")
|
||||||
|
add("concurrent_ms_gc.bc")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,9 +60,12 @@ bitcode {
|
|||||||
"${target}LegacyMemoryManager",
|
"${target}LegacyMemoryManager",
|
||||||
"${target}ExperimentalMemoryManagerNoop",
|
"${target}ExperimentalMemoryManagerNoop",
|
||||||
"${target}ExperimentalMemoryManagerStms",
|
"${target}ExperimentalMemoryManagerStms",
|
||||||
|
"${target}ExperimentalMemoryManagerCms",
|
||||||
"${target}CommonGcNoop",
|
"${target}CommonGcNoop",
|
||||||
"${target}CommonGcStms",
|
"${target}CommonGcStms",
|
||||||
|
"${target}CommonGcCms",
|
||||||
"${target}SameThreadMsGc",
|
"${target}SameThreadMsGc",
|
||||||
|
"${target}ConcurrentMsGc",
|
||||||
"${target}NoopGc"
|
"${target}NoopGc"
|
||||||
)
|
)
|
||||||
includeRuntime()
|
includeRuntime()
|
||||||
@@ -182,6 +185,11 @@ bitcode {
|
|||||||
includeRuntime()
|
includeRuntime()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create("experimental_memory_manager_cms", file("src/mm")) {
|
||||||
|
headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp")
|
||||||
|
includeRuntime()
|
||||||
|
}
|
||||||
|
|
||||||
create("common_gc_noop", file("src/gc/common")) {
|
create("common_gc_noop", file("src/gc/common")) {
|
||||||
headersDirs += files("src/gc/noop/cpp", "src/mm/cpp")
|
headersDirs += files("src/gc/noop/cpp", "src/mm/cpp")
|
||||||
includeRuntime()
|
includeRuntime()
|
||||||
@@ -192,6 +200,11 @@ bitcode {
|
|||||||
includeRuntime()
|
includeRuntime()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create("common_gc_cms", file("src/gc/common")) {
|
||||||
|
headersDirs += files("src/gc/cms/cpp", "src/mm/cpp")
|
||||||
|
includeRuntime()
|
||||||
|
}
|
||||||
|
|
||||||
create("noop_gc", file("src/gc/noop")) {
|
create("noop_gc", file("src/gc/noop")) {
|
||||||
headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
||||||
includeRuntime()
|
includeRuntime()
|
||||||
@@ -201,6 +214,11 @@ bitcode {
|
|||||||
headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
||||||
includeRuntime()
|
includeRuntime()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create("concurrent_ms_gc", file("src/gc/cms")) {
|
||||||
|
headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
||||||
|
includeRuntime()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
targetList.forEach { targetName ->
|
targetList.forEach { targetName ->
|
||||||
@@ -272,6 +290,41 @@ targetList.forEach { targetName ->
|
|||||||
includeRuntime()
|
includeRuntime()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
allTests.addAll(createTestTasks(
|
||||||
|
project,
|
||||||
|
targetName,
|
||||||
|
"${targetName}ExperimentalMMCmsMimallocRuntimeTests",
|
||||||
|
listOf(
|
||||||
|
"${targetName}Runtime",
|
||||||
|
"${targetName}ExperimentalMemoryManagerCms",
|
||||||
|
"${targetName}CommonGcCms",
|
||||||
|
"${targetName}ConcurrentMsGc",
|
||||||
|
"${targetName}Mimalloc",
|
||||||
|
"${targetName}OptAlloc",
|
||||||
|
"${targetName}Objc"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
||||||
|
includeRuntime()
|
||||||
|
})
|
||||||
|
|
||||||
|
allTests.addAll(createTestTasks(
|
||||||
|
project,
|
||||||
|
targetName,
|
||||||
|
"${targetName}ExperimentalMMCmsStdAllocRuntimeTests",
|
||||||
|
listOf(
|
||||||
|
"${targetName}Runtime",
|
||||||
|
"${targetName}ExperimentalMemoryManagerCms",
|
||||||
|
"${targetName}CommonGcCms",
|
||||||
|
"${targetName}ConcurrentMsGc",
|
||||||
|
"${targetName}StdAlloc",
|
||||||
|
"${targetName}Objc"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp")
|
||||||
|
includeRuntime()
|
||||||
|
})
|
||||||
|
|
||||||
allTests.addAll(createTestTasks(
|
allTests.addAll(createTestTasks(
|
||||||
project,
|
project,
|
||||||
targetName,
|
targetName,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* that can be found in the LICENSE file.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SameThreadMarkAndSweep.hpp"
|
#include "ConcurrentMarkAndSweep.hpp"
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
@@ -24,55 +24,55 @@ namespace {
|
|||||||
|
|
||||||
struct MarkTraits {
|
struct MarkTraits {
|
||||||
static bool IsMarked(ObjHeader* object) noexcept {
|
static bool IsMarked(ObjHeader* object) noexcept {
|
||||||
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::NodeRef::From(object).GCObjectData();
|
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::NodeRef::From(object).GCObjectData();
|
||||||
return objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack;
|
return objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool TryMark(ObjHeader* object) noexcept {
|
static bool TryMark(ObjHeader* object) noexcept {
|
||||||
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::NodeRef::From(object).GCObjectData();
|
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::NodeRef::From(object).GCObjectData();
|
||||||
if (objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack) return false;
|
if (objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack) return false;
|
||||||
objectData.setColor(gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack);
|
objectData.setColor(gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SweepTraits {
|
struct SweepTraits {
|
||||||
using ObjectFactory = mm::ObjectFactory<gc::SameThreadMarkAndSweep>;
|
using ObjectFactory = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>;
|
||||||
using ExtraObjectsFactory = mm::ExtraObjectDataFactory;
|
using ExtraObjectsFactory = mm::ExtraObjectDataFactory;
|
||||||
|
|
||||||
static bool IsMarkedByExtraObject(mm::ExtraObjectData &object) noexcept {
|
static bool IsMarkedByExtraObject(mm::ExtraObjectData &object) noexcept {
|
||||||
auto *baseObject = object.GetBaseObject();
|
auto *baseObject = object.GetBaseObject();
|
||||||
if (!baseObject->heap()) return true;
|
if (!baseObject->heap()) return true;
|
||||||
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::NodeRef::From(baseObject).GCObjectData();
|
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::NodeRef::From(baseObject).GCObjectData();
|
||||||
return objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack;
|
return objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool TryResetMark(ObjectFactory::NodeRef node) noexcept {
|
static bool TryResetMark(ObjectFactory::NodeRef node) noexcept {
|
||||||
auto& objectData = node.GCObjectData();
|
auto& objectData = node.GCObjectData();
|
||||||
if (objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kWhite) return false;
|
if (objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kWhite) return false;
|
||||||
objectData.setColor(gc::SameThreadMarkAndSweep::ObjectData::Color::kWhite);
|
objectData.setColor(gc::ConcurrentMarkAndSweep::ObjectData::Color::kWhite);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FinalizeTraits {
|
struct FinalizeTraits {
|
||||||
using ObjectFactory = mm::ObjectFactory<gc::SameThreadMarkAndSweep>;
|
using ObjectFactory = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global, because it's accessed on a hot path: avoid memory load from `this`.
|
// Global, because it's accessed on a hot path: avoid memory load from `this`.
|
||||||
std::atomic<gc::SameThreadMarkAndSweep::SafepointFlag> gSafepointFlag = gc::SameThreadMarkAndSweep::SafepointFlag::kNone;
|
std::atomic<gc::ConcurrentMarkAndSweep::SafepointFlag> gSafepointFlag = gc::ConcurrentMarkAndSweep::SafepointFlag::kNone;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointFunctionPrologue() noexcept {
|
ALWAYS_INLINE void gc::ConcurrentMarkAndSweep::ThreadData::SafePointFunctionPrologue() noexcept {
|
||||||
SafePointRegular(GCSchedulerThreadData::kFunctionPrologueWeight);
|
SafePointRegular(GCSchedulerThreadData::kFunctionPrologueWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointLoopBody() noexcept {
|
ALWAYS_INLINE void gc::ConcurrentMarkAndSweep::ThreadData::SafePointLoopBody() noexcept {
|
||||||
SafePointRegular(GCSchedulerThreadData::kLoopBodyWeight);
|
SafePointRegular(GCSchedulerThreadData::kLoopBodyWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::SameThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) noexcept {
|
void gc::ConcurrentMarkAndSweep::ThreadData::SafePointAllocation(size_t size) noexcept {
|
||||||
threadData_.gcScheduler().OnSafePointAllocation(size);
|
threadData_.gcScheduler().OnSafePointAllocation(size);
|
||||||
SafepointFlag flag = gSafepointFlag.load();
|
SafepointFlag flag = gSafepointFlag.load();
|
||||||
if (flag != SafepointFlag::kNone) {
|
if (flag != SafepointFlag::kNone) {
|
||||||
@@ -80,7 +80,7 @@ void gc::SameThreadMarkAndSweep::ThreadData::SafePointAllocation(size_t size) no
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::SameThreadMarkAndSweep::ThreadData::PerformFullGC() noexcept {
|
void gc::ConcurrentMarkAndSweep::ThreadData::PerformFullGC() noexcept {
|
||||||
auto didGC = gc_.PerformFullGC();
|
auto didGC = gc_.PerformFullGC();
|
||||||
|
|
||||||
if (!didGC) {
|
if (!didGC) {
|
||||||
@@ -89,12 +89,12 @@ void gc::SameThreadMarkAndSweep::ThreadData::PerformFullGC() noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::SameThreadMarkAndSweep::ThreadData::OnOOM(size_t size) noexcept {
|
void gc::ConcurrentMarkAndSweep::ThreadData::OnOOM(size_t size) noexcept {
|
||||||
RuntimeLogDebug({kTagGC}, "Attempt to GC on OOM at size=%zu", size);
|
RuntimeLogDebug({kTagGC}, "Attempt to GC on OOM at size=%zu", size);
|
||||||
PerformFullGC();
|
PerformFullGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointRegular(size_t weight) noexcept {
|
ALWAYS_INLINE void gc::ConcurrentMarkAndSweep::ThreadData::SafePointRegular(size_t weight) noexcept {
|
||||||
threadData_.gcScheduler().OnSafePointRegular(weight);
|
threadData_.gcScheduler().OnSafePointRegular(weight);
|
||||||
SafepointFlag flag = gSafepointFlag.load();
|
SafepointFlag flag = gSafepointFlag.load();
|
||||||
if (flag != SafepointFlag::kNone) {
|
if (flag != SafepointFlag::kNone) {
|
||||||
@@ -102,7 +102,7 @@ ALWAYS_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointRegular(size
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NO_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointSlowPath(SafepointFlag flag) noexcept {
|
NO_INLINE void gc::ConcurrentMarkAndSweep::ThreadData::SafePointSlowPath(SafepointFlag flag) noexcept {
|
||||||
RuntimeAssert(flag != SafepointFlag::kNone, "Must've been handled by the caller");
|
RuntimeAssert(flag != SafepointFlag::kNone, "Must've been handled by the caller");
|
||||||
// No need to check for kNeedsSuspend, because `suspendIfRequested` checks for its own atomic.
|
// No need to check for kNeedsSuspend, because `suspendIfRequested` checks for its own atomic.
|
||||||
threadData_.suspensionData().suspendIfRequested();
|
threadData_.suspensionData().suspendIfRequested();
|
||||||
@@ -112,14 +112,14 @@ NO_INLINE void gc::SameThreadMarkAndSweep::ThreadData::SafePointSlowPath(Safepoi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep() noexcept {
|
gc::ConcurrentMarkAndSweep::ConcurrentMarkAndSweep() noexcept {
|
||||||
mm::GlobalData::Instance().gcScheduler().SetScheduleGC([]() {
|
mm::GlobalData::Instance().gcScheduler().SetScheduleGC([]() {
|
||||||
RuntimeLogDebug({kTagGC}, "Scheduling GC by thread %d", konan::currentThreadId());
|
RuntimeLogDebug({kTagGC}, "Scheduling GC by thread %d", konan::currentThreadId());
|
||||||
gSafepointFlag = SafepointFlag::kNeedsGC;
|
gSafepointFlag = SafepointFlag::kNeedsGC;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept {
|
bool gc::ConcurrentMarkAndSweep::PerformFullGC() noexcept {
|
||||||
RuntimeLogDebug({kTagGC}, "Attempt to suspend threads by thread %d", konan::currentThreadId());
|
RuntimeLogDebug({kTagGC}, "Attempt to suspend threads by thread %d", konan::currentThreadId());
|
||||||
auto timeStartUs = konan::getTimeMicros();
|
auto timeStartUs = konan::getTimeMicros();
|
||||||
bool didSuspend = mm::RequestThreadsSuspension();
|
bool didSuspend = mm::RequestThreadsSuspension();
|
||||||
@@ -132,7 +132,7 @@ bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept {
|
|||||||
RuntimeLogDebug({kTagGC}, "Requested thread suspension by thread %d", konan::currentThreadId());
|
RuntimeLogDebug({kTagGC}, "Requested thread suspension by thread %d", konan::currentThreadId());
|
||||||
gSafepointFlag = SafepointFlag::kNeedsSuspend;
|
gSafepointFlag = SafepointFlag::kNeedsSuspend;
|
||||||
|
|
||||||
mm::ObjectFactory<gc::SameThreadMarkAndSweep>::FinalizerQueue finalizerQueue;
|
mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::FinalizerQueue finalizerQueue;
|
||||||
{
|
{
|
||||||
// Switch state to native to simulate this thread being a GC thread.
|
// Switch state to native to simulate this thread being a GC thread.
|
||||||
ThreadStateGuard guard(ThreadState::kNative);
|
ThreadStateGuard guard(ThreadState::kNative);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class ThreadData;
|
|||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
// Stop-the-world Mark-and-Sweep that runs on mutator threads. Can support targets that do not have threads.
|
// Stop-the-world Mark-and-Sweep that runs on mutator threads. Can support targets that do not have threads.
|
||||||
class SameThreadMarkAndSweep : private Pinned {
|
class ConcurrentMarkAndSweep : private Pinned {
|
||||||
public:
|
public:
|
||||||
enum class SafepointFlag {
|
enum class SafepointFlag {
|
||||||
kNone,
|
kNone,
|
||||||
@@ -47,10 +47,10 @@ public:
|
|||||||
|
|
||||||
class ThreadData : private Pinned {
|
class ThreadData : private Pinned {
|
||||||
public:
|
public:
|
||||||
using ObjectData = SameThreadMarkAndSweep::ObjectData;
|
using ObjectData = ConcurrentMarkAndSweep::ObjectData;
|
||||||
using Allocator = AllocatorWithGC<AlignedAllocator, ThreadData>;
|
using Allocator = AllocatorWithGC<AlignedAllocator, ThreadData>;
|
||||||
|
|
||||||
explicit ThreadData(SameThreadMarkAndSweep& gc, mm::ThreadData& threadData) noexcept : gc_(gc), threadData_(threadData) {}
|
explicit ThreadData(ConcurrentMarkAndSweep& gc, mm::ThreadData& threadData) noexcept : gc_(gc), threadData_(threadData) {}
|
||||||
~ThreadData() = default;
|
~ThreadData() = default;
|
||||||
|
|
||||||
void SafePointFunctionPrologue() noexcept;
|
void SafePointFunctionPrologue() noexcept;
|
||||||
@@ -68,14 +68,14 @@ public:
|
|||||||
void SafePointRegular(size_t weight) noexcept;
|
void SafePointRegular(size_t weight) noexcept;
|
||||||
void SafePointSlowPath(SafepointFlag flag) noexcept;
|
void SafePointSlowPath(SafepointFlag flag) noexcept;
|
||||||
|
|
||||||
SameThreadMarkAndSweep& gc_;
|
ConcurrentMarkAndSweep& gc_;
|
||||||
mm::ThreadData& threadData_;
|
mm::ThreadData& threadData_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Allocator = ThreadData::Allocator;
|
using Allocator = ThreadData::Allocator;
|
||||||
|
|
||||||
SameThreadMarkAndSweep() noexcept;
|
ConcurrentMarkAndSweep() noexcept;
|
||||||
~SameThreadMarkAndSweep() = default;
|
~ConcurrentMarkAndSweep() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns `true` if GC has happened, and `false` if not (because someone else has suspended the threads).
|
// Returns `true` if GC has happened, and `false` if not (because someone else has suspended the threads).
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* that can be found in the LICENSE file.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SameThreadMarkAndSweep.hpp"
|
#include "ConcurrentMarkAndSweep.hpp"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <future>
|
#include <future>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
using namespace kotlin;
|
using namespace kotlin;
|
||||||
|
|
||||||
// These tests can only work if `GC` is `SameThreadMarkAndSweep`.
|
// These tests can only work if `GC` is `ConcurrentMarkAndSweep`.
|
||||||
// TODO: Extracting GC into a separate module will help with this.
|
// TODO: Extracting GC into a separate module will help with this.
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -197,10 +197,10 @@ KStdVector<ObjHeader*> Alive(mm::ThreadData& threadData) {
|
|||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
using Color = gc::SameThreadMarkAndSweep::ObjectData::Color;
|
using Color = gc::ConcurrentMarkAndSweep::ObjectData::Color;
|
||||||
|
|
||||||
Color GetColor(ObjHeader* objHeader) {
|
Color GetColor(ObjHeader* objHeader) {
|
||||||
auto nodeRef = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::NodeRef::From(objHeader);
|
auto nodeRef = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::NodeRef::From(objHeader);
|
||||||
return nodeRef.GCObjectData().color();
|
return nodeRef.GCObjectData().color();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ WeakCounter& InstallWeakCounter(mm::ThreadData& threadData, ObjHeader* objHeader
|
|||||||
return weakCounter;
|
return weakCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SameThreadMarkAndSweepTest : public testing::Test {
|
class ConcurrentMarkAndSweepTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~ConcurrentMarkAndSweepTest() {
|
~ConcurrentMarkAndSweepTest() {
|
||||||
@@ -231,7 +231,7 @@ private:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, RootSet) {
|
TEST_F(ConcurrentMarkAndSweepTest, RootSet) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global1{threadData};
|
GlobalObjectHolder global1{threadData};
|
||||||
GlobalObjectArrayHolder global2{threadData};
|
GlobalObjectArrayHolder global2{threadData};
|
||||||
@@ -266,7 +266,7 @@ TEST_F(SameThreadMarkAndSweepTest, RootSet) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, InterconnectedRootSet) {
|
TEST_F(ConcurrentMarkAndSweepTest, InterconnectedRootSet) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global1{threadData};
|
GlobalObjectHolder global1{threadData};
|
||||||
GlobalObjectArrayHolder global2{threadData};
|
GlobalObjectArrayHolder global2{threadData};
|
||||||
@@ -312,7 +312,7 @@ TEST_F(SameThreadMarkAndSweepTest, InterconnectedRootSet) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, FreeObjects) {
|
TEST_F(ConcurrentMarkAndSweepTest, FreeObjects) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
auto& object1 = AllocateObject(threadData);
|
auto& object1 = AllocateObject(threadData);
|
||||||
auto& object2 = AllocateObject(threadData);
|
auto& object2 = AllocateObject(threadData);
|
||||||
@@ -327,7 +327,7 @@ TEST_F(SameThreadMarkAndSweepTest, FreeObjects) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, FreeObjectsWithFinalizers) {
|
TEST_F(ConcurrentMarkAndSweepTest, FreeObjectsWithFinalizers) {
|
||||||
RunInNewThread([this](mm::ThreadData& threadData) {
|
RunInNewThread([this](mm::ThreadData& threadData) {
|
||||||
auto& object1 = AllocateObjectWithFinalizer(threadData);
|
auto& object1 = AllocateObjectWithFinalizer(threadData);
|
||||||
auto& object2 = AllocateObjectWithFinalizer(threadData);
|
auto& object2 = AllocateObjectWithFinalizer(threadData);
|
||||||
@@ -344,7 +344,7 @@ TEST_F(SameThreadMarkAndSweepTest, FreeObjectsWithFinalizers) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithFreeWeak) {
|
TEST_F(ConcurrentMarkAndSweepTest, FreeObjectWithFreeWeak) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
auto& object1 = AllocateObject(threadData);
|
auto& object1 = AllocateObject(threadData);
|
||||||
auto& weak1 = ([&threadData, &object1]() -> WeakCounter& {
|
auto& weak1 = ([&threadData, &object1]() -> WeakCounter& {
|
||||||
@@ -363,7 +363,7 @@ TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithFreeWeak) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithHoldedWeak) {
|
TEST_F(ConcurrentMarkAndSweepTest, FreeObjectWithHoldedWeak) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
auto& object1 = AllocateObject(threadData);
|
auto& object1 = AllocateObject(threadData);
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -382,7 +382,7 @@ TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithHoldedWeak) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, ObjectReferencedFromRootSet) {
|
TEST_F(ConcurrentMarkAndSweepTest, ObjectReferencedFromRootSet) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -422,7 +422,7 @@ TEST_F(SameThreadMarkAndSweepTest, ObjectReferencedFromRootSet) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCycles) {
|
TEST_F(ConcurrentMarkAndSweepTest, ObjectsWithCycles) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -471,7 +471,7 @@ TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCycles) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCyclesAndFinalizers) {
|
TEST_F(ConcurrentMarkAndSweepTest, ObjectsWithCyclesAndFinalizers) {
|
||||||
RunInNewThread([this](mm::ThreadData& threadData) {
|
RunInNewThread([this](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -522,7 +522,7 @@ TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCyclesAndFinalizers) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCyclesIntoRootSet) {
|
TEST_F(ConcurrentMarkAndSweepTest, ObjectsWithCyclesIntoRootSet) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -550,7 +550,7 @@ TEST_F(SameThreadMarkAndSweepTest, ObjectsWithCyclesIntoRootSet) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, RunGCTwice) {
|
TEST_F(ConcurrentMarkAndSweepTest, RunGCTwice) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack{threadData};
|
StackObjectHolder stack{threadData};
|
||||||
@@ -600,7 +600,7 @@ TEST_F(SameThreadMarkAndSweepTest, RunGCTwice) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, PermanentObjects) {
|
TEST_F(ConcurrentMarkAndSweepTest, PermanentObjects) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalPermanentObjectHolder global1{threadData};
|
GlobalPermanentObjectHolder global1{threadData};
|
||||||
GlobalObjectHolder global2{threadData};
|
GlobalObjectHolder global2{threadData};
|
||||||
@@ -622,7 +622,7 @@ TEST_F(SameThreadMarkAndSweepTest, PermanentObjects) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, SameObjectInRootSet) {
|
TEST_F(ConcurrentMarkAndSweepTest, SameObjectInRootSet) {
|
||||||
RunInNewThread([](mm::ThreadData& threadData) {
|
RunInNewThread([](mm::ThreadData& threadData) {
|
||||||
GlobalObjectHolder global{threadData};
|
GlobalObjectHolder global{threadData};
|
||||||
StackObjectHolder stack(*global);
|
StackObjectHolder stack(*global);
|
||||||
@@ -746,7 +746,7 @@ private:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
|
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsCollect) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
||||||
@@ -802,7 +802,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsCollect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
|
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAllCollect) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
||||||
@@ -852,7 +852,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAllCollect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRequested) {
|
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRequested) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
||||||
@@ -924,7 +924,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsAddToRootSetAfterCollectionRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
|
TEST_F(ConcurrentMarkAndSweepTest, CrossThreadReference) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> globals(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
KStdVector<ObjHeader*> locals(kDefaultThreadCount);
|
||||||
@@ -990,7 +990,7 @@ TEST_F(SameThreadMarkAndSweepTest, CrossThreadReference) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
|
TEST_F(ConcurrentMarkAndSweepTest, MultipleMutatorsWeaks) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
ObjHeader* globalRoot = nullptr;
|
ObjHeader* globalRoot = nullptr;
|
||||||
WeakCounter* weak = nullptr;
|
WeakCounter* weak = nullptr;
|
||||||
@@ -1042,7 +1042,7 @@ TEST_F(SameThreadMarkAndSweepTest, MultipleMutatorsWeaks) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
|
TEST_F(ConcurrentMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
|
||||||
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
KStdVector<Mutator> mutators(kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> globals(2 * kDefaultThreadCount);
|
KStdVector<ObjHeader*> globals(2 * kDefaultThreadCount);
|
||||||
KStdVector<ObjHeader*> locals(2 * kDefaultThreadCount);
|
KStdVector<ObjHeader*> locals(2 * kDefaultThreadCount);
|
||||||
@@ -1124,7 +1124,7 @@ TEST_F(SameThreadMarkAndSweepTest, NewThreadsWhileRequestingCollection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(SameThreadMarkAndSweepTest, FreeObjectWithFreeWeakReversedOrder) {
|
TEST_F(ConcurrentMarkAndSweepTest, FreeObjectWithFreeWeakReversedOrder) {
|
||||||
KStdVector<Mutator> mutators(2);
|
KStdVector<Mutator> mutators(2);
|
||||||
std::atomic<test_support::Object<Payload>*> object1 = nullptr;
|
std::atomic<test_support::Object<Payload>*> object1 = nullptr;
|
||||||
std::atomic<WeakCounter*> weak = nullptr;
|
std::atomic<WeakCounter*> weak = nullptr;
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SameThreadMarkAndSweep.hpp"
|
#include "ConcurrentMarkAndSweep.hpp"
|
||||||
|
|
||||||
namespace kotlin {
|
namespace kotlin {
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
using GC = kotlin::gc::SameThreadMarkAndSweep;
|
using GC = kotlin::gc::ConcurrentMarkAndSweep;
|
||||||
|
|
||||||
inline constexpr bool kSupportsMultipleMutators = true;
|
inline constexpr bool kSupportsMultipleMutators = true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user