[FIR] Use coroutine intrinsics in tower resolver manager
To remove SafeContinuation overhead
This commit is contained in:
+20
-7
@@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user