JVM_IR: place suspend markers in faux lambdas around inline references

Otherwise, the assumption that coroutine codegen makes about every
inlined function already having the markers breaks and it is no longer
true that calls to inline lambdas do not require them.
This commit is contained in:
pyos
2020-03-13 13:14:37 +01:00
committed by Ilmir Usmanov
parent f29e665dce
commit bdd88e1655
11 changed files with 133 additions and 6 deletions
@@ -102,7 +102,6 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE &&
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC &&
origin != JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE &&
origin != IrDeclarationOrigin.BRIDGE &&
origin != IrDeclarationOrigin.BRIDGE_SPECIAL &&
origin != IrDeclarationOrigin.DELEGATED_MEMBER &&
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.irArray
@@ -78,7 +77,7 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
return irBuilder.irBlock(expression, IrStatementOrigin.LAMBDA) {
val function = buildFun {
setSourceRange(expression)
origin = JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
name = Name.identifier("stub_for_inline")
visibility = Visibilities.LOCAL
returnType = field.type
@@ -135,7 +134,7 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
val function = buildFun {
setSourceRange(expression)
origin = JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
name = Name.identifier("stub_for_inlining")
visibility = Visibilities.LOCAL
returnType = referencedFunction.returnType
@@ -46,7 +46,7 @@ private class TailCallOptimizationLowering(private val context: JvmBackendContex
}, null)
}
private fun IrExpression.coerceToUnit() = IrTypeOperatorCallImpl(
private fun IrExpression.coerceToUnit() = if (type == context.irBuiltIns.unitType) this else IrTypeOperatorCallImpl(
startOffset, endOffset, context.irBuiltIns.unitType, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType, this
)
}
@@ -75,7 +75,7 @@ private class TailCallOptimizationData(val function: IrSimpleFunction) {
init {
when (val body = function.body) {
is IrBlockBody -> body.statements.findTailCall(returnsUnit)?.findCallsOnTailPositionWithoutImmediateReturn()
is IrExpressionBody -> body.expression.findCallsOnTailPositionWithoutImmediateReturn()
is IrExpressionBody -> body.expression.findCallsOnTailPositionWithoutImmediateReturn(immediateReturn = true)
}
}
}
@@ -0,0 +1,36 @@
// WITH_RUNTIME
// WITH_COROUTINES
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
import kotlin.coroutines.intrinsics.*
import kotlin.coroutines.*
class Delayed(val run: suspend() -> Unit)
inline fun asyncThenAddK(crossinline block: suspend () -> Unit) =
Delayed {
block()
result += "K"
}
suspend fun pause(): Unit = suspendCoroutineUninterceptedOrReturn { cont ->
cont.resume(Unit)
COROUTINE_SUSPENDED
}
var result = ""
suspend fun addO(): Unit {
pause()
result += "O"
}
// FILE: 2.kt
import kotlin.coroutines.intrinsics.*
import kotlin.coroutines.*
import helpers.*
fun box(): String {
suspend { asyncThenAddK(::addO).run() }.startCoroutine(EmptyContinuation)
return result
}
@@ -0,0 +1,33 @@
// WITH_RUNTIME
// WITH_COROUTINES
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
import kotlin.coroutines.intrinsics.*
import kotlin.coroutines.*
class Delayed(val run: suspend() -> Unit)
inline fun async(crossinline block: suspend () -> Unit) =
Delayed { block() }
suspend fun pause(): Unit = suspendCoroutineUninterceptedOrReturn { cont ->
cont.resume(Unit)
COROUTINE_SUSPENDED
}
var result = ""
suspend fun addOK(): Unit {
pause()
result += "OK"
}
// FILE: 2.kt
import kotlin.coroutines.intrinsics.*
import kotlin.coroutines.*
import helpers.*
fun box(): String {
suspend { async(::addOK).run() }.startCoroutine(EmptyContinuation)
return result
}
@@ -3885,10 +3885,20 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
@@ -3885,10 +3885,20 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
@@ -3780,10 +3780,20 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
@@ -3780,10 +3780,20 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
@@ -3355,10 +3355,20 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
@@ -3355,10 +3355,20 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("nonTailCall.kt")
public void testNonTailCall() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/nonTailCall.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/simple.kt");
}
@TestMetadata("unitReturn.kt")
public void testUnitReturn() throws Exception {
runTest("compiler/testData/codegen/boxInline/suspend/callableReference/unitReturn.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")