Fix incorrect coroutines codegen behavior
If all the suspension calls in a suspend function were "hidden" under the for-convention (iterator/next/hasNext) calls, control-flow didn't find them, thus supposing that there is no suspension points and there is no need to generate a coroutine state machine The solution is to add relevant calls to CFG #KT-15824 Fixed
This commit is contained in:
@@ -931,9 +931,7 @@ class ControlFlowInformationProvider private constructor(
|
||||
private inline fun traverseCalls(crossinline onCall: (instruction: CallInstruction, resolvedCall: ResolvedCall<*>) -> Unit) {
|
||||
pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
||||
if (instruction !is CallInstruction) return@traverse
|
||||
val resolvedCall = instruction.element.getResolvedCall(trace.bindingContext) ?: return@traverse
|
||||
|
||||
onCall(instruction, resolvedCall)
|
||||
onCall(instruction, instruction.resolvedCall)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
|
||||
import java.util.*
|
||||
|
||||
class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
@@ -750,15 +751,18 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
override fun visitForExpression(expression: KtForExpression) {
|
||||
builder.enterBlockScope(expression)
|
||||
|
||||
generateInstructions(expression.loopRange)
|
||||
val loopRange = expression.loopRange
|
||||
generateInstructions(loopRange)
|
||||
generateLoopConventionCall(loopRange, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL)
|
||||
declareLoopParameter(expression)
|
||||
|
||||
// TODO : primitive cases
|
||||
val loopInfo = builder.enterLoop(expression)
|
||||
|
||||
builder.bindLabel(loopInfo.conditionEntryPoint)
|
||||
generateLoopConventionCall(loopRange, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL)
|
||||
builder.nondeterministicJump(loopInfo.exitPoint, expression, null)
|
||||
|
||||
generateLoopConventionCall(loopRange, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL)
|
||||
|
||||
writeLoopParameterAssignment(expression)
|
||||
|
||||
@@ -773,6 +777,15 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
builder.exitBlockScope(expression)
|
||||
}
|
||||
|
||||
private fun generateLoopConventionCall(
|
||||
loopRange: KtExpression?,
|
||||
callSlice: ReadOnlySlice<KtExpression, ResolvedCall<FunctionDescriptor>>
|
||||
) {
|
||||
if (loopRange == null) return
|
||||
val resolvedCall = trace.bindingContext[callSlice, loopRange] ?: return
|
||||
generateCall(resolvedCall)
|
||||
}
|
||||
|
||||
private fun declareLoopParameter(expression: KtForExpression) {
|
||||
val loopParameter = expression.loopParameter
|
||||
if (loopParameter != null) {
|
||||
|
||||
Reference in New Issue
Block a user