Skip to content

Commit 0a19a24

Browse files
committed
Formalize the internal IDEA dependencies for binary compatibility
1 parent 2e92d58 commit 0a19a24

File tree

2 files changed

+31
-19
lines changed

2 files changed

+31
-19
lines changed

kotlinx-coroutines-core/api/kotlinx-coroutines-core.api

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,16 @@ public final class kotlinx/coroutines/debug/internal/DebugCoroutineInfo {
888888
public final fun lastObservedStackTrace ()Ljava/util/List;
889889
}
890890

891+
public final class kotlinx/coroutines/debug/internal/DebugProbesImpl {
892+
public static final field INSTANCE Lkotlinx/coroutines/debug/internal/DebugProbesImpl;
893+
public final fun dumpCoroutinesInfo ()Ljava/util/List;
894+
public final fun dumpCoroutinesInfoAsJsonAndReferences ()[Ljava/lang/Object;
895+
public final fun dumpDebuggerInfo ()Ljava/util/List;
896+
public final fun enhanceStackTraceWithThreadDump (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfo;Ljava/util/List;)Ljava/util/List;
897+
public final fun enhanceStackTraceWithThreadDumpAsJson (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfo;)Ljava/lang/String;
898+
public final fun isInstalled ()Z
899+
}
900+
891901
public final class kotlinx/coroutines/debug/internal/DebuggerInfo : java/io/Serializable {
892902
public fun <init> (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfoImpl;Lkotlin/coroutines/CoroutineContext;)V
893903
public final fun getCoroutineId ()Ljava/lang/Long;

kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import kotlin.coroutines.jvm.internal.CoroutineStackFrame
1818
import kotlin.synchronized
1919
import _COROUTINE.ArtificialStackFrames
2020

21+
@PublishedApi
2122
internal object DebugProbesImpl {
2223
private val ARTIFICIAL_FRAME = ArtificialStackFrames().coroutineCreation()
2324
private val dateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
@@ -31,16 +32,16 @@ internal object DebugProbesImpl {
3132
private val installations = atomic(0)
3233

3334
/**
34-
* This internal method is used by IDEA debugger under the JVM name of
35+
* This internal method is used by the IDEA debugger under the JVM name
3536
* "isInstalled$kotlinx_coroutines_debug".
3637
*/
37-
internal val isInstalled: Boolean get() = installations.value > 0
38+
val isInstalled: Boolean get() = installations.value > 0
3839

39-
// To sort coroutines by creation order, used as unique id
40+
// To sort coroutines by creation order, used as a unique id
4041
private val sequenceNumber = atomic(0L)
4142

42-
public var sanitizeStackTraces: Boolean = true
43-
public var enableCreationStackTraces: Boolean = true
43+
internal var sanitizeStackTraces: Boolean = true
44+
internal var enableCreationStackTraces: Boolean = true
4445

4546
/*
4647
* Substitute for service loader, DI between core and debug modules.
@@ -55,27 +56,28 @@ internal object DebugProbesImpl {
5556
ctor.newInstance() as Function1<Boolean, Unit>
5657
}.getOrNull()
5758

58-
/*
59-
* This is an optimization in the face of KT-29997:
60-
* Consider suspending call stack a()->b()->c() and c() completes its execution and every call is
59+
/**
60+
* Because `probeCoroutinesResumed` is called for every resumed continuation (see KT-29997 and the related code),
61+
* we perform a performance optimization:
62+
* Imagine a suspending call stack a()->b()->c(), where c() completes its execution and every call is
6163
* "almost" in tail position.
6264
*
63-
* Then at least three RUNNING -> RUNNING transitions will occur consecutively and complexity of each is O(depth).
64-
* To avoid that quadratic complexity, we are caching lookup result for such chains in this map and update it incrementally.
65+
* Then at least three RUNNING -> RUNNING transitions will occur consecutively, the complexity of each O(depth).
66+
* To avoid this quadratic complexity, we are caching lookup result for such chains in this map and update it incrementally.
6567
*
6668
* [DebugCoroutineInfoImpl] keeps a lot of auxiliary information about a coroutine, so we use a weak reference queue
6769
* to promptly release the corresponding memory when the reference to the coroutine itself was already collected.
6870
*/
6971
private val callerInfoCache = ConcurrentWeakMap<CoroutineStackFrame, DebugCoroutineInfoImpl>(weakRefQueue = true)
7072

71-
fun install() {
73+
internal fun install() {
7274
if (installations.incrementAndGet() > 1) return
7375
startWeakRefCleanerThread()
7476
if (AgentInstallationType.isInstalledStatically) return
7577
dynamicAttach?.invoke(true) // attach
7678
}
7779

78-
fun uninstall() {
80+
internal fun uninstall() {
7981
check(isInstalled) { "Agent was not installed" }
8082
if (installations.decrementAndGet() != 0) return
8183
stopWeakRefCleanerThread()
@@ -98,7 +100,7 @@ internal object DebugProbesImpl {
98100
thread.join()
99101
}
100102

101-
fun hierarchyToString(job: Job): String {
103+
internal fun hierarchyToString(job: Job): String {
102104
check(isInstalled) { "Debug probes are not installed" }
103105
val jobToStack = capturedCoroutines
104106
.filter { it.delegate.context[Job] != null }
@@ -174,7 +176,7 @@ internal object DebugProbesImpl {
174176
* Internal (JVM-public) method used by IDEA debugger as of 1.6.0-RC.
175177
*/
176178
@OptIn(ExperimentalStdlibApi::class)
177-
public fun dumpCoroutinesInfoAsJsonAndReferences(): Array<Any> {
179+
fun dumpCoroutinesInfoAsJsonAndReferences(): Array<Any> {
178180
val coroutinesInfo = dumpCoroutinesInfo()
179181
val size = coroutinesInfo.size
180182
val lastObservedThreads = ArrayList<Thread?>(size)
@@ -210,7 +212,7 @@ internal object DebugProbesImpl {
210212
/*
211213
* Internal (JVM-public) method used by IDEA debugger as of 1.6.0-RC.
212214
*/
213-
public fun enhanceStackTraceWithThreadDumpAsJson(info: DebugCoroutineInfo): String {
215+
fun enhanceStackTraceWithThreadDumpAsJson(info: DebugCoroutineInfo): String {
214216
val stackTraceElements = enhanceStackTraceWithThreadDump(info, info.lastObservedStackTrace)
215217
val stackTraceElementsInfoAsJson = mutableListOf<String>()
216218
for (element in stackTraceElements) {
@@ -234,17 +236,17 @@ internal object DebugProbesImpl {
234236
/*
235237
* Internal (JVM-public) method used by IDEA debugger as of 1.4-M3.
236238
*/
237-
public fun dumpCoroutinesInfo(): List<DebugCoroutineInfo> =
239+
fun dumpCoroutinesInfo(): List<DebugCoroutineInfo> =
238240
dumpCoroutinesInfoImpl { owner, context -> DebugCoroutineInfo(owner.info, context) }
239241

240242
/*
241243
* Internal (JVM-public) method to be used by IDEA debugger in the future (not used as of 1.4-M3).
242244
* It is equivalent to [dumpCoroutinesInfo], but returns serializable (and thus less typed) objects.
243245
*/
244-
public fun dumpDebuggerInfo(): List<DebuggerInfo> =
246+
fun dumpDebuggerInfo(): List<DebuggerInfo> =
245247
dumpCoroutinesInfoImpl { owner, context -> DebuggerInfo(owner.info, context) }
246248

247-
public fun dumpCoroutines(out: PrintStream): Unit = synchronized(out) {
249+
internal fun dumpCoroutines(out: PrintStream): Unit = synchronized(out) {
248250
/*
249251
* This method synchronizes both on `out` and `this` for a reason:
250252
* 1) Taking a write lock is required to have a consistent snapshot of coroutines.
@@ -306,7 +308,7 @@ internal object DebugProbesImpl {
306308
* It is similar to [enhanceStackTraceWithThreadDumpImpl], but uses debugger-facing [DebugCoroutineInfo] type.
307309
*/
308310
@Suppress("unused")
309-
public fun enhanceStackTraceWithThreadDump(
311+
fun enhanceStackTraceWithThreadDump(
310312
info: DebugCoroutineInfo,
311313
coroutineTrace: List<StackTraceElement>
312314
): List<StackTraceElement> =

0 commit comments

Comments
 (0)