Misc changes for GC in new MM (#4699)

This commit is contained in:
Alexander Shabalin
2021-02-12 14:45:45 +03:00
committed by Vasily Levchenko
parent f7af8bc763
commit 97262c273f
10 changed files with 166 additions and 83 deletions
@@ -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