Misc changes for GC in new MM (#4699)
This commit is contained in:
committed by
Vasily Levchenko
parent
f7af8bc763
commit
97262c273f
@@ -2396,6 +2396,11 @@ task hash_map0(type: KonanLocalTest) {
|
||||
source = "runtime/collections/hash_map0.kt"
|
||||
}
|
||||
|
||||
task hash_map1(type: KonanLocalTest) {
|
||||
goldValue = "OK\n"
|
||||
source = "runtime/collections/hash_map1.kt"
|
||||
}
|
||||
|
||||
task hash_set0(type: KonanLocalTest) {
|
||||
goldValue = "OK\n"
|
||||
source = "runtime/collections/hash_set0.kt"
|
||||
|
||||
@@ -94,58 +94,6 @@ fun testBasic() {
|
||||
assertEquals(0, m.size)
|
||||
}
|
||||
|
||||
fun testRehashAndCompact() {
|
||||
val m = HashMap<String, String>()
|
||||
for (repeat in 1..10) {
|
||||
val n = when (repeat) {
|
||||
1 -> 1000
|
||||
2 -> 10000
|
||||
3 -> 10
|
||||
else -> 100000
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(null, m.put(i.toString(), "val$i"))
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
assertEquals(i, m.size)
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertEquals("val$i", m.remove(i.toString()))
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(n - i, m.size)
|
||||
}
|
||||
assertTrue(m.isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
fun testClear() {
|
||||
val m = HashMap<String, String>()
|
||||
for (repeat in 1..10) {
|
||||
val n = when (repeat) {
|
||||
1 -> 1000
|
||||
2 -> 10000
|
||||
3 -> 10
|
||||
else -> 100000
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(null, m.put(i.toString(), "val$i"))
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
assertEquals(i, m.size)
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
}
|
||||
m.clear()
|
||||
assertEquals(0, m.size)
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun testEquals() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
@@ -257,8 +205,6 @@ fun testEntriesIteratorSet() {
|
||||
|
||||
@Test fun runTest() {
|
||||
testBasic()
|
||||
testRehashAndCompact()
|
||||
testClear()
|
||||
testEquals()
|
||||
testHashCode()
|
||||
testToString()
|
||||
@@ -272,4 +218,4 @@ fun testEntriesIteratorSet() {
|
||||
testEntriesIteratorSet()
|
||||
//testDegenerateKeys()
|
||||
println("OK")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package runtime.collections.hash_map1
|
||||
|
||||
import kotlin.native.MemoryModel
|
||||
import kotlin.native.Platform
|
||||
import kotlin.native.internal.GC
|
||||
import kotlin.test.*
|
||||
|
||||
fun assertTrue(cond: Boolean) {
|
||||
if (!cond)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertFalse(cond: Boolean) {
|
||||
if (cond)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: Any?, value2: Any?) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertNotEquals(value1: Any?, value2: Any?) {
|
||||
if (value1 == value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: Int, value2: Int) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun testRehashAndCompact() {
|
||||
val m = HashMap<String, String>()
|
||||
for (repeat in 1..10) {
|
||||
val n = when (repeat) {
|
||||
1 -> 1000
|
||||
2 -> 10000
|
||||
3 -> 10
|
||||
else -> 100000
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(null, m.put(i.toString(), "val$i"))
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
assertEquals(i, m.size)
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertEquals("val$i", m.remove(i.toString()))
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(n - i, m.size)
|
||||
}
|
||||
assertTrue(m.isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
fun testClear() {
|
||||
val m = HashMap<String, String>()
|
||||
for (repeat in 1..10) {
|
||||
val n = when (repeat) {
|
||||
1 -> 1000
|
||||
2 -> 10000
|
||||
3 -> 10
|
||||
else -> 100000
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
assertEquals(null, m.put(i.toString(), "val$i"))
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
assertEquals(i, m.size)
|
||||
}
|
||||
for (i in 1..n) {
|
||||
assertTrue(m.containsKey(i.toString()))
|
||||
}
|
||||
m.clear()
|
||||
assertEquals(0, m.size)
|
||||
for (i in 1..n) {
|
||||
assertFalse(m.containsKey(i.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun runTest() {
|
||||
// TODO: Do not manually control this.
|
||||
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
||||
GC.threshold = 1000000
|
||||
GC.thresholdAllocations = 1000000
|
||||
}
|
||||
testRehashAndCompact()
|
||||
testClear()
|
||||
println("OK")
|
||||
}
|
||||
@@ -71,6 +71,11 @@ public:
|
||||
owner_.deletionQueue_.splice(owner_.deletionQueue_.end(), deletionQueue_);
|
||||
}
|
||||
|
||||
void ClearForTests() noexcept {
|
||||
queue_.clear();
|
||||
deletionQueue_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
MultiSourceQueue& owner_; // weak
|
||||
KStdList<Node> queue_;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
using namespace kotlin;
|
||||
|
||||
mm::GlobalData::GlobalData() = default;
|
||||
mm::GlobalData::~GlobalData() = default;
|
||||
|
||||
// static
|
||||
mm::GlobalData mm::GlobalData::instance_;
|
||||
mm::GlobalData mm::GlobalData::instance_ [[clang::no_destroy]];
|
||||
|
||||
@@ -29,8 +29,9 @@ public:
|
||||
|
||||
private:
|
||||
GlobalData();
|
||||
~GlobalData();
|
||||
~GlobalData() = delete;
|
||||
|
||||
// This `GlobalData` is never destroyed.
|
||||
static GlobalData instance_;
|
||||
|
||||
ThreadRegistry threadRegistry_;
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
// Make sure to clean everything allocated by the tests.
|
||||
for (auto& threadData : threadDatas_) {
|
||||
threadData->objectFactoryThreadQueue().ClearForTests();
|
||||
threadData->globalsThreadQueue().ClearForTests();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,6 +263,48 @@ extern "C" void Kotlin_native_internal_GC_collectCyclic(ObjHeader*) {
|
||||
ThrowIllegalArgumentException();
|
||||
}
|
||||
|
||||
extern "C" void Kotlin_native_internal_GC_setThreshold(ObjHeader*, int32_t value) {
|
||||
if (value < 0) {
|
||||
ThrowIllegalArgumentException();
|
||||
}
|
||||
mm::GlobalData::Instance().gc().SetThreshold(static_cast<size_t>(value));
|
||||
}
|
||||
|
||||
extern "C" int32_t Kotlin_native_internal_GC_getThreshold(ObjHeader*) {
|
||||
auto threshold = mm::GlobalData::Instance().gc().GetThreshold();
|
||||
auto maxValue = std::numeric_limits<int32_t>::max();
|
||||
if (threshold > static_cast<size_t>(maxValue)) {
|
||||
return maxValue;
|
||||
}
|
||||
return static_cast<int32_t>(maxValue);
|
||||
}
|
||||
|
||||
extern "C" void Kotlin_native_internal_GC_setCollectCyclesThreshold(ObjHeader*, int64_t value) {
|
||||
// TODO: Remove when legacy MM is gone.
|
||||
ThrowIllegalArgumentException();
|
||||
}
|
||||
|
||||
extern "C" int64_t Kotlin_native_internal_GC_getCollectCyclesThreshold(ObjHeader*) {
|
||||
// TODO: Remove when legacy MM is gone.
|
||||
ThrowIllegalArgumentException();
|
||||
}
|
||||
|
||||
extern "C" void Kotlin_native_internal_GC_setThresholdAllocations(ObjHeader*, int64_t value) {
|
||||
if (value < 0) {
|
||||
ThrowIllegalArgumentException();
|
||||
}
|
||||
mm::GlobalData::Instance().gc().SetAllocationThresholdBytes(static_cast<size_t>(value));
|
||||
}
|
||||
|
||||
extern "C" int64_t Kotlin_native_internal_GC_getThresholdAllocations(ObjHeader*) {
|
||||
auto threshold = mm::GlobalData::Instance().gc().GetAllocationThresholdBytes();
|
||||
auto maxValue = std::numeric_limits<int64_t>::max();
|
||||
if (threshold > static_cast<size_t>(maxValue)) {
|
||||
return maxValue;
|
||||
}
|
||||
return static_cast<int64_t>(maxValue);
|
||||
}
|
||||
|
||||
extern "C" OBJ_GETTER(Kotlin_native_internal_GC_detectCycles, ObjHeader*) {
|
||||
// TODO: Remove when legacy MM is gone.
|
||||
RETURN_OBJ(nullptr);
|
||||
|
||||
@@ -42,30 +42,6 @@ void Kotlin_native_internal_GC_start(ObjHeader*) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
void Kotlin_native_internal_GC_setThreshold(ObjHeader*, int32_t value) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
int32_t Kotlin_native_internal_GC_getThreshold(ObjHeader*) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
void Kotlin_native_internal_GC_setCollectCyclesThreshold(ObjHeader*, int64_t value) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
int64_t Kotlin_native_internal_GC_getCollectCyclesThreshold(ObjHeader*) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
void Kotlin_native_internal_GC_setThresholdAllocations(ObjHeader*, int64_t value) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
int64_t Kotlin_native_internal_GC_getThresholdAllocations(ObjHeader*) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
void Kotlin_native_internal_GC_setTuneThreshold(ObjHeader*, int32_t value) {
|
||||
TODO();
|
||||
}
|
||||
|
||||
@@ -38,10 +38,18 @@ public:
|
||||
private:
|
||||
};
|
||||
|
||||
NoOpGC() noexcept = default;
|
||||
NoOpGC() noexcept {}
|
||||
~NoOpGC() = default;
|
||||
|
||||
void SetThreshold(size_t value) noexcept { threshold_ = value; }
|
||||
size_t GetThreshold() noexcept { return threshold_; }
|
||||
|
||||
void SetAllocationThresholdBytes(size_t value) noexcept { allocationThresholdBytes_ = value; }
|
||||
size_t GetAllocationThresholdBytes() noexcept { return allocationThresholdBytes_; }
|
||||
|
||||
private:
|
||||
size_t threshold_ = 0;
|
||||
size_t allocationThresholdBytes_ = 0;
|
||||
};
|
||||
|
||||
} // namespace mm
|
||||
|
||||
Reference in New Issue
Block a user