(CoroutineDebugger) Refactoring of retrieving BaseContinuationImpl chains
This commit is contained in:
+24
-12
@@ -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.data.SuspendCoroutineStackFrameItem
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.DebugMetadata
|
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.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.proxy.mirror.MirrorOfCoroutineInfo
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isCreationSeparatorFrame
|
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isCreationSeparatorFrame
|
||||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
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? {
|
private fun mapToCoroutineInfoData(mirror: MirrorOfCoroutineInfo): CoroutineInfoData? {
|
||||||
val coroutineNameIdState = CoroutineNameIdState.instance(mirror)
|
val coroutineNameIdState = CoroutineNameIdState.instance(mirror)
|
||||||
val stackTrace = mirror.enhancedStackTrace?.mapNotNull { it.stackTraceElement() } ?: emptyList()
|
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(
|
return CoroutineInfoData(
|
||||||
coroutineNameIdState,
|
coroutineNameIdState,
|
||||||
stackFrames.restoredStackFrames,
|
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<MirrorOfBaseContinuationImpl> {
|
||||||
|
val restoredBaseContinuationImpl = mutableListOf<MirrorOfBaseContinuationImpl>()
|
||||||
|
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 {
|
fun isInstalled(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
debugProbesImpl?.isInstalledValue ?: false
|
debugProbesImpl?.isInstalledValue ?: false
|
||||||
@@ -54,7 +74,7 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution
|
|||||||
|
|
||||||
private fun findStackFrames(
|
private fun findStackFrames(
|
||||||
frames: List<StackTraceElement>,
|
frames: List<StackTraceElement>,
|
||||||
lastObservedFrame: ObjectReference?
|
baseContinuationList: List<MirrorOfBaseContinuationImpl>
|
||||||
): CoroutineStackFrames {
|
): CoroutineStackFrames {
|
||||||
val index = frames.indexOfFirst { it.isCreationSeparatorFrame() }
|
val index = frames.indexOfFirst { it.isCreationSeparatorFrame() }
|
||||||
val restoredStackTraceElements = if (index >= 0)
|
val restoredStackTraceElements = if (index >= 0)
|
||||||
@@ -62,16 +82,8 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution
|
|||||||
else
|
else
|
||||||
frames
|
frames
|
||||||
|
|
||||||
var observedFrame = lastObservedFrame
|
val restoredStackFrames = restoredStackTraceElements.mapIndexed { index, it ->
|
||||||
val restoredStackFrames = restoredStackTraceElements.map {
|
val variables = baseContinuationList.getOrNull(index)?.spilledValues(executionContext) ?: emptyList()
|
||||||
val variables: List<XNamedValue> = observedFrame?.let {
|
|
||||||
val spilledVariables = debugMetadata?.baseContinuationImpl?.mirror(it, executionContext)
|
|
||||||
if (spilledVariables != null) {
|
|
||||||
observedFrame = spilledVariables.nextContinuation
|
|
||||||
spilledVariables.spilledValues(executionContext)
|
|
||||||
} else
|
|
||||||
null
|
|
||||||
} ?: emptyList()
|
|
||||||
SuspendCoroutineStackFrameItem(it, locationCache.createLocation(it), variables)
|
SuspendCoroutineStackFrameItem(it, locationCache.createLocation(it), variables)
|
||||||
}
|
}
|
||||||
val creationStackFrames = frames.subList(index + 1, frames.size).mapIndexed { ix, it ->
|
val creationStackFrames = frames.subList(index + 1, frames.size).mapIndexed { ix, it ->
|
||||||
|
|||||||
+2
-2
@@ -44,14 +44,14 @@ class CoroutineFrameBuilder {
|
|||||||
|
|
||||||
val coroutineFrameLists = build(preflightStackFrame, suspendContext)
|
val coroutineFrameLists = build(preflightStackFrame, suspendContext)
|
||||||
coroutineStackFrameList.addAll(coroutineFrameLists.frames)
|
coroutineStackFrameList.addAll(coroutineFrameLists.frames)
|
||||||
return CoroutineFrameItemLists(coroutineStackFrameList, coroutineFrameLists.creationFrames)
|
return CoroutineFrameItemLists(coroutineStackFrameList, coroutine.creationStackTrace)
|
||||||
} else {
|
} else {
|
||||||
buildRealStackFrameItem(runningStackFrameProxy)?.let {
|
buildRealStackFrameItem(runningStackFrameProxy)?.let {
|
||||||
coroutineStackFrameList.add(it)
|
coroutineStackFrameList.add(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CoroutineFrameItemLists(coroutineStackFrameList, emptyList())
|
return CoroutineFrameItemLists(coroutineStackFrameList, coroutine.creationStackTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user