[FIR] Use coroutine intrinsics in tower resolver manager

To remove SafeContinuation overhead
This commit is contained in:
Simon Ogorodnik
2020-08-07 18:15:16 +03:00
parent 7cb5c0a6d8
commit 7170a23f63
@@ -8,6 +8,9 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.resolve.calls.CandidateCollector
import java.util.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
class TowerResolveManager private constructor(private val shouldStopAtTheLevel: (TowerGroup) -> Boolean) {
@@ -19,7 +22,13 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
queue.clear()
}
private suspend fun suspendResolverTask(group: TowerGroup) = suspendCoroutine<Unit> { queue += SuspendedResolverTask(it, group) }
private suspend fun suspendResolverTask(group: TowerGroup) =
suspendCoroutineUninterceptedOrReturn<Unit> {
val nextTask = queue.poll()
queue += SuspendedResolverTask(it, group)
if (nextTask != null) resumeTask(nextTask)
COROUTINE_SUSPENDED
}
suspend fun requestGroup(requested: TowerGroup) {
if (shouldStopAtTheLevel(requested)) {
@@ -34,7 +43,7 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
}
}
private suspend fun stopResolverTask(): Nothing = suspendCoroutine { }
private suspend fun stopResolverTask(): Nothing = suspendCoroutineUninterceptedOrReturn { COROUTINE_SUSPENDED }
private data class SuspendedResolverTask(
val continuation: Continuation<Unit>,
@@ -46,7 +55,7 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
}
fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) {
val continuation = task.createCoroutine(
val continuation = task.createCoroutineUnintercepted(
object : Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
@@ -60,13 +69,17 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
queue += SuspendedResolverTask(continuation, group)
}
private fun resumeTask(task: SuspendedResolverTask) {
if (shouldStopAtTheLevel(task.group)) {
return
}
task.continuation.resume(Unit)
}
fun runTasks() {
while (queue.isNotEmpty()) {
val current = queue.poll()
if (shouldStopAtTheLevel(current.group)) {
return
}
current.continuation.resume(Unit)
resumeTask(current)
}
}
}