diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt index fb39ff7a3ac..4e659290486 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackF import org.jetbrains.kotlin.idea.debugger.coroutine.data.SuspendCoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.DebugMetadata import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.DebugProbesImpl +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.MirrorOfBaseContinuationImpl import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.MirrorOfCoroutineInfo import org.jetbrains.kotlin.idea.debugger.coroutine.util.isCreationSeparatorFrame import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger @@ -33,7 +34,8 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution private fun mapToCoroutineInfoData(mirror: MirrorOfCoroutineInfo): CoroutineInfoData? { val coroutineNameIdState = CoroutineNameIdState.instance(mirror) val stackTrace = mirror.enhancedStackTrace?.mapNotNull { it.stackTraceElement() } ?: emptyList() - val stackFrames = findStackFrames(stackTrace, mirror.lastObservedFrame) + val baseContinuationImpls = getAllBaseContinuationImpls(mirror.lastObservedFrame) + val stackFrames = findStackFrames(stackTrace, baseContinuationImpls) return CoroutineInfoData( coroutineNameIdState, stackFrames.restoredStackFrames, @@ -43,6 +45,24 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution ) } + /** + * Restores array of BaseContinuationImpl's for each restored frame based on the CoroutineInfo's last frame. + * Start from 'lastObservedFrame' and following 'completion' property until the end of the chain (completion = null). + */ + private fun getAllBaseContinuationImpls(lastObservedFrame: ObjectReference?): List { + val restoredBaseContinuationImpl = mutableListOf() + var observedFrame = lastObservedFrame + while (observedFrame != null) { + val baseContinuationImpl = debugMetadata?.baseContinuationImpl?.mirror(observedFrame, executionContext) + if (baseContinuationImpl != null) { + restoredBaseContinuationImpl.add(baseContinuationImpl) + observedFrame = baseContinuationImpl.nextContinuation + } else + break + } + return restoredBaseContinuationImpl + } + fun isInstalled(): Boolean { return try { debugProbesImpl?.isInstalledValue ?: false @@ -54,7 +74,7 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution private fun findStackFrames( frames: List, - lastObservedFrame: ObjectReference? + baseContinuationList: List ): CoroutineStackFrames { val index = frames.indexOfFirst { it.isCreationSeparatorFrame() } val restoredStackTraceElements = if (index >= 0) @@ -62,16 +82,8 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution else frames - var observedFrame = lastObservedFrame - val restoredStackFrames = restoredStackTraceElements.map { - val variables: List = observedFrame?.let { - val spilledVariables = debugMetadata?.baseContinuationImpl?.mirror(it, executionContext) - if (spilledVariables != null) { - observedFrame = spilledVariables.nextContinuation - spilledVariables.spilledValues(executionContext) - } else - null - } ?: emptyList() + val restoredStackFrames = restoredStackTraceElements.mapIndexed { index, it -> + val variables = baseContinuationList.getOrNull(index)?.spilledValues(executionContext) ?: emptyList() SuspendCoroutineStackFrameItem(it, locationCache.createLocation(it), variables) } val creationStackFrames = frames.subList(index + 1, frames.size).mapIndexed { ix, it -> diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt index 90b78c5b007..fd104038e2a 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt @@ -44,14 +44,14 @@ class CoroutineFrameBuilder { val coroutineFrameLists = build(preflightStackFrame, suspendContext) coroutineStackFrameList.addAll(coroutineFrameLists.frames) - return CoroutineFrameItemLists(coroutineStackFrameList, coroutineFrameLists.creationFrames) + return CoroutineFrameItemLists(coroutineStackFrameList, coroutine.creationStackTrace) } else { buildRealStackFrameItem(runningStackFrameProxy)?.let { coroutineStackFrameList.add(it) } } } - return CoroutineFrameItemLists(coroutineStackFrameList, emptyList()) + return CoroutineFrameItemLists(coroutineStackFrameList, coroutine.creationStackTrace) } /**