[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 org.jetbrains.kotlin.fir.resolve.calls.CandidateCollector
import java.util.* import java.util.*
import kotlin.coroutines.* 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) { class TowerResolveManager private constructor(private val shouldStopAtTheLevel: (TowerGroup) -> Boolean) {
@@ -19,7 +22,13 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
queue.clear() 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) { suspend fun requestGroup(requested: TowerGroup) {
if (shouldStopAtTheLevel(requested)) { 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( private data class SuspendedResolverTask(
val continuation: Continuation<Unit>, val continuation: Continuation<Unit>,
@@ -46,7 +55,7 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
} }
fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) { fun enqueueResolverTask(group: TowerGroup = TowerGroup.Start, task: suspend () -> Unit) {
val continuation = task.createCoroutine( val continuation = task.createCoroutineUnintercepted(
object : Continuation<Unit> { object : Continuation<Unit> {
override val context: CoroutineContext override val context: CoroutineContext
get() = EmptyCoroutineContext get() = EmptyCoroutineContext
@@ -60,13 +69,17 @@ class TowerResolveManager private constructor(private val shouldStopAtTheLevel:
queue += SuspendedResolverTask(continuation, group) queue += SuspendedResolverTask(continuation, group)
} }
private fun resumeTask(task: SuspendedResolverTask) {
if (shouldStopAtTheLevel(task.group)) {
return
}
task.continuation.resume(Unit)
}
fun runTasks() { fun runTasks() {
while (queue.isNotEmpty()) { while (queue.isNotEmpty()) {
val current = queue.poll() val current = queue.poll()
if (shouldStopAtTheLevel(current.group)) { resumeTask(current)
return
}
current.continuation.resume(Unit)
} }
} }
} }