[K/N] Benchmarks on weak references
Merge-request: KT-MR-7575 Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
ab590e1279
commit
a31c3f979b
@@ -229,6 +229,9 @@ class RingLauncher : Launcher() {
|
|||||||
"Calls.interfaceMethodHexamorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_HexamorphicCallsite() }),
|
"Calls.interfaceMethodHexamorphic" to BenchmarkEntryWithInit.create(::CallsBenchmark, { interfaceMethodCall_HexamorphicCallsite() }),
|
||||||
"LocalObjects.localArray" to BenchmarkEntryWithInit.create(::LocalObjectsBenchmark, { localArray() }),
|
"LocalObjects.localArray" to BenchmarkEntryWithInit.create(::LocalObjectsBenchmark, { localArray() }),
|
||||||
"ComplexArrays.outerProduct" to BenchmarkEntryWithInit.create(::ComplexArraysBenchmark, { outerProduct() }),
|
"ComplexArrays.outerProduct" to BenchmarkEntryWithInit.create(::ComplexArraysBenchmark, { outerProduct() }),
|
||||||
|
"WeakRefBenchmark.aliveReference" to BenchmarkEntryWithInit.create(::WeakRefBenchmark, { aliveReference() }),
|
||||||
|
"WeakRefBenchmark.deadReference" to BenchmarkEntryWithInit.create(::WeakRefBenchmark, { deadReference() }),
|
||||||
|
"WeakRefBenchmark.dyingReference" to BenchmarkEntryWithInit.create(::WeakRefBenchmark, { dyingReference() }),
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.ring
|
||||||
|
|
||||||
|
import kotlin.native.internal.GC
|
||||||
|
import kotlin.native.ref.WeakReference
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotEquals
|
||||||
|
import kotlinx.cinterop.StableRef
|
||||||
|
import org.jetbrains.benchmarksLauncher.Blackhole
|
||||||
|
import org.jetbrains.benchmarksLauncher.Random
|
||||||
|
|
||||||
|
private const val REPEAT_COUNT = BENCHMARK_SIZE
|
||||||
|
private const val REFERENCES_COUNT = 3
|
||||||
|
|
||||||
|
private class Data(var x: Int = Random.nextInt(1000) + 1)
|
||||||
|
|
||||||
|
private class ReferenceWrapper private constructor(
|
||||||
|
data: Data
|
||||||
|
) {
|
||||||
|
private val weak = WeakReference(data)
|
||||||
|
private val strong = StableRef.create(data)
|
||||||
|
|
||||||
|
val value: Int
|
||||||
|
get() {
|
||||||
|
val ref: Data? = weak.value
|
||||||
|
if (ref == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return ref.x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
strong.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create() = ReferenceWrapper(Data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ReferenceWrapper.stress() = (1..REPEAT_COUNT).sumOf {
|
||||||
|
this.value
|
||||||
|
}
|
||||||
|
|
||||||
|
open class WeakRefBenchmark {
|
||||||
|
private val aliveRef = ReferenceWrapper.create()
|
||||||
|
private val deadRef = ReferenceWrapper.create().apply {
|
||||||
|
dispose()
|
||||||
|
GC.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access alive reference.
|
||||||
|
fun aliveReference() {
|
||||||
|
assertNotEquals(0, aliveRef.stress())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access dead reference.
|
||||||
|
fun deadReference() {
|
||||||
|
assertEquals(0, deadRef.stress())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access reference that is nulled out in the middle.
|
||||||
|
fun dyingReference() {
|
||||||
|
val ref = ReferenceWrapper.create()
|
||||||
|
|
||||||
|
ref.dispose()
|
||||||
|
GC.schedule()
|
||||||
|
|
||||||
|
Blackhole.consume(ref.stress())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,11 @@ swiftBenchmark {
|
|||||||
applicationName = "swiftInterop"
|
applicationName = "swiftInterop"
|
||||||
commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin/report", "src", "../shared/src/main/kotlin")
|
commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin/report", "src", "../shared/src/main/kotlin")
|
||||||
nativeSrcDirs = listOf("../shared/src/main/kotlin-native/common", "../shared/src/main/kotlin-native/posix")
|
nativeSrcDirs = listOf("../shared/src/main/kotlin-native/common", "../shared/src/main/kotlin-native/posix")
|
||||||
swiftSources = listOf("$projectDir/swiftSrc/benchmarks.swift", "$projectDir/swiftSrc/main.swift")
|
swiftSources = listOf(
|
||||||
|
"$projectDir/swiftSrc/benchmarks.swift",
|
||||||
|
"$projectDir/swiftSrc/main.swift",
|
||||||
|
"$projectDir/swiftSrc/weakRefBenchmarks.swift",
|
||||||
|
)
|
||||||
compileTasks = listOf("compileKotlinNative", "linkBenchmark${buildType.name.toLowerCase().capitalize()}FrameworkNative")
|
compileTasks = listOf("compileKotlinNative", "linkBenchmark${buildType.name.toLowerCase().capitalize()}FrameworkNative")
|
||||||
cleanBeforeRunTask = "compileKotlinNative"
|
cleanBeforeRunTask = "compileKotlinNative"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.gc
|
||||||
|
|
||||||
|
import kotlin.native.internal.GC
|
||||||
|
|
||||||
|
fun collect() = GC.collect()
|
||||||
|
fun schedule() = GC.schedule()
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.model
|
||||||
|
|
||||||
|
import org.jetbrains.benchmarksLauncher.Random
|
||||||
|
|
||||||
|
class KotlinData(var x: Int = Random.nextInt())
|
||||||
@@ -36,6 +36,28 @@ swiftLauncher.addBase(name: "createMultigraphOfInt", benchmark: companion.create
|
|||||||
lambda: { ($0 as! SwiftInteropBenchmarks).stringInterop() }))
|
lambda: { ($0 as! SwiftInteropBenchmarks).stringInterop() }))
|
||||||
swiftLauncher.addBase(name: "simpleFunction", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
|
swiftLauncher.addBase(name: "simpleFunction", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
|
||||||
lambda: { ($0 as! SwiftInteropBenchmarks).simpleFunction() }))
|
lambda: { ($0 as! SwiftInteropBenchmarks).simpleFunction() }))
|
||||||
|
swiftLauncher.addBase(
|
||||||
|
name: "WeakRefBenchmark.aliveReference",
|
||||||
|
benchmark: BenchmarkEntryWithInit.companion.create(
|
||||||
|
ctor: { return WeakRefBenchmark() },
|
||||||
|
lambda: { ($0 as! WeakRefBenchmark).aliveReference() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
swiftLauncher.addBase(
|
||||||
|
name: "WeakRefBenchmark.deadReference",
|
||||||
|
benchmark: BenchmarkEntryWithInit.companion.create(
|
||||||
|
ctor: { return WeakRefBenchmark() },
|
||||||
|
lambda: { ($0 as! WeakRefBenchmark).deadReference() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
swiftLauncher.addBase(
|
||||||
|
name: "WeakRefBenchmark.dyingReference",
|
||||||
|
benchmark: BenchmarkEntryWithInit.companion.create(
|
||||||
|
ctor: { return WeakRefBenchmark() },
|
||||||
|
lambda: { ($0 as! WeakRefBenchmark).dyingReference() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in
|
runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in
|
||||||
if arguments is BaseBenchmarkArguments {
|
if arguments is BaseBenchmarkArguments {
|
||||||
let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments
|
let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments
|
||||||
@@ -50,4 +72,4 @@ runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [Benc
|
|||||||
return runner.parse(args: args, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) }) },
|
return runner.parse(args: args, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) }) },
|
||||||
collect: { (benchmarks: [BenchmarkResult], arguments: BenchmarkArguments) -> Void in
|
collect: { (benchmarks: [BenchmarkResult], arguments: BenchmarkArguments) -> Void in
|
||||||
runner.collect(results: benchmarks, arguments: arguments)
|
runner.collect(results: benchmarks, arguments: arguments)
|
||||||
}, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) })
|
}, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) })
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import benchmark
|
||||||
|
|
||||||
|
private let REPEAT_COUNT = 10000
|
||||||
|
private let REFERENCES_COUNT = 3
|
||||||
|
|
||||||
|
private class ReferenceWrapper {
|
||||||
|
private weak var weakRef: KotlinData?
|
||||||
|
private var strongRef: KotlinData?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let data = KotlinData(x: Int32.random(in: 1 ... 1000))
|
||||||
|
self.strongRef = data
|
||||||
|
self.weakRef = data
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function must not be inlined. We must ensure `weakRef` is accessed at each loop iteration.
|
||||||
|
@inline(never) func value() -> Int32 {
|
||||||
|
let ref: KotlinData? = self.weakRef
|
||||||
|
if ref == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return ref!.x
|
||||||
|
}
|
||||||
|
|
||||||
|
func dispose() {
|
||||||
|
self.strongRef = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func stress() -> Int32 {
|
||||||
|
var counter: Int32 = 0
|
||||||
|
for _ in 1...REPEAT_COUNT {
|
||||||
|
counter += self.value()
|
||||||
|
}
|
||||||
|
return counter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func deadReferenceWrapper() -> ReferenceWrapper {
|
||||||
|
let ref = ReferenceWrapper()
|
||||||
|
ref.dispose()
|
||||||
|
GCKt.collect()
|
||||||
|
return ref
|
||||||
|
}
|
||||||
|
|
||||||
|
class WeakRefBenchmark {
|
||||||
|
private let aliveRef = ReferenceWrapper()
|
||||||
|
private let deadRef = deadReferenceWrapper()
|
||||||
|
|
||||||
|
// Access alive reference.
|
||||||
|
func aliveReference() {
|
||||||
|
let counter = aliveRef.stress()
|
||||||
|
if counter == 0 {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access dead reference.
|
||||||
|
func deadReference() {
|
||||||
|
let counter = deadRef.stress()
|
||||||
|
if counter != 0 {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access reference that is nulled out in the middle.
|
||||||
|
func dyingReference() {
|
||||||
|
let ref = ReferenceWrapper()
|
||||||
|
|
||||||
|
ref.dispose()
|
||||||
|
GCKt.schedule()
|
||||||
|
|
||||||
|
let counter = ref.stress()
|
||||||
|
Blackhole.companion.consume(value: counter)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,12 @@ void gc::ConcurrentMarkAndSweep::ThreadData::SafePointAllocation(size_t size) no
|
|||||||
gcScheduler_.OnSafePointAllocation(size);
|
gcScheduler_.OnSafePointAllocation(size);
|
||||||
mm::SuspendIfRequested();
|
mm::SuspendIfRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc::ConcurrentMarkAndSweep::ThreadData::Schedule() noexcept {
|
||||||
|
ThreadStateGuard guard(ThreadState::kNative);
|
||||||
|
gc_.state_.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
void gc::ConcurrentMarkAndSweep::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
void gc::ConcurrentMarkAndSweep::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
||||||
ThreadStateGuard guard(ThreadState::kNative);
|
ThreadStateGuard guard(ThreadState::kNative);
|
||||||
auto scheduled_epoch = gc_.state_.schedule();
|
auto scheduled_epoch = gc_.state_.schedule();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public:
|
|||||||
|
|
||||||
void SafePointAllocation(size_t size) noexcept;
|
void SafePointAllocation(size_t size) noexcept;
|
||||||
|
|
||||||
|
void Schedule() noexcept;
|
||||||
void ScheduleAndWaitFullGC() noexcept;
|
void ScheduleAndWaitFullGC() noexcept;
|
||||||
void ScheduleAndWaitFullGCWithFinalizers() noexcept;
|
void ScheduleAndWaitFullGCWithFinalizers() noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ ALWAYS_INLINE void gc::GC::ThreadData::SafePointLoopBody() noexcept {
|
|||||||
SafePointRegular(*this, GCSchedulerThreadData::kLoopBodyWeight);
|
SafePointRegular(*this, GCSchedulerThreadData::kLoopBodyWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc::GC::ThreadData::Schedule() noexcept {
|
||||||
|
impl_->gc().Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
||||||
impl_->gc().ScheduleAndWaitFullGC();
|
impl_->gc().ScheduleAndWaitFullGC();
|
||||||
}
|
}
|
||||||
@@ -124,4 +128,4 @@ ALWAYS_INLINE void gc::GC::processArrayInMark(void* state, ArrayHeader* array) n
|
|||||||
// static
|
// static
|
||||||
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {
|
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {
|
||||||
gc::internal::processFieldInMark<gc::internal::MarkTraits>(state, field);
|
gc::internal::processFieldInMark<gc::internal::MarkTraits>(state, field);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
void SafePointFunctionPrologue() noexcept;
|
void SafePointFunctionPrologue() noexcept;
|
||||||
void SafePointLoopBody() noexcept;
|
void SafePointLoopBody() noexcept;
|
||||||
|
|
||||||
|
void Schedule() noexcept;
|
||||||
void ScheduleAndWaitFullGC() noexcept;
|
void ScheduleAndWaitFullGC() noexcept;
|
||||||
void ScheduleAndWaitFullGCWithFinalizers() noexcept;
|
void ScheduleAndWaitFullGCWithFinalizers() noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ ALWAYS_INLINE void gc::GC::ThreadData::SafePointLoopBody() noexcept {
|
|||||||
impl_->gc().SafePointLoopBody();
|
impl_->gc().SafePointLoopBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc::GC::ThreadData::Schedule() noexcept {
|
||||||
|
impl_->gc().Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
||||||
impl_->gc().ScheduleAndWaitFullGC();
|
impl_->gc().ScheduleAndWaitFullGC();
|
||||||
}
|
}
|
||||||
@@ -100,4 +104,4 @@ ALWAYS_INLINE void gc::GC::processObjectInMark(void* state, ObjHeader* object) n
|
|||||||
ALWAYS_INLINE void gc::GC::processArrayInMark(void* state, ArrayHeader* array) noexcept {}
|
ALWAYS_INLINE void gc::GC::processArrayInMark(void* state, ArrayHeader* array) noexcept {}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {}
|
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
void SafePointLoopBody() noexcept {}
|
void SafePointLoopBody() noexcept {}
|
||||||
void SafePointAllocation(size_t size) noexcept {}
|
void SafePointAllocation(size_t size) noexcept {}
|
||||||
|
|
||||||
|
void Schedule() noexcept {}
|
||||||
void ScheduleAndWaitFullGC() noexcept {}
|
void ScheduleAndWaitFullGC() noexcept {}
|
||||||
void ScheduleAndWaitFullGCWithFinalizers() noexcept {}
|
void ScheduleAndWaitFullGCWithFinalizers() noexcept {}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ ALWAYS_INLINE void gc::GC::ThreadData::SafePointLoopBody() noexcept {
|
|||||||
SafePointRegular(*this, GCSchedulerThreadData::kLoopBodyWeight);
|
SafePointRegular(*this, GCSchedulerThreadData::kLoopBodyWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc::GC::ThreadData::Schedule() noexcept {
|
||||||
|
impl_->gc().Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
void gc::GC::ThreadData::ScheduleAndWaitFullGC() noexcept {
|
||||||
impl_->gc().ScheduleAndWaitFullGC();
|
impl_->gc().ScheduleAndWaitFullGC();
|
||||||
}
|
}
|
||||||
@@ -119,4 +123,4 @@ ALWAYS_INLINE void gc::GC::processArrayInMark(void* state, ArrayHeader* array) n
|
|||||||
// static
|
// static
|
||||||
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {
|
ALWAYS_INLINE void gc::GC::processFieldInMark(void* state, ObjHeader* field) noexcept {
|
||||||
gc::internal::processFieldInMark<gc::internal::MarkTraits>(state, field);
|
gc::internal::processFieldInMark<gc::internal::MarkTraits>(state, field);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public:
|
|||||||
void SafePointSlowPath(SafepointFlag flag) noexcept;
|
void SafePointSlowPath(SafepointFlag flag) noexcept;
|
||||||
void SafePointAllocation(size_t size) noexcept;
|
void SafePointAllocation(size_t size) noexcept;
|
||||||
|
|
||||||
|
void Schedule() noexcept { ScheduleAndWaitFullGC(); }
|
||||||
void ScheduleAndWaitFullGC() noexcept;
|
void ScheduleAndWaitFullGC() noexcept;
|
||||||
void ScheduleAndWaitFullGCWithFinalizers() noexcept { ScheduleAndWaitFullGC(); }
|
void ScheduleAndWaitFullGCWithFinalizers() noexcept { ScheduleAndWaitFullGC(); }
|
||||||
|
|
||||||
|
|||||||
@@ -3526,6 +3526,12 @@ void Kotlin_native_internal_GC_collect(KRef) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kotlin_native_internal_GC_schedule(KRef) {
|
||||||
|
#if USE_GC
|
||||||
|
garbageCollect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void Kotlin_Internal_GC_GCInfoBuilder_Fill(KRef builder, int id) {
|
extern "C" void Kotlin_Internal_GC_GCInfoBuilder_Fill(KRef builder, int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ object GC {
|
|||||||
@GCUnsafeCall("Kotlin_native_internal_GC_collect")
|
@GCUnsafeCall("Kotlin_native_internal_GC_collect")
|
||||||
external fun collect()
|
external fun collect()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger new collection without waiting for its completion.
|
||||||
|
*/
|
||||||
|
@GCUnsafeCall("Kotlin_native_internal_GC_schedule")
|
||||||
|
external fun schedule()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated and unused.
|
* Deprecated and unused.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -310,6 +310,12 @@ extern "C" void Kotlin_native_internal_GC_collect(ObjHeader*) {
|
|||||||
threadData->gc().ScheduleAndWaitFullGCWithFinalizers();
|
threadData->gc().ScheduleAndWaitFullGCWithFinalizers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void Kotlin_native_internal_GC_schedule(ObjHeader*) {
|
||||||
|
auto* threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
|
||||||
|
AssertThreadState(threadData, ThreadState::kRunnable);
|
||||||
|
threadData->gc().Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void Kotlin_native_internal_GC_collectCyclic(ObjHeader*) {
|
extern "C" void Kotlin_native_internal_GC_collectCyclic(ObjHeader*) {
|
||||||
// TODO: Remove when legacy MM is gone.
|
// TODO: Remove when legacy MM is gone.
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
@@ -649,4 +655,4 @@ RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processFieldInMark(void* st
|
|||||||
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processEmptyObjectInMark(void* state, ObjHeader* object) {
|
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processEmptyObjectInMark(void* state, ObjHeader* object) {
|
||||||
// Empty object. Nothing to do.
|
// Empty object. Nothing to do.
|
||||||
// TODO: Try to generate it in the code generator.
|
// TODO: Try to generate it in the code generator.
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user