[K/N] Move kotlin.native.internal.GC into kotlin.native.runtime
As a part of efforts to stabilize Native stdlib #KT-55765.
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("UNUSED")
|
@file:Suppress("UNUSED")
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package stdlib
|
package stdlib
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ data class TripleVars<T>(var first: T, var second: T, var third: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun gc() = kotlin.native.internal.GC.collect()
|
fun gc() = kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
// Note: this method checks only some of the operations (namely the ones modified recently,
|
// Note: this method checks only some of the operations (namely the ones modified recently,
|
||||||
// and thus required additional tests).
|
// and thus required additional tests).
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(ExperimentalStdlibApi::class)
|
@file:OptIn(ExperimentalStdlibApi::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.internal.*
|
import kotlin.native.internal.*
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
fun ensureInitialized() {}
|
fun ensureInitialized() {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kt44283.*
|
import kt44283.*
|
||||||
import kotlin.native.concurrent.AtomicInt
|
import kotlin.native.concurrent.AtomicInt
|
||||||
@@ -7,7 +9,7 @@ val callbackCounter = AtomicInt(0)
|
|||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val func = staticCFunction<CValue<TestStruct>, Unit> {
|
val func = staticCFunction<CValue<TestStruct>, Unit> {
|
||||||
kotlin.native.internal.GC.collect() // Helps to ensure that "runtime" is already initialized.
|
kotlin.native.runtime.GC.collect() // Helps to ensure that "runtime" is already initialized.
|
||||||
|
|
||||||
memScoped {
|
memScoped {
|
||||||
println("Hello, Kotlin/Native! ${it.ptr.pointed.d}")
|
println("Hello, Kotlin/Native! ${it.ptr.pointed.d}")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2018 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import objcSmoke.*
|
import objcSmoke.*
|
||||||
@@ -204,7 +205,7 @@ fun testCustomRetain() {
|
|||||||
|
|
||||||
autoreleasepool {
|
autoreleasepool {
|
||||||
test()
|
test()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse(unexpectedDeallocation)
|
assertFalse(unexpectedDeallocation)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2018 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import objcSmoke.*
|
import objcSmoke.*
|
||||||
@@ -204,7 +205,7 @@ fun testCustomRetain() {
|
|||||||
|
|
||||||
autoreleasepool {
|
autoreleasepool {
|
||||||
test()
|
test()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse(unexpectedDeallocation)
|
assertFalse(unexpectedDeallocation)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
import objcTests.*
|
import objcTests.*
|
||||||
@@ -13,7 +15,7 @@ import objcTests.*
|
|||||||
}
|
}
|
||||||
|
|
||||||
test()
|
test()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertTrue(customStringDeallocated)
|
assertTrue(customStringDeallocated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
@@ -9,7 +11,7 @@ import objcTests.*
|
|||||||
@Test
|
@Test
|
||||||
fun testKT41811() {
|
fun testKT41811() {
|
||||||
// Attempt to make the state predictable:
|
// Attempt to make the state predictable:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
deallocRetainReleaseDeallocated = false
|
deallocRetainReleaseDeallocated = false
|
||||||
assertFalse(deallocRetainReleaseDeallocated)
|
assertFalse(deallocRetainReleaseDeallocated)
|
||||||
@@ -17,12 +19,12 @@ fun testKT41811() {
|
|||||||
createGarbageDeallocRetainRelease()
|
createGarbageDeallocRetainRelease()
|
||||||
|
|
||||||
// Runs [DeallocRetainRelease dealloc]:
|
// Runs [DeallocRetainRelease dealloc]:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(deallocRetainReleaseDeallocated)
|
assertTrue(deallocRetainReleaseDeallocated)
|
||||||
|
|
||||||
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createGarbageDeallocRetainRelease() {
|
private fun createGarbageDeallocRetainRelease() {
|
||||||
@@ -55,7 +57,7 @@ fun testKT41811LoadKotlinWeak() {
|
|||||||
|
|
||||||
private fun testKT41811LoadWeak(weakRef: WeakReferenceProtocol) {
|
private fun testKT41811LoadWeak(weakRef: WeakReferenceProtocol) {
|
||||||
// Attempt to make the state predictable:
|
// Attempt to make the state predictable:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
deallocLoadWeakDeallocated = false
|
deallocLoadWeakDeallocated = false
|
||||||
assertFalse(deallocLoadWeakDeallocated)
|
assertFalse(deallocLoadWeakDeallocated)
|
||||||
@@ -63,12 +65,12 @@ private fun testKT41811LoadWeak(weakRef: WeakReferenceProtocol) {
|
|||||||
createGarbageDeallocLoadWeak(weakRef)
|
createGarbageDeallocLoadWeak(weakRef)
|
||||||
|
|
||||||
// Runs [DeallocLoadWeak dealloc]:
|
// Runs [DeallocLoadWeak dealloc]:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(deallocLoadWeakDeallocated)
|
assertTrue(deallocLoadWeakDeallocated)
|
||||||
|
|
||||||
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
weakDeallocLoadWeak = null
|
weakDeallocLoadWeak = null
|
||||||
}
|
}
|
||||||
@@ -85,7 +87,7 @@ private fun createGarbageDeallocLoadWeak(weakRef: WeakReferenceProtocol) {
|
|||||||
@Test
|
@Test
|
||||||
fun testKT41811WithGlobal() {
|
fun testKT41811WithGlobal() {
|
||||||
// Attempt to make the state predictable:
|
// Attempt to make the state predictable:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
deallocRetainReleaseDeallocated = false
|
deallocRetainReleaseDeallocated = false
|
||||||
assertFalse(deallocRetainReleaseDeallocated)
|
assertFalse(deallocRetainReleaseDeallocated)
|
||||||
@@ -99,7 +101,7 @@ fun testKT41811WithGlobal() {
|
|||||||
assertFalse(deallocRetainReleaseDeallocated)
|
assertFalse(deallocRetainReleaseDeallocated)
|
||||||
|
|
||||||
// Clean up local DeallocRetainRelease on Kotlin side
|
// Clean up local DeallocRetainRelease on Kotlin side
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertFalse(deallocRetainReleaseDeallocated)
|
assertFalse(deallocRetainReleaseDeallocated)
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ fun testKT41811WithGlobal() {
|
|||||||
// on ObjC side, which triggers `retain` and `release` of `self`. If these messages
|
// on ObjC side, which triggers `retain` and `release` of `self`. If these messages
|
||||||
// were to reach Kotlin side, the `release` would have immediately scheduled the
|
// were to reach Kotlin side, the `release` would have immediately scheduled the
|
||||||
// second disposal of Kotlin object.
|
// second disposal of Kotlin object.
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(deallocRetainReleaseDeallocated)
|
assertTrue(deallocRetainReleaseDeallocated)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
@@ -6,7 +8,7 @@ import objcTests.*
|
|||||||
@Test
|
@Test
|
||||||
fun testKT42482() {
|
fun testKT42482() {
|
||||||
// Attempt to make the state predictable:
|
// Attempt to make the state predictable:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
kt42482Deallocated = false
|
kt42482Deallocated = false
|
||||||
assertFalse(kt42482Deallocated);
|
assertFalse(kt42482Deallocated);
|
||||||
@@ -25,7 +27,7 @@ fun testKT42482() {
|
|||||||
kt42482Global = null
|
kt42482Global = null
|
||||||
}()
|
}()
|
||||||
|
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(kt42482Deallocated)
|
assertTrue(kt42482Deallocated)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@file:OptIn(FreezingIsDeprecated::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
@@ -16,7 +16,7 @@ import objcTests.*
|
|||||||
testObjCWeakRef0(deallocListener)
|
testObjCWeakRef0(deallocListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertTrue(deallocListener.deallocated)
|
assertTrue(deallocListener.deallocated)
|
||||||
assertTrue(deallocListener.deallocExecutorIsNil())
|
assertTrue(deallocListener.deallocExecutorIsNil())
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,6 @@ private fun testObjCWeakRef0(deallocListener: DeallocListener) = withWorker {
|
|||||||
assertFalse(deallocListener.deallocExecutorIsNil())
|
assertFalse(deallocListener.deallocExecutorIsNil())
|
||||||
}
|
}
|
||||||
// Process release of Kotlin reference to [obj] in any case:
|
// Process release of Kotlin reference to [obj] in any case:
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
import objcTests.*
|
import objcTests.*
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTryRetainGC() {
|
fun testTryRetainGC() {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
val weakRefHolder = WeakRefHolder()
|
val weakRefHolder = WeakRefHolder()
|
||||||
createGarbageNSObjects(weakRefHolder)
|
createGarbageNSObjects(weakRefHolder)
|
||||||
weakRefHolder.obj = object : NSObject() {}
|
weakRefHolder.obj = object : NSObject() {}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.ref.*
|
import kotlin.native.ref.*
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
@@ -16,7 +18,7 @@ private fun testWeakReference(block: () -> NSObject) {
|
|||||||
createAndTestWeakReference(block)
|
createAndTestWeakReference(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertNull(ref.get())
|
assertNull(ref.get())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package coroutines
|
package coroutines
|
||||||
|
|
||||||
@@ -243,4 +244,4 @@ fun createCoroutineUninterceptedAndResume(fn: suspend () -> Any?, resultHolder:
|
|||||||
fun createCoroutineUninterceptedAndResume(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
|
fun createCoroutineUninterceptedAndResume(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
|
||||||
fn.createCoroutine(receiver, ResultHolderCompletion(resultHolder)).resume(Unit)
|
fn.createCoroutine(receiver, ResultHolderCompletion(resultHolder)).resume(Unit)
|
||||||
|
|
||||||
fun gc() = kotlin.native.internal.GC.collect()
|
fun gc() = kotlin.native.runtime.GC.collect()
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ package deallocretain
|
|||||||
|
|
||||||
open class DeallocRetainBase
|
open class DeallocRetainBase
|
||||||
|
|
||||||
fun garbageCollect() = kotlin.native.internal.GC.collect()
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
fun garbageCollect() = kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
fun createWeakReference(value: Any) = kotlin.native.ref.WeakReference(value)
|
fun createWeakReference(value: Any) = kotlin.native.ref.WeakReference(value)
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ class KotlinLivenessTracker {
|
|||||||
fun objectsAreDead() = weakRefs.all { it.value === null }
|
fun objectsAreDead() = weakRefs.all { it.value === null }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun gc() = kotlin.native.internal.GC.collect()
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
fun gc() = kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
class KotlinObject
|
class KotlinObject
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
// All classes and methods should be used in tests
|
// All classes and methods should be used in tests
|
||||||
@file:Suppress("UNUSED")
|
@file:Suppress("UNUSED")
|
||||||
@file:OptIn(FreezingIsDeprecated::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package conversions
|
package conversions
|
||||||
|
|
||||||
@@ -807,7 +807,7 @@ open class TestDeprecation() {
|
|||||||
@Deprecated("warning", level = DeprecationLevel.WARNING) var warningVar: Any? = null
|
@Deprecated("warning", level = DeprecationLevel.WARNING) var warningVar: Any? = null
|
||||||
|
|
||||||
fun gc() {
|
fun gc() {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestWeakRefs(private val frozen: Boolean) {
|
class TestWeakRefs(private val frozen: Boolean) {
|
||||||
@@ -862,7 +862,7 @@ class SharedRefs {
|
|||||||
fun createFrozenCollection() = createCollection().freeze()
|
fun createFrozenCollection() = createCollection().freeze()
|
||||||
|
|
||||||
fun hasAliveObjects(): Boolean {
|
fun hasAliveObjects(): Boolean {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
return mustBeRemoved.any { it.get() != null }
|
return mustBeRemoved.any { it.get() != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(ExperimentalStdlibApi::class, FreezingIsDeprecated::class)
|
@file:OptIn(ExperimentalStdlibApi::class, FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package runtime.basic.cleaner_basic
|
package runtime.basic.cleaner_basic
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import kotlin.native.concurrent.*
|
|||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
import kotlin.native.ref.Cleaner
|
import kotlin.native.ref.Cleaner
|
||||||
import kotlin.native.ref.createCleaner
|
import kotlin.native.ref.createCleaner
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
class AtomicBoolean(initialValue: Boolean) {
|
class AtomicBoolean(initialValue: Boolean) {
|
||||||
private val impl = AtomicInt(if (initialValue) 1 else 0)
|
private val impl = AtomicInt(if (initialValue) 1 else 0)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(ExperimentalStdlibApi::class)
|
@file:OptIn(ExperimentalStdlibApi::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ import kotlin.native.concurrent.*
|
|||||||
import kotlin.native.internal.*
|
import kotlin.native.internal.*
|
||||||
import kotlin.native.ref.Cleaner
|
import kotlin.native.ref.Cleaner
|
||||||
import kotlin.native.ref.createCleaner
|
import kotlin.native.ref.createCleaner
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
@ThreadLocal
|
@ThreadLocal
|
||||||
var tlsCleaner: Cleaner? = null
|
var tlsCleaner: Cleaner? = null
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(ExperimentalStdlibApi::class, FreezingIsDeprecated::class, kotlin.experimental.ExperimentalNativeApi::class)
|
@file:OptIn(ExperimentalStdlibApi::class, FreezingIsDeprecated::class, kotlin.experimental.ExperimentalNativeApi::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package runtime.basic.cleaner_workers
|
package runtime.basic.cleaner_workers
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import kotlin.native.concurrent.*
|
|||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
import kotlin.native.ref.Cleaner
|
import kotlin.native.ref.Cleaner
|
||||||
import kotlin.native.ref.createCleaner
|
import kotlin.native.ref.createCleaner
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
class AtomicBoolean(initialValue: Boolean) {
|
class AtomicBoolean(initialValue: Boolean) {
|
||||||
private val impl = AtomicInt(if (initialValue) 1 else 0)
|
private val impl = AtomicInt(if (initialValue) 1 else 0)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package runtime.collections.hash_map1
|
|||||||
|
|
||||||
import kotlin.native.MemoryModel
|
import kotlin.native.MemoryModel
|
||||||
import kotlin.native.Platform
|
import kotlin.native.Platform
|
||||||
import kotlin.native.internal.GC
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
fun assertTrue(cond: Boolean) {
|
fun assertTrue(cond: Boolean) {
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2020 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(FreezingIsDeprecated::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package runtime.concurrent.worker_bound_reference0
|
package runtime.concurrent.worker_bound_reference0
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.internal.GC
|
|
||||||
import kotlin.native.*
|
import kotlin.native.*
|
||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
import kotlin.text.Regex
|
import kotlin.text.Regex
|
||||||
|
|
||||||
class A(var a: Int)
|
class A(var a: Int)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
import kotlin.native.Platform
|
import kotlin.native.Platform
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@@ -44,15 +46,15 @@ fun makeIt(): Holder {
|
|||||||
fun test4() {
|
fun test4() {
|
||||||
val holder = makeIt()
|
val holder = makeIt()
|
||||||
// To clean rc count coming from rememberNewContainer().
|
// To clean rc count coming from rememberNewContainer().
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
// Request cyclic collection.
|
// Request cyclic collection.
|
||||||
kotlin.native.internal.GC.collectCyclic()
|
kotlin.native.runtime.GC.collectCyclic()
|
||||||
// Ensure we processed delayed release.
|
// Ensure we processed delayed release.
|
||||||
repeat(10) {
|
repeat(10) {
|
||||||
// Wait a bit and process queue.
|
// Wait a bit and process queue.
|
||||||
Worker.current.park(10)
|
Worker.current.park(10)
|
||||||
Worker.current.processQueue()
|
Worker.current.processQueue()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
val value = @Suppress("UNCHECKED_CAST") (holder.other as? AtomicReference<Holder?>?)
|
val value = @Suppress("UNCHECKED_CAST") (holder.other as? AtomicReference<Holder?>?)
|
||||||
assertTrue(value != null)
|
assertTrue(value != null)
|
||||||
@@ -77,15 +79,15 @@ fun createHolder2() = Holder2(createRef())
|
|||||||
|
|
||||||
fun test5() {
|
fun test5() {
|
||||||
val holder = createHolder2()
|
val holder = createHolder2()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
kotlin.native.internal.GC.collectCyclic()
|
kotlin.native.runtime.GC.collectCyclic()
|
||||||
Worker.current.park(100 * 1000)
|
Worker.current.park(100 * 1000)
|
||||||
holder.switch()
|
holder.switch()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
Worker.current.park(100 * 1000)
|
Worker.current.park(100 * 1000)
|
||||||
withWorker {
|
withWorker {
|
||||||
executeAfter(0L, {
|
executeAfter(0L, {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}.freeze())
|
}.freeze())
|
||||||
}
|
}
|
||||||
Worker.current.park(1000)
|
Worker.current.park(1000)
|
||||||
@@ -109,9 +111,9 @@ fun createRoot(): AtomicReference<Any?> {
|
|||||||
|
|
||||||
fun test7() {
|
fun test7() {
|
||||||
val ref1 = createRoot()
|
val ref1 = createRoot()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
kotlin.native.internal.GC.collectCyclic()
|
kotlin.native.runtime.GC.collectCyclic()
|
||||||
Worker.current.park(500 * 1000L)
|
Worker.current.park(500 * 1000L)
|
||||||
|
|
||||||
withWorker {
|
withWorker {
|
||||||
@@ -177,7 +179,7 @@ fun test9() {
|
|||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
Platform.isMemoryLeakCheckerActive = true
|
Platform.isMemoryLeakCheckerActive = true
|
||||||
kotlin.native.internal.GC.cyclicCollectorEnabled = true
|
kotlin.native.runtime.GC.cyclicCollectorEnabled = true
|
||||||
test1()
|
test1()
|
||||||
test2()
|
test2()
|
||||||
test3()
|
test3()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.internal.GC
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
fun main() {
|
fun main() {
|
||||||
kotlin.native.internal.GC.cyclicCollectorEnabled = true
|
kotlin.native.runtime.GC.cyclicCollectorEnabled = true
|
||||||
|
|
||||||
repeat(10000) {
|
repeat(10000) {
|
||||||
// Create atomic cyclic garbage:
|
// Create atomic cyclic garbage:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
import kotlin.native.Platform
|
import kotlin.native.Platform
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,12 @@ fun createCycles(junk: Node) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
@Test fun runTest() {
|
@Test fun runTest() {
|
||||||
// Create outer link from cyclic garbage.
|
// Create outer link from cyclic garbage.
|
||||||
val outer = Node(42, null, null, null)
|
val outer = Node(42, null, null, null)
|
||||||
createCycles(outer)
|
createCycles(outer)
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
// Ensure outer is not collected.
|
// Ensure outer is not collected.
|
||||||
println(outer.data)
|
println(outer.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ package runtime.memory.cycles1
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
import kotlin.native.ref.*
|
import kotlin.native.ref.*
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
@Test fun runTest() {
|
@Test fun runTest() {
|
||||||
// TODO: make it work in relaxed model as well.
|
// TODO: make it work in relaxed model as well.
|
||||||
if (Platform.memoryModel == MemoryModel.RELAXED) return
|
if (Platform.memoryModel == MemoryModel.RELAXED) return
|
||||||
val weakRefToTrashCycle = createLoop()
|
val weakRefToTrashCycle = createLoop()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertNull(weakRefToTrashCycle.get())
|
assertNull(weakRefToTrashCycle.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:OptIn(kotlin.ExperimentalStdlibApi::class)
|
@file:OptIn(kotlin.ExperimentalStdlibApi::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2018 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
@@ -58,8 +60,8 @@ fun test() {
|
|||||||
val progressReportsCount = 100
|
val progressReportsCount = 100
|
||||||
|
|
||||||
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
||||||
kotlin.native.internal.GC.autotune = false
|
kotlin.native.runtime.GC.autotune = false
|
||||||
kotlin.native.internal.GC.targetHeapBytes = retainLimit
|
kotlin.native.runtime.GC.targetHeapBytes = retainLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Linux, the child process might immediately commit the same amount of memory as the parent.
|
// On Linux, the child process might immediately commit the same amount of memory as the parent.
|
||||||
|
|||||||
@@ -28,15 +28,16 @@ fun multiWeak(): Array<WeakReference<Data>> {
|
|||||||
return weaks
|
return weaks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
@Test fun runTest() {
|
@Test fun runTest() {
|
||||||
val weak = localWeak()
|
val weak = localWeak()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
val value = weak.get()
|
val value = weak.get()
|
||||||
println(value?.toString())
|
println(value?.toString())
|
||||||
|
|
||||||
val weaks = multiWeak()
|
val weaks = multiWeak()
|
||||||
|
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
weaks.forEach {
|
weaks.forEach {
|
||||||
it -> if (it.get()?.s != null) throw Error("not null")
|
it -> if (it.get()?.s != null) throw Error("not null")
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Note: This test reproduces a race, so it'll start flaking if problem is reintroduced.
|
// Note: This test reproduces a race, so it'll start flaking if problem is reintroduced.
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.internal.*
|
import kotlin.native.internal.*
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
val thrashGC = AtomicInt(1)
|
val thrashGC = AtomicInt(1)
|
||||||
val canStartCreating = AtomicInt(0)
|
val canStartCreating = AtomicInt(0)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2018 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@file:OptIn(FreezingIsDeprecated::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package runtime.workers.freeze6
|
package runtime.workers.freeze6
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ var global = 0
|
|||||||
@Test
|
@Test
|
||||||
fun ensureFreezableHandlesCycles1() {
|
fun ensureFreezableHandlesCycles1() {
|
||||||
val ref = createRef1()
|
val ref = createRef1()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
val obj: Any = ref
|
val obj: Any = ref
|
||||||
global = obj.hashCode()
|
global = obj.hashCode()
|
||||||
@@ -86,7 +86,7 @@ fun createRef2(): Pair<FreezableAtomicReference<Node?>, Any> {
|
|||||||
@Test
|
@Test
|
||||||
fun ensureFreezableHandlesCycles2() {
|
fun ensureFreezableHandlesCycles2() {
|
||||||
val (ref, obj) = createRef2()
|
val (ref, obj) = createRef2()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(obj.toString().length > 0)
|
assertTrue(obj.toString().length > 0)
|
||||||
global = ref.value!!.ref!!.hashCode()
|
global = ref.value!!.ref!!.hashCode()
|
||||||
@@ -108,7 +108,7 @@ fun createRef3(): FreezableAtomicReference<Any?> {
|
|||||||
fun ensureFreezableHandlesCycles3() {
|
fun ensureFreezableHandlesCycles3() {
|
||||||
val ref = createRef3()
|
val ref = createRef3()
|
||||||
ref.value = null
|
ref.value = null
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
val obj: Any = ref
|
val obj: Any = ref
|
||||||
assertTrue(obj.toString().length > 0)
|
assertTrue(obj.toString().length > 0)
|
||||||
@@ -133,7 +133,7 @@ fun ensureWeakRefNotLeaks1() {
|
|||||||
ref.value = null
|
ref.value = null
|
||||||
// We cannot check weakRef.get() here, as value read will be stored in the stack slot,
|
// We cannot check weakRef.get() here, as value read will be stored in the stack slot,
|
||||||
// and thus hold weak reference from release.
|
// and thus hold weak reference from release.
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
assertTrue(weakRef.get() == null)
|
assertTrue(weakRef.get() == null)
|
||||||
}
|
}
|
||||||
@@ -155,6 +155,6 @@ fun createRef5() {
|
|||||||
@Test
|
@Test
|
||||||
fun ensureWeakRefNotLeaks2() {
|
fun ensureWeakRefNotLeaks2() {
|
||||||
createRef5()
|
createRef5()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertTrue(weakNode2.get() == null)
|
assertTrue(weakNode2.get() == null)
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,9 @@ fun printAll() {
|
|||||||
// initializer field in frozen lazy object led to the crash, induced by breaking frozen objects'
|
// initializer field in frozen lazy object led to the crash, induced by breaking frozen objects'
|
||||||
// invariant (initializer end up in the same container as the lazy object itself, so it was destroyed
|
// invariant (initializer end up in the same container as the lazy object itself, so it was destroyed
|
||||||
// earlier than it should when reference counter was decremented).
|
// earlier than it should when reference counter was decremented).
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
printAll()
|
printAll()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
println("OK")
|
println("OK")
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@file:OptIn(FreezingIsDeprecated::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.native.ref.*
|
import kotlin.native.ref.*
|
||||||
@@ -49,7 +49,7 @@ fun ensureGetsCollectedFrozenAndNotFrozen(create: () -> Any) {
|
|||||||
|
|
||||||
fun ensureGetsCollected(create: () -> Any) {
|
fun ensureGetsCollected(create: () -> Any) {
|
||||||
val ref = makeWeakRef(create)
|
val ref = makeWeakRef(create)
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertNull(ref.get())
|
assertNull(ref.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@file:OptIn(FreezingIsDeprecated::class, kotlin.experimental.ExperimentalNativeApi::class)
|
@file:OptIn(FreezingIsDeprecated::class, kotlin.experimental.ExperimentalNativeApi::class, kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
package runtime.workers.worker10
|
package runtime.workers.worker10
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
@@ -99,7 +99,7 @@ val semaphore = AtomicInt(0)
|
|||||||
}
|
}
|
||||||
while (semaphore.value != 1) {}
|
while (semaphore.value != 1) {}
|
||||||
atomicRef.value = null
|
atomicRef.value = null
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
future.result
|
future.result
|
||||||
worker.requestTermination().result
|
worker.requestTermination().result
|
||||||
@@ -116,7 +116,7 @@ val semaphore = AtomicInt(0)
|
|||||||
}
|
}
|
||||||
while (semaphore.value != 1) {}
|
while (semaphore.value != 1) {}
|
||||||
stableRef.dispose()
|
stableRef.dispose()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
future.result
|
future.result
|
||||||
worker.requestTermination().result
|
worker.requestTermination().result
|
||||||
@@ -135,12 +135,12 @@ val stableHolder1 = StableRef.create(("hello" to "world").freeze())
|
|||||||
ensureWeakIs(it, "hello" to "world")
|
ensureWeakIs(it, "hello" to "world")
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
while (semaphore.value != 2) {}
|
while (semaphore.value != 2) {}
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
ensureWeakIs(it, null)
|
ensureWeakIs(it, null)
|
||||||
}
|
}
|
||||||
while (semaphore.value != 1) {}
|
while (semaphore.value != 1) {}
|
||||||
stableHolder1.dispose()
|
stableHolder1.dispose()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
future.result
|
future.result
|
||||||
worker.requestTermination().result
|
worker.requestTermination().result
|
||||||
@@ -155,12 +155,12 @@ val stableHolder2 = StableRef.create(("hello" to "world").freeze())
|
|||||||
val value = it.get()
|
val value = it.get()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
while (semaphore.value != 2) {}
|
while (semaphore.value != 2) {}
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
assertEquals("hello" to "world", value)
|
assertEquals("hello" to "world", value)
|
||||||
}
|
}
|
||||||
while (semaphore.value != 1) {}
|
while (semaphore.value != 1) {}
|
||||||
stableHolder2.dispose()
|
stableHolder2.dispose()
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
future.result
|
future.result
|
||||||
worker.requestTermination().result
|
worker.requestTermination().result
|
||||||
@@ -178,7 +178,7 @@ val atomicRef2 = AtomicReference<Any?>(Any().freeze())
|
|||||||
}
|
}
|
||||||
while (semaphore.value != 1) {}
|
while (semaphore.value != 1) {}
|
||||||
atomicRef2.value = null
|
atomicRef2.value = null
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
semaphore.increment()
|
semaphore.increment()
|
||||||
future.result
|
future.result
|
||||||
worker.requestTermination().result
|
worker.requestTermination().result
|
||||||
|
|||||||
@@ -80,12 +80,13 @@ fun makeCyclic(): Node {
|
|||||||
return outer
|
return outer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
@Test fun runTest4() {
|
@Test fun runTest4() {
|
||||||
val worker = Worker.start()
|
val worker = Worker.start()
|
||||||
|
|
||||||
val future = worker.execute(TransferMode.SAFE, { }) {
|
val future = worker.execute(TransferMode.SAFE, { }) {
|
||||||
makeCyclic().also {
|
makeCyclic().also {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(future.result != null)
|
assert(future.result != null)
|
||||||
|
|||||||
@@ -78,12 +78,13 @@ fun makeCyclic(): Node {
|
|||||||
return outer
|
return outer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
@Test fun runTest4() {
|
@Test fun runTest4() {
|
||||||
val worker = Worker.start()
|
val worker = Worker.start()
|
||||||
|
|
||||||
val future = worker.execute(TransferMode.SAFE, { }) {
|
val future = worker.execute(TransferMode.SAFE, { }) {
|
||||||
makeCyclic().also {
|
makeCyclic().also {
|
||||||
kotlin.native.internal.GC.collect()
|
kotlin.native.runtime.GC.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(future.result != null)
|
assert(future.result != null)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.ring
|
package org.jetbrains.ring
|
||||||
|
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
actual fun cleanup() { GC.collect() }
|
actual fun cleanup() { GC.collect() }
|
||||||
+2
-1
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.ring
|
package org.jetbrains.ring
|
||||||
|
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
import kotlin.native.ref.WeakReference
|
import kotlin.native.ref.WeakReference
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotEquals
|
import kotlin.test.assertNotEquals
|
||||||
@@ -46,6 +46,7 @@ private fun ReferenceWrapper.stress() = (1..REPEAT_COUNT).sumOf {
|
|||||||
this.value
|
this.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
open class WeakRefBenchmark {
|
open class WeakRefBenchmark {
|
||||||
private val aliveRef = ReferenceWrapper.create()
|
private val aliveRef = ReferenceWrapper.create()
|
||||||
private val deadRef = ReferenceWrapper.create().apply {
|
private val deadRef = ReferenceWrapper.create().apply {
|
||||||
|
|||||||
+2
-1
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.benchmarksLauncher
|
package org.jetbrains.benchmarksLauncher
|
||||||
|
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
import platform.posix.*
|
import platform.posix.*
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ actual inline fun measureNanoTime(block: () -> Unit): Long {
|
|||||||
return kotlin.system.measureNanoTime(block)
|
return kotlin.system.measureNanoTime(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
actual fun cleanup() {
|
actual fun cleanup() {
|
||||||
GC.collect()
|
GC.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* Copyright 2010-2022 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
|
||||||
package org.jetbrains.gc
|
package org.jetbrains.gc
|
||||||
|
|
||||||
import kotlin.native.internal.GC
|
import kotlin.native.runtime.GC
|
||||||
|
|
||||||
fun collect() = GC.collect()
|
fun collect() = GC.collect()
|
||||||
fun schedule() = GC.schedule()
|
fun schedule() = GC.schedule()
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ private fun debugString(value: Any?): String {
|
|||||||
*
|
*
|
||||||
* Legacy MM: An atomic reference to a frozen Kotlin object. Can be used in concurrent scenarious
|
* Legacy MM: An atomic reference to a frozen Kotlin object. Can be used in concurrent scenarious
|
||||||
* but frequently shall be of nullable type and be zeroed out once no longer needed.
|
* but frequently shall be of nullable type and be zeroed out once no longer needed.
|
||||||
* Otherwise memory leak could happen. To detect such leaks [kotlin.native.internal.GC.detectCycles]
|
* Otherwise memory leak could happen. To detect such leaks [kotlin.native.runtime.GC.detectCycles]
|
||||||
* in debug mode could be helpful.
|
* in debug mode could be helpful.
|
||||||
*/
|
*/
|
||||||
@FrozenLegacyMM
|
@FrozenLegacyMM
|
||||||
@@ -284,7 +284,7 @@ public class AtomicReference<T> {
|
|||||||
*
|
*
|
||||||
* An atomic reference to a Kotlin object. Can be used in concurrent scenarious, but must be frozen first,
|
* An atomic reference to a Kotlin object. Can be used in concurrent scenarious, but must be frozen first,
|
||||||
* otherwise behaves as regular box for the value. If frozen, shall be zeroed out once no longer needed.
|
* otherwise behaves as regular box for the value. If frozen, shall be zeroed out once no longer needed.
|
||||||
* Otherwise memory leak could happen. To detect such leaks [kotlin.native.internal.GC.detectCycles]
|
* Otherwise memory leak could happen. To detect such leaks [kotlin.native.runtime.GC.detectCycles]
|
||||||
* in debug mode could be helpful.
|
* in debug mode could be helpful.
|
||||||
*/
|
*/
|
||||||
@NoReorderFields
|
@NoReorderFields
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import kotlin.native.internal.Frozen
|
|||||||
* Note, that for some cases cycle collection need to be done to ensure that dead cycles do not affect
|
* Note, that for some cases cycle collection need to be done to ensure that dead cycles do not affect
|
||||||
* reachability of passed object graph.
|
* reachability of passed object graph.
|
||||||
*
|
*
|
||||||
* @see [kotlin.native.internal.GC.collect].
|
* @see [kotlin.native.runtime.GC.collect].
|
||||||
*/
|
*/
|
||||||
// Not @FreezingIsDeprecated: every `Worker.execute` uses this.
|
// Not @FreezingIsDeprecated: every `Worker.execute` uses this.
|
||||||
public enum class TransferMode(val value: Int) {
|
public enum class TransferMode(val value: Int) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public value class Worker @PublishedApi internal constructor(val id: Int) {
|
|||||||
* and result of such a execution is being disconnected from worker's object graph. Whoever will consume
|
* and result of such a execution is being disconnected from worker's object graph. Whoever will consume
|
||||||
* the future, can use result of worker's computations.
|
* the future, can use result of worker's computations.
|
||||||
* Note, that some technically disjoint subgraphs may lead to `kotlin.IllegalStateException`
|
* Note, that some technically disjoint subgraphs may lead to `kotlin.IllegalStateException`
|
||||||
* so `kotlin.native.internal.GC.collect()` could be called in the end of `producer` and `job`
|
* so `kotlin.native.runtime.GC.collect()` could be called in the end of `producer` and `job`
|
||||||
* if garbage cyclic structures or other uncollected objects refer to the value being transferred.
|
* if garbage cyclic structures or other uncollected objects refer to the value being transferred.
|
||||||
*
|
*
|
||||||
* @return the future with the computation result of [job].
|
* @return the future with the computation result of [job].
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package kotlin.native.internal
|
|||||||
|
|
||||||
import kotlin.experimental.ExperimentalNativeApi
|
import kotlin.experimental.ExperimentalNativeApi
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
|
import kotlin.native.runtime.GC
|
||||||
import kotlinx.cinterop.NativePtr
|
import kotlinx.cinterop.NativePtr
|
||||||
|
|
||||||
@Deprecated("Use kotlin.native.ref.Cleaner instead.", ReplaceWith("kotlin.native.ref.Cleaner"))
|
@Deprecated("Use kotlin.native.ref.Cleaner instead.", ReplaceWith("kotlin.native.ref.Cleaner"))
|
||||||
@@ -83,6 +84,7 @@ fun <T> createCleaner(argument: T, block: (T) -> Unit): Cleaner =
|
|||||||
* Perform GC on a worker that executes Cleaner blocks.
|
* Perform GC on a worker that executes Cleaner blocks.
|
||||||
*/
|
*/
|
||||||
@InternalForKotlinNative
|
@InternalForKotlinNative
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
fun performGCOnCleanerWorker() =
|
fun performGCOnCleanerWorker() =
|
||||||
getCleanerWorker().execute(TransferMode.SAFE, {}) {
|
getCleanerWorker().execute(TransferMode.SAFE, {}) {
|
||||||
GC.collect()
|
GC.collect()
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
|
|
||||||
package kotlin.native.internal
|
package kotlin.native.internal
|
||||||
|
|
||||||
import kotlin.native.internal.gc.GCInfo
|
|
||||||
import kotlin.time.*
|
import kotlin.time.*
|
||||||
import kotlin.time.Duration.Companion.microseconds
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __Note__: this API is unstable and may change in any release.
|
* __Note__: this API is unstable and may change in any release.
|
||||||
@@ -34,6 +32,9 @@ import kotlin.time.Duration.Companion.microseconds
|
|||||||
* its lifetime, and resume it later on, or just completely turn it off, if GC pauses
|
* its lifetime, and resume it later on, or just completely turn it off, if GC pauses
|
||||||
* are less desirable than cyclical garbage leaks.
|
* are less desirable than cyclical garbage leaks.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use kotlin.native.runtime.GC instead.", ReplaceWith("GC", "kotlin.native.runtime.GC"))
|
||||||
|
@DeprecatedSinceKotlin(warningSince = "1.9")
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
object GC {
|
object GC {
|
||||||
/**
|
/**
|
||||||
* Trigger new collection and wait for its completion.
|
* Trigger new collection and wait for its completion.
|
||||||
@@ -108,12 +109,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is not positive.
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
*/
|
*/
|
||||||
var threshold: Int
|
var threshold: Int by kotlin.native.runtime.GC::threshold
|
||||||
get() = getThreshold()
|
|
||||||
set(value) {
|
|
||||||
require(value > 0) { "threshold must be positive: $value" }
|
|
||||||
setThreshold(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated and unused.
|
* Deprecated and unused.
|
||||||
@@ -125,13 +121,9 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is not positive.
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("No-op in modern GC implementation")
|
@Deprecated("No-op in modern GC implementation")
|
||||||
var collectCyclesThreshold: Long
|
var collectCyclesThreshold: Long by kotlin.native.runtime.GC::collectCyclesThreshold
|
||||||
get() = getCollectCyclesThreshold()
|
|
||||||
set(value) {
|
|
||||||
require(value > 0) { "collectCyclesThreshold must be positive: $value" }
|
|
||||||
setCollectCyclesThreshold(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How many bytes a thread can allocate before informing the GC scheduler.
|
* How many bytes a thread can allocate before informing the GC scheduler.
|
||||||
@@ -145,12 +137,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is not positive.
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
*/
|
*/
|
||||||
var thresholdAllocations: Long
|
var thresholdAllocations: Long by kotlin.native.runtime.GC::thresholdAllocations
|
||||||
get() = getThresholdAllocations()
|
|
||||||
set(value) {
|
|
||||||
require(value > 0) { "thresholdAllocations must be positive: $value" }
|
|
||||||
setThresholdAllocations(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true update targetHeapBytes after each collection.
|
* If true update targetHeapBytes after each collection.
|
||||||
@@ -159,9 +146,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* Default: true
|
* Default: true
|
||||||
*/
|
*/
|
||||||
var autotune: Boolean
|
var autotune: Boolean by kotlin.native.runtime.GC::autotune
|
||||||
get() = getTuneThreshold()
|
|
||||||
set(value) = setTuneThreshold(value)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,10 +154,9 @@ object GC {
|
|||||||
*
|
*
|
||||||
* Legacy MM: If cyclic collector for atomic references to be deployed.
|
* Legacy MM: If cyclic collector for atomic references to be deployed.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("No-op in modern GC implementation")
|
@Deprecated("No-op in modern GC implementation")
|
||||||
var cyclicCollectorEnabled: Boolean
|
var cyclicCollectorEnabled: Boolean by kotlin.native.runtime.GC::cyclicCollectorEnabled
|
||||||
get() = getCyclicCollectorEnabled()
|
|
||||||
set(value) = setCyclicCollectorEnabled(value)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When Kotlin code is not allocating enough to trigger GC, the GC scheduler uses timer to drive collection.
|
* When Kotlin code is not allocating enough to trigger GC, the GC scheduler uses timer to drive collection.
|
||||||
@@ -186,12 +170,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is negative.
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
*/
|
*/
|
||||||
var regularGCInterval: Duration
|
var regularGCInterval: Duration by kotlin.native.runtime.GC::regularGCInterval
|
||||||
get() = getRegularGCIntervalMicroseconds().microseconds
|
|
||||||
set(value) {
|
|
||||||
require(!value.isNegative()) { "regularGCInterval must not be negative: $value" }
|
|
||||||
setRegularGCIntervalMicroseconds(value.inWholeMicroseconds)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Total amount of heap available for Kotlin objects. When Kotlin objects overflow this heap,
|
* Total amount of heap available for Kotlin objects. When Kotlin objects overflow this heap,
|
||||||
@@ -208,12 +187,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is negative.
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
*/
|
*/
|
||||||
var targetHeapBytes: Long
|
var targetHeapBytes: Long by kotlin.native.runtime.GC::targetHeapBytes
|
||||||
get() = getTargetHeapBytes()
|
|
||||||
set(value) {
|
|
||||||
require(value >= 0) { "targetHeapBytes must not be negative: $value" }
|
|
||||||
setTargetHeapBytes(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What fraction of the Kotlin heap should be populated.
|
* What fraction of the Kotlin heap should be populated.
|
||||||
@@ -225,12 +199,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is outside (0, 1] interval.
|
* @throws [IllegalArgumentException] when value is outside (0, 1] interval.
|
||||||
*/
|
*/
|
||||||
var targetHeapUtilization: Double
|
var targetHeapUtilization: Double by kotlin.native.runtime.GC::targetHeapUtilization
|
||||||
get() = getTargetHeapUtilization()
|
|
||||||
set(value) {
|
|
||||||
require(value > 0 && value <= 1) { "targetHeapUtilization must be in (0, 1] interval: $value" }
|
|
||||||
setTargetHeapUtilization(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum value for [targetHeapBytes]
|
* The minimum value for [targetHeapBytes]
|
||||||
@@ -242,12 +211,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is negative.
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
*/
|
*/
|
||||||
var minHeapBytes: Long
|
var minHeapBytes: Long by kotlin.native.runtime.GC::minHeapBytes
|
||||||
get() = getMinHeapBytes()
|
|
||||||
set(value) {
|
|
||||||
require(value >= 0) { "minHeapBytes must not be negative: $value" }
|
|
||||||
setMinHeapBytes(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum value for [targetHeapBytes].
|
* The maximum value for [targetHeapBytes].
|
||||||
@@ -259,12 +223,7 @@ object GC {
|
|||||||
*
|
*
|
||||||
* @throws [IllegalArgumentException] when value is negative.
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
*/
|
*/
|
||||||
var maxHeapBytes: Long
|
var maxHeapBytes: Long by kotlin.native.runtime.GC::maxHeapBytes
|
||||||
get() = getMaxHeapBytes()
|
|
||||||
set(value) {
|
|
||||||
require(value >= 0) { "maxHeapBytes must not be negative: $value" }
|
|
||||||
setMaxHeapBytes(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated and unused. Always returns null.
|
* Deprecated and unused. Always returns null.
|
||||||
@@ -286,75 +245,7 @@ object GC {
|
|||||||
* Legacy MM: Always returns null
|
* Legacy MM: Always returns null
|
||||||
*/
|
*/
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
val lastGCInfo: GCInfo?
|
@Suppress("DEPRECATION")
|
||||||
get() = GCInfo.lastGCInfo
|
val lastGCInfo: kotlin.native.internal.gc.GCInfo?
|
||||||
|
get() = kotlin.native.internal.gc.GCInfo.lastGCInfo
|
||||||
/**
|
|
||||||
* Deprecated and unused. Always returns null.
|
|
||||||
*
|
|
||||||
* Legacy MM: Find a reference cycle including from the given object, `null` if no cycles detected.
|
|
||||||
*/
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_findCycle")
|
|
||||||
@Deprecated("No-op in modern GC implementation")
|
|
||||||
external fun findCycle(root: Any): Array<Any>?
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getThreshold")
|
|
||||||
private external fun getThreshold(): Int
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setThreshold")
|
|
||||||
private external fun setThreshold(value: Int)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getCollectCyclesThreshold")
|
|
||||||
private external fun getCollectCyclesThreshold(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setCollectCyclesThreshold")
|
|
||||||
private external fun setCollectCyclesThreshold(value: Long)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getThresholdAllocations")
|
|
||||||
private external fun getThresholdAllocations(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setThresholdAllocations")
|
|
||||||
private external fun setThresholdAllocations(value: Long)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getTuneThreshold")
|
|
||||||
private external fun getTuneThreshold(): Boolean
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setTuneThreshold")
|
|
||||||
private external fun setTuneThreshold(value: Boolean)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getCyclicCollector")
|
|
||||||
private external fun getCyclicCollectorEnabled(): Boolean
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setCyclicCollector")
|
|
||||||
private external fun setCyclicCollectorEnabled(value: Boolean)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getRegularGCIntervalMicroseconds")
|
|
||||||
private external fun getRegularGCIntervalMicroseconds(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setRegularGCIntervalMicroseconds")
|
|
||||||
private external fun setRegularGCIntervalMicroseconds(value: Long)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getTargetHeapBytes")
|
|
||||||
private external fun getTargetHeapBytes(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setTargetHeapBytes")
|
|
||||||
private external fun setTargetHeapBytes(value: Long)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getTargetHeapUtilization")
|
|
||||||
private external fun getTargetHeapUtilization(): Double
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setTargetHeapUtilization")
|
|
||||||
private external fun setTargetHeapUtilization(value: Double)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getMinHeapBytes")
|
|
||||||
private external fun getMinHeapBytes(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setMinHeapBytes")
|
|
||||||
private external fun setMinHeapBytes(value: Long)
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_getMaxHeapBytes")
|
|
||||||
private external fun getMaxHeapBytes(): Long
|
|
||||||
|
|
||||||
@GCUnsafeCall("Kotlin_native_internal_GC_setMaxHeapBytes")
|
|
||||||
private external fun setMaxHeapBytes(value: Long)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 kotlin.native.runtime
|
||||||
|
|
||||||
|
import kotlin.time.*
|
||||||
|
import kotlin.time.Duration.Companion.microseconds
|
||||||
|
import kotlin.native.internal.GCUnsafeCall
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __Note__: this API is unstable and may change in any release.
|
||||||
|
*
|
||||||
|
* Kotlin/Native uses tracing garbage collector (GC) that is executed periodically to collect objects
|
||||||
|
* that are not reachable from the "roots", like local and global variables.
|
||||||
|
* See [documentation](https://kotlinlang.org/docs/native-memory-manager.html) to learn more about
|
||||||
|
* Kotlin/Native memory management.
|
||||||
|
*
|
||||||
|
* This object provides a set of functions and properties that allows to tune garbage collector.
|
||||||
|
*
|
||||||
|
* __Legacy memory manager__
|
||||||
|
*
|
||||||
|
* Kotlin/Native relies upon reference counting for object management, however it could
|
||||||
|
* not collect cyclical garbage, so we perform periodic garbage collection.
|
||||||
|
* This may slow down application, so this interface provides control over how
|
||||||
|
* garbage collector activates and runs.
|
||||||
|
* Garbage collector can be in one of the following states:
|
||||||
|
* - running
|
||||||
|
* - suspended (so cycle candidates are collected, but GC is not performed until resume)
|
||||||
|
* - stopped (all cyclical garbage is hopelessly lost)
|
||||||
|
* Immediately after startup GC is in running state.
|
||||||
|
* Depending on application needs it may select to suspend GC for certain phases of
|
||||||
|
* its lifetime, and resume it later on, or just completely turn it off, if GC pauses
|
||||||
|
* are less desirable than cyclical garbage leaks.
|
||||||
|
*/
|
||||||
|
@NativeRuntimeApi
|
||||||
|
@SinceKotlin("1.9")
|
||||||
|
public object GC {
|
||||||
|
/**
|
||||||
|
* Trigger new collection and wait for its completion.
|
||||||
|
*
|
||||||
|
* Legacy MM: force garbage collection immediately, unless collector is stopped
|
||||||
|
* with [stop] operation. Even if GC is suspended, [collect] still triggers collection.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_collect")
|
||||||
|
external fun collect()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger new collection without waiting for its completion.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_schedule")
|
||||||
|
external fun schedule()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: Request global cyclic collector, operation is async and just triggers the collection.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_collectCyclic")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun collectCyclic()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: Suspend garbage collection. Release candidates are still collected, but
|
||||||
|
* GC algorithm is not executed.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_suspend")
|
||||||
|
external fun suspend()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: Resume garbage collection. Can potentially lead to GC immediately.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_resume")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun resume()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: Stop garbage collection. Cyclical garbage is no longer collected.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_stop")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun stop()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: Start garbage collection. Cyclical garbage produced while GC was stopped
|
||||||
|
* cannot be reclaimed, but all new garbage is collected.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_start")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun start()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GC threshold, controlling how frequenly GC is activated, and how much time GC
|
||||||
|
* takes. Bigger values lead to longer GC pauses, but less GCs.
|
||||||
|
* Usually unused. For the on-safepoints GC scheduler counts
|
||||||
|
* how many safepoints must the code pass before informing the GC scheduler.
|
||||||
|
*
|
||||||
|
* Default: (old MM) 8 * 1024
|
||||||
|
*
|
||||||
|
* Default: (new MM) 100000
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
|
*/
|
||||||
|
var threshold: Int
|
||||||
|
get() = getThreshold()
|
||||||
|
set(value) {
|
||||||
|
require(value > 0) { "threshold must be positive: $value" }
|
||||||
|
setThreshold(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: GC allocation threshold, controlling how frequenly GC collect cycles, and how much time
|
||||||
|
* this process takes. Bigger values lead to longer GC pauses, but less GCs.
|
||||||
|
*
|
||||||
|
* Default: 8 * 1024
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
|
*/
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
var collectCyclesThreshold: Long
|
||||||
|
get() = getCollectCyclesThreshold()
|
||||||
|
set(value) {
|
||||||
|
require(value > 0) { "collectCyclesThreshold must be positive: $value" }
|
||||||
|
setCollectCyclesThreshold(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many bytes a thread can allocate before informing the GC scheduler.
|
||||||
|
*
|
||||||
|
* Default: 10 * 1024
|
||||||
|
*
|
||||||
|
* Legacy MM: GC allocation threshold, controlling how many bytes allocated since last
|
||||||
|
* collection will trigger new GC.
|
||||||
|
*
|
||||||
|
* Default: (legacy MM) 8 * 1024 * 1024
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is not positive.
|
||||||
|
*/
|
||||||
|
var thresholdAllocations: Long
|
||||||
|
get() = getThresholdAllocations()
|
||||||
|
set(value) {
|
||||||
|
require(value > 0) { "thresholdAllocations must be positive: $value" }
|
||||||
|
setThresholdAllocations(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true update targetHeapBytes after each collection.
|
||||||
|
*
|
||||||
|
* Legacy MM: If GC shall auto-tune thresholds, depending on how much time is spent in collection.
|
||||||
|
*
|
||||||
|
* Default: true
|
||||||
|
*/
|
||||||
|
var autotune: Boolean
|
||||||
|
get() = getTuneThreshold()
|
||||||
|
set(value) = setTuneThreshold(value)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused.
|
||||||
|
*
|
||||||
|
* Legacy MM: If cyclic collector for atomic references to be deployed.
|
||||||
|
*/
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
var cyclicCollectorEnabled: Boolean
|
||||||
|
get() = getCyclicCollectorEnabled()
|
||||||
|
set(value) = setCyclicCollectorEnabled(value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When Kotlin code is not allocating enough to trigger GC, the GC scheduler uses timer to drive collection.
|
||||||
|
* Timer-triggered collection will happen roughly in [regularGCInterval] .. 2 * [regularGCInterval] since
|
||||||
|
* any previous collection.
|
||||||
|
* Unused with on-safepoints GC scheduler.
|
||||||
|
*
|
||||||
|
* Default: 10 seconds
|
||||||
|
*
|
||||||
|
* Unused in legacy MM.
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
|
*/
|
||||||
|
var regularGCInterval: Duration
|
||||||
|
get() = getRegularGCIntervalMicroseconds().microseconds
|
||||||
|
set(value) {
|
||||||
|
require(!value.isNegative()) { "regularGCInterval must not be negative: $value" }
|
||||||
|
setRegularGCIntervalMicroseconds(value.inWholeMicroseconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total amount of heap available for Kotlin objects. When Kotlin objects overflow this heap,
|
||||||
|
* the garbage collection is requested. Automatically adjusts when [autotune] is true:
|
||||||
|
* after each collection the [targetHeapBytes] is set to heapBytes / [targetHeapUtilization] and
|
||||||
|
* capped between [minHeapBytes] and [maxHeapBytes], where heapBytes is heap usage after the garbage
|
||||||
|
* is collected.
|
||||||
|
* Note, that if after a collection heapBytes > [targetHeapBytes] (which may happen if [autotune] is false,
|
||||||
|
* or [maxHeapBytes] is set too low), the next collection will be triggered almost immediately.
|
||||||
|
*
|
||||||
|
* Default: 1 MiB
|
||||||
|
*
|
||||||
|
* Unused in legacy MM.
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
|
*/
|
||||||
|
var targetHeapBytes: Long
|
||||||
|
get() = getTargetHeapBytes()
|
||||||
|
set(value) {
|
||||||
|
require(value >= 0) { "targetHeapBytes must not be negative: $value" }
|
||||||
|
setTargetHeapBytes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What fraction of the Kotlin heap should be populated.
|
||||||
|
* Only used if [autotune] is true. See [targetHeapBytes] for more details.
|
||||||
|
*
|
||||||
|
* Default: 0.5
|
||||||
|
*
|
||||||
|
* Unused in legacy MM.
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is outside (0, 1] interval.
|
||||||
|
*/
|
||||||
|
var targetHeapUtilization: Double
|
||||||
|
get() = getTargetHeapUtilization()
|
||||||
|
set(value) {
|
||||||
|
require(value > 0 && value <= 1) { "targetHeapUtilization must be in (0, 1] interval: $value" }
|
||||||
|
setTargetHeapUtilization(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum value for [targetHeapBytes]
|
||||||
|
* Only used if [autotune] is true. See [targetHeapBytes] for more details.
|
||||||
|
*
|
||||||
|
* Default: 1 MiB
|
||||||
|
*
|
||||||
|
* Unused in legacy MM.
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
|
*/
|
||||||
|
var minHeapBytes: Long
|
||||||
|
get() = getMinHeapBytes()
|
||||||
|
set(value) {
|
||||||
|
require(value >= 0) { "minHeapBytes must not be negative: $value" }
|
||||||
|
setMinHeapBytes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum value for [targetHeapBytes].
|
||||||
|
* Only used if [autotune] is true. See [targetHeapBytes] for more details.
|
||||||
|
*
|
||||||
|
* Default: [Long.MAX_VALUE]
|
||||||
|
*
|
||||||
|
* Unused in legacy MM.
|
||||||
|
*
|
||||||
|
* @throws [IllegalArgumentException] when value is negative.
|
||||||
|
*/
|
||||||
|
var maxHeapBytes: Long
|
||||||
|
get() = getMaxHeapBytes()
|
||||||
|
set(value) {
|
||||||
|
require(value >= 0) { "maxHeapBytes must not be negative: $value" }
|
||||||
|
setMaxHeapBytes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused. Always returns null.
|
||||||
|
*
|
||||||
|
* Legacy MM: Detect cyclic references going via atomic references and return list of cycle-inducing objects
|
||||||
|
* or `null` if the leak detector is not available. Use [Platform.isMemoryLeakCheckerActive] to check
|
||||||
|
* leak detector availability.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_detectCycles")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun detectCycles(): Array<Any>?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns statistics of the last finished garbage collection run.
|
||||||
|
* This information is supposed to be used for testing and debugging purposes only
|
||||||
|
*
|
||||||
|
* Can return null, if there was no garbage collection runs yet.
|
||||||
|
*
|
||||||
|
* Legacy MM: Always returns null
|
||||||
|
*/
|
||||||
|
@ExperimentalStdlibApi
|
||||||
|
val lastGCInfo: GCInfo?
|
||||||
|
get() = GCInfo.lastGCInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated and unused. Always returns null.
|
||||||
|
*
|
||||||
|
* Legacy MM: Find a reference cycle including from the given object, `null` if no cycles detected.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_findCycle")
|
||||||
|
@Deprecated("No-op in modern GC implementation")
|
||||||
|
external fun findCycle(root: Any): Array<Any>?
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getThreshold")
|
||||||
|
private external fun getThreshold(): Int
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setThreshold")
|
||||||
|
private external fun setThreshold(value: Int)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getCollectCyclesThreshold")
|
||||||
|
private external fun getCollectCyclesThreshold(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setCollectCyclesThreshold")
|
||||||
|
private external fun setCollectCyclesThreshold(value: Long)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getThresholdAllocations")
|
||||||
|
private external fun getThresholdAllocations(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setThresholdAllocations")
|
||||||
|
private external fun setThresholdAllocations(value: Long)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getTuneThreshold")
|
||||||
|
private external fun getTuneThreshold(): Boolean
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setTuneThreshold")
|
||||||
|
private external fun setTuneThreshold(value: Boolean)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getCyclicCollector")
|
||||||
|
private external fun getCyclicCollectorEnabled(): Boolean
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setCyclicCollector")
|
||||||
|
private external fun setCyclicCollectorEnabled(value: Boolean)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getRegularGCIntervalMicroseconds")
|
||||||
|
private external fun getRegularGCIntervalMicroseconds(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setRegularGCIntervalMicroseconds")
|
||||||
|
private external fun setRegularGCIntervalMicroseconds(value: Long)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getTargetHeapBytes")
|
||||||
|
private external fun getTargetHeapBytes(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setTargetHeapBytes")
|
||||||
|
private external fun setTargetHeapBytes(value: Long)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getTargetHeapUtilization")
|
||||||
|
private external fun getTargetHeapUtilization(): Double
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setTargetHeapUtilization")
|
||||||
|
private external fun setTargetHeapUtilization(value: Double)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getMinHeapBytes")
|
||||||
|
private external fun getMinHeapBytes(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setMinHeapBytes")
|
||||||
|
private external fun setMinHeapBytes(value: Long)
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_getMaxHeapBytes")
|
||||||
|
private external fun getMaxHeapBytes(): Long
|
||||||
|
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_setMaxHeapBytes")
|
||||||
|
private external fun setMaxHeapBytes(value: Long)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user