Invoke probeCoroutineResumed on each unroll of the frame from heap

Fixes KT-29997
This commit is contained in:
Roman Elizarov
2019-02-20 14:59:54 +03:00
parent 9b50d31169
commit 4f532a7c05
2 changed files with 13 additions and 6 deletions
@@ -19,12 +19,13 @@ internal abstract class BaseContinuationImpl(
) : Continuation<Any?>, CoroutineStackFrame, Serializable {
// This implementation is final. This fact is used to unroll resumeWith recursion.
public final override fun resumeWith(result: Result<Any?>) {
// Invoke "resume" debug probe only once, even if previous frames are "resumed" in the loop below, too
probeCoroutineResumed(this)
// This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
var current = this
var param = result
while (true) {
// Invoke "resume" debug probe on every resumed continuation, so that a debugging library infrastructure
// can precisely track what part of suspended callstack was already resumed
probeCoroutineResumed(current)
with(current) {
val completion = completion!! // fail fast when trying to resume continuation without completion
val outcome: Result<Any?> =
@@ -21,10 +21,13 @@ import kotlin.coroutines.intrinsics.*
* +-------+ probeCoroutineCreated +-----------+
* | START | ---------------------->| SUSPENDED |
* +-------+ +-----------+
* probeCoroutineResumed | ^ probeCoroutineSuspended
* V |
* +------------+ completion invoked +-----------+
* | RUNNING | ------------------->| COMPLETED |
* | ^
* probeCoroutineResumed | | probeCoroutineSuspended
* +-------+ |
* | | |
* | V |
* | +------------+ completion invoked +-----------+
* +-- | RUNNING | ------------------->| COMPLETED |
* +------------+ +-----------+
* ```
*
@@ -48,6 +51,9 @@ internal fun <T> probeCoroutineCreated(completion: Continuation<T>): Continuatio
* This probe is invoked when coroutine is resumed using [Continuation.resumeWith].
*
* This probe is invoked from stdlib implementation of [BaseContinuationImpl.resumeWith] function.
* Note, this probe can be invoked multiple times when coroutine is running. Every time the coroutine
* resumes a part its callstack that was previously stored in the heap, this probe is invoked
* with the references to the newly resumed [frame].
*
* Coroutines machinery implementation guarantees that the actual [frame] instance extends
* [BaseContinuationImpl] class, despite the fact that the declared type of [frame]