JVM_IR: treat suspend-converted references as lambdas for inlining
Again, this is consistent with adapted function references, since they're pretty much the same anyway.
This commit is contained in:
Generated
+5
@@ -8678,6 +8678,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
+8
-7
@@ -76,7 +76,7 @@ class IrInlineCodegen(
|
|||||||
blockInfo: BlockInfo
|
blockInfo: BlockInfo
|
||||||
) {
|
) {
|
||||||
val isInlineParameter = irValueParameter.isInlineParameter()
|
val isInlineParameter = irValueParameter.isInlineParameter()
|
||||||
if (isInlineParameter && isInlineIrExpression(argumentExpression)) {
|
if (isInlineParameter && argumentExpression.isInlineIrExpression()) {
|
||||||
val irReference = (argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
val irReference = (argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
||||||
val lambdaInfo = IrExpressionLambdaImpl(codegen, irReference, irValueParameter)
|
val lambdaInfo = IrExpressionLambdaImpl(codegen, irReference, irValueParameter)
|
||||||
val closureInfo = invocationParamBuilder.addNextValueParameter(parameterType, true, null, irValueParameter.index)
|
val closureInfo = invocationParamBuilder.addNextValueParameter(parameterType, true, null, irValueParameter.index)
|
||||||
@@ -245,18 +245,19 @@ class IrDefaultLambda(
|
|||||||
}.toIrBasedDescriptor()
|
}.toIrBasedDescriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isInlineIrExpression(argumentExpression: IrExpression) =
|
fun IrExpression.isInlineIrExpression() =
|
||||||
when (argumentExpression) {
|
when (this) {
|
||||||
is IrBlock -> argumentExpression.isInlineIrBlock()
|
is IrBlock -> origin.isInlineIrExpression()
|
||||||
is IrCallableReference<*> -> true.also {
|
is IrCallableReference<*> -> true.also {
|
||||||
assert((0 until argumentExpression.valueArgumentsCount).count { argumentExpression.getValueArgument(it) != null } == 0) {
|
assert((0 until valueArgumentsCount).count { getValueArgument(it) != null } == 0) {
|
||||||
"Expecting 0 value arguments for bounded callable reference: ${argumentExpression.dump()}"
|
"Expecting 0 value arguments for bounded callable reference: ${dump()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBlock.isInlineIrBlock(): Boolean = origin.isLambda || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
|
fun IrStatementOrigin?.isInlineIrExpression() =
|
||||||
|
isLambda || this == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || this == IrStatementOrigin.SUSPEND_CONVERSION
|
||||||
|
|
||||||
fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) =
|
fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) =
|
||||||
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) && isInline
|
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) && isInline
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ internal open class IrInlineReferenceLocator(private val context: JvmBackendCont
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
val valueArgument = expression.getValueArgument(parameter.index) ?: continue
|
val valueArgument = expression.getValueArgument(parameter.index) ?: continue
|
||||||
if (!isInlineIrExpression(valueArgument))
|
if (!valueArgument.isInlineIrExpression())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (valueArgument is IrBlock) {
|
if (valueArgument is IrBlock) {
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
|||||||
// because they are also their own continuation classes.
|
// because they are also their own continuation classes.
|
||||||
// TODO: Currently, origin of callable references explicitly written in source code is null. Do we need to create one?
|
// TODO: Currently, origin of callable references explicitly written in source code is null. Do we need to create one?
|
||||||
private fun IrFunctionReference.isSuspendFunctionReference(): Boolean = isSuspend &&
|
private fun IrFunctionReference.isSuspendFunctionReference(): Boolean = isSuspend &&
|
||||||
(origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE)
|
(origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || origin == IrStatementOrigin.SUSPEND_CONVERSION)
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile))
|
ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile))
|
||||||
|
|||||||
+2
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
@@ -37,7 +38,7 @@ private class RemoveDeclarationsThatWouldBeInlinedLowering(val context: JvmBacke
|
|||||||
override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this)
|
override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this)
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference) {
|
override fun visitFunctionReference(expression: IrFunctionReference) {
|
||||||
if (expression.origin.isLambda || expression.origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) {
|
if (expression.origin.isInlineIrExpression()) {
|
||||||
loweredLambdasToDelete.add(expression.symbol.owner)
|
loweredLambdasToDelete.add(expression.symbol.owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-4
@@ -109,12 +109,9 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val inlineReferences = IrInlineReferenceLocator.scan(context, irFile)
|
val inlineReferences = IrInlineReferenceLocator.scan(context, irFile)
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
private fun IrFunctionReference.shouldBeTreatedAsSuspendLambda() =
|
|
||||||
isSuspend && (origin == IrStatementOrigin.LAMBDA || origin == IrStatementOrigin.SUSPEND_CONVERSION)
|
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock): IrExpression {
|
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||||
val reference = expression.statements.lastOrNull() as? IrFunctionReference ?: return super.visitBlock(expression)
|
val reference = expression.statements.lastOrNull() as? IrFunctionReference ?: return super.visitBlock(expression)
|
||||||
if (reference.shouldBeTreatedAsSuspendLambda() && reference !in inlineReferences) {
|
if (reference.isSuspend && reference.origin.isLambda && reference !in inlineReferences) {
|
||||||
assert(expression.statements.size == 2 && expression.statements[0] is IrFunction)
|
assert(expression.statements.size == 2 && expression.statements[0] is IrFunction)
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
val parent = currentDeclarationParent ?: error("No current declaration parent at ${reference.dump()}")
|
val parent = currentDeclarationParent ?: error("No current declaration parent at ${reference.dump()}")
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// !LANGUAGE: +SuspendConversion
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
// IGNORE_BACKEND: JVM, NATIVE
|
||||||
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
|
|
||||||
|
// `lambda` should not be wrapped in yet another object (so no OnInlineArgumentKt$box$1$1).
|
||||||
|
// CHECK_BYTECODE_LISTING
|
||||||
|
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
inline suspend fun runS(fn: suspend (String) -> String) = fn("O")
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var test = "Failed"
|
||||||
|
val lambda: (String) -> String = { it + "K" }
|
||||||
|
suspend { test = runS(lambda) }.startCoroutine(EmptyContinuation)
|
||||||
|
return test
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class OnInlineArgumentKt$box$1 {
|
||||||
|
// source: 'onInlineArgument.kt'
|
||||||
|
enclosing method OnInlineArgumentKt.box()Ljava/lang/String;
|
||||||
|
synthetic final field $lambda: kotlin.jvm.functions.Function1
|
||||||
|
synthetic final field $test: kotlin.jvm.internal.Ref$ObjectRef
|
||||||
|
field label: int
|
||||||
|
inner (anonymous) class OnInlineArgumentKt$box$1
|
||||||
|
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function1, p2: kotlin.coroutines.Continuation): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||||
|
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||||
|
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class OnInlineArgumentKt$box$lambda$1 {
|
||||||
|
// source: 'onInlineArgument.kt'
|
||||||
|
enclosing method OnInlineArgumentKt.box()Ljava/lang/String;
|
||||||
|
public final static field INSTANCE: OnInlineArgumentKt$box$lambda$1
|
||||||
|
inner (anonymous) class OnInlineArgumentKt$box$lambda$1
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public final @org.jetbrains.annotations.NotNull method invoke(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String
|
||||||
|
public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class OnInlineArgumentKt {
|
||||||
|
// source: 'onInlineArgument.kt'
|
||||||
|
inner (anonymous) class OnInlineArgumentKt$box$1
|
||||||
|
inner (anonymous) class OnInlineArgumentKt$box$lambda$1
|
||||||
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
|
private final static method runS$$forInline(p0: kotlin.jvm.functions.Function2, p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method runS(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
|
}
|
||||||
+5
@@ -9893,6 +9893,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
+5
@@ -9885,6 +9885,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void ignoreOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void ignoreSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void ignoreSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
+5
@@ -8678,6 +8678,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
Generated
+5
@@ -7373,6 +7373,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
Generated
+5
@@ -7373,6 +7373,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
+5
@@ -7373,6 +7373,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("onInlineArgument.kt")
|
||||||
|
public void testOnInlineArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
@TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt")
|
||||||
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user