JVM_IR: improve suspend tail call detection.
* TailCallOptimizationLowering should go into local classes in order to transform their suspend methods; * the check for invokes of noinline lambda arguments in codegen was incorrect, as it also returned true for calls of lambdas stored in local variables; * IrInlineCodegen should mark non-inlinable arguments used as inline suspend parameters; * detection of suspend/inline call sites was incorrect (or maybe it's the `compilationContextDescriptor` that was incorrect?..)
This commit is contained in:
@@ -117,7 +117,6 @@ class JvmBackendContext(
|
|||||||
val continuationClassBuilders = mutableMapOf<IrSimpleFunction, ClassBuilder>()
|
val continuationClassBuilders = mutableMapOf<IrSimpleFunction, ClassBuilder>()
|
||||||
val suspendFunctionOriginalToView = mutableMapOf<IrFunction, IrFunction>()
|
val suspendFunctionOriginalToView = mutableMapOf<IrFunction, IrFunction>()
|
||||||
val suspendFunctionOriginalToStub = mutableMapOf<IrFunction, IrFunction>()
|
val suspendFunctionOriginalToStub = mutableMapOf<IrFunction, IrFunction>()
|
||||||
val suspendTailCallsWithUnitReplacement = mutableSetOf<IrAttributeContainer>()
|
|
||||||
val fakeContinuation: IrExpression = createFakeContinuation(this)
|
val fakeContinuation: IrExpression = createFakeContinuation(this)
|
||||||
|
|
||||||
val staticDefaultStubs = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
val staticDefaultStubs = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
||||||
|
|||||||
+16
-29
@@ -476,28 +476,22 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunctionAccessExpression.isSuspensionPoint(): Boolean {
|
private fun IrFunctionAccessExpression.isInvokeOfInlineLambda(): Boolean = when (val receiver = dispatchReceiver) {
|
||||||
val owner = symbol.owner
|
is IrGetField -> receiver.symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
||||||
return when {
|
is IrGetValue -> receiver.origin == IrStatementOrigin.VARIABLE_AS_FUNCTION &&
|
||||||
// Only suspend functions are suspension points
|
(receiver.symbol.owner as? IrValueParameter)?.isNoinline == false
|
||||||
!owner.isSuspend -> false
|
else -> false
|
||||||
// But not inside continuation classes and bridges
|
}
|
||||||
irFunction.shouldNotContainSuspendMarkers() -> false
|
|
||||||
// Noinline function are always suspension points
|
private fun IrFunctionAccessExpression.isSuspensionPoint(): Boolean = when {
|
||||||
!owner.isInline -> true
|
!symbol.owner.isSuspend || irFunction.shouldNotContainSuspendMarkers() -> false
|
||||||
// The suspend intrinsics are, albeit inline, also suspension points
|
// Copy-pasted bytecode blocks are not suspension points.
|
||||||
owner.fqNameForIrSerialization == FqName("kotlin.coroutines.intrinsics.IntrinsicsKt.suspendCoroutineUninterceptedOrReturn") -> true
|
symbol.owner.isInline ->
|
||||||
// Inside $$forInline functions crossinline calls are (usually) not suspension points, otherwise, flow will be pessimized
|
symbol.owner.fqNameForIrSerialization == FqName("kotlin.coroutines.intrinsics.IntrinsicsKt.suspendCoroutineUninterceptedOrReturn")
|
||||||
(dispatchReceiver as? IrGetField)?.symbol?.owner?.origin ==
|
// This includes inline lambdas, but only in functions intended for the inliner; in others, they stay as `f.invoke()`.
|
||||||
LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE ->
|
isInvokeOfInlineLambda() ->
|
||||||
irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE && irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
||||||
// The same goes for inline lambdas
|
else -> true
|
||||||
(dispatchReceiver as? IrGetValue)?.let {
|
|
||||||
it.origin == IrStatementOrigin.VARIABLE_AS_FUNCTION && (it.symbol.owner as? IrValueParameter)?.isNoinline != true
|
|
||||||
} == true -> irFunction.origin != FOR_INLINE_STATE_MACHINE_TEMPLATE
|
|
||||||
// Otherwise, this is normal inline call, ergo not a suspension point
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable, data: BlockInfo): PromisedValue {
|
override fun visitVariable(declaration: IrVariable, data: BlockInfo): PromisedValue {
|
||||||
@@ -661,13 +655,6 @@ class ExpressionCodegen(
|
|||||||
val returnType = if (owner == irFunction) signature.returnType else methodSignatureMapper.mapReturnType(owner)
|
val returnType = if (owner == irFunction) signature.returnType else methodSignatureMapper.mapReturnType(owner)
|
||||||
val afterReturnLabel = Label()
|
val afterReturnLabel = Label()
|
||||||
expression.value.accept(this, data).coerce(returnType, owner.returnType).materialize()
|
expression.value.accept(this, data).coerce(returnType, owner.returnType).materialize()
|
||||||
// We replaced COERTION_TO_UNIT with IrReturn during TailCallOptimizationLowering.
|
|
||||||
// Generate POP GETSTATIC kotlin/Unit.INSTANCE now.
|
|
||||||
// Otherwise, tail-call optimization will not work. See tailSuspendUnitFun.kt test.
|
|
||||||
if (expression in context.suspendTailCallsWithUnitReplacement) {
|
|
||||||
mv.pop()
|
|
||||||
mv.getstatic("kotlin/Unit", "INSTANCE", "Lkotlin/Unit;")
|
|
||||||
}
|
|
||||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
||||||
expression.markLineNumber(startOffset = true)
|
expression.markLineNumber(startOffset = true)
|
||||||
if (isNonLocalReturn) {
|
if (isNonLocalReturn) {
|
||||||
|
|||||||
+13
-18
@@ -22,11 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
|
||||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -87,11 +83,9 @@ class IrInlineCodegen(
|
|||||||
super.genValueAndPut(irValueParameter, argumentExpression, parameterType, codegen, blockInfo)
|
super.genValueAndPut(irValueParameter, argumentExpression, parameterType, codegen, blockInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irValueParameter.isInlineParameter(
|
// after transformation inlinable lambda parameter with default value would have nullable type: check default value type first
|
||||||
/*after transformation inlinable lambda parameter with default value would have nullable type: check default value type first*/
|
val isInlineParameter = irValueParameter.isInlineParameter(irValueParameter.defaultValue?.expression?.type ?: irValueParameter.type)
|
||||||
irValueParameter.defaultValue?.expression?.type ?: irValueParameter.type
|
if (isInlineParameter && isInlineIrExpression(argumentExpression)) {
|
||||||
) && isInlineIrExpression(argumentExpression)
|
|
||||||
) {
|
|
||||||
val irReference: IrFunctionReference =
|
val irReference: IrFunctionReference =
|
||||||
(argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
(argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
||||||
val boundReceiver = argumentExpression.statements.filterIsInstance<IrVariable>().singleOrNull()
|
val boundReceiver = argumentExpression.statements.filterIsInstance<IrVariable>().singleOrNull()
|
||||||
@@ -107,9 +101,14 @@ class IrInlineCodegen(
|
|||||||
val kind = when (irValueParameter.origin) {
|
val kind = when (irValueParameter.origin) {
|
||||||
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION -> ValueKind.DEFAULT_MASK
|
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION -> ValueKind.DEFAULT_MASK
|
||||||
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT
|
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT
|
||||||
else -> if (argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE)
|
else -> when {
|
||||||
ValueKind.DEFAULT_PARAMETER
|
argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE ->
|
||||||
else ValueKind.CAPTURED
|
ValueKind.DEFAULT_PARAMETER
|
||||||
|
// TODO ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND?
|
||||||
|
isInlineParameter && irValueParameter.type.isSuspendFunctionTypeOrSubtype() ->
|
||||||
|
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
|
||||||
|
else -> ValueKind.GENERAL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val onStack = when {
|
val onStack = when {
|
||||||
@@ -130,11 +129,7 @@ class IrInlineCodegen(
|
|||||||
|
|
||||||
|
|
||||||
//TODO support default argument erasure
|
//TODO support default argument erasure
|
||||||
if (!processDefaultMaskOrMethodHandler(
|
if (!processDefaultMaskOrMethodHandler(onStack, kind)) {
|
||||||
onStack,
|
|
||||||
kind
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toKotlinType())
|
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toKotlinType())
|
||||||
putArgumentOrCapturedToLocalVal(expectedType, onStack, -1, irValueParameter.index, kind)
|
putArgumentOrCapturedToLocalVal(expectedType, onStack, -1, irValueParameter.index, kind)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -89,8 +89,8 @@ class IrSourceCompilerForInline(
|
|||||||
root.classCodegen.type.internalName,
|
root.classCodegen.type.internalName,
|
||||||
root.signature.asmMethod.name,
|
root.signature.asmMethod.name,
|
||||||
root.signature.asmMethod.descriptor,
|
root.signature.asmMethod.descriptor,
|
||||||
compilationContextFunctionDescriptor.isInlineOrInsideInline(),
|
root.irFunction.descriptor.isInlineOrInsideInline(),
|
||||||
compilationContextFunctionDescriptor.isSuspend,
|
root.irFunction.isSuspend,
|
||||||
findElement()?.let { CodegenUtil.getLineNumberForElement(it, false) } ?: 0
|
findElement()?.let { CodegenUtil.getLineNumberForElement(it, false) } ?: 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-66
@@ -11,21 +11,18 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.anyOfOverriddenFunctionsReturnsNonUnit
|
import org.jetbrains.kotlin.backend.jvm.codegen.anyOfOverriddenFunctionsReturnsNonUnit
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isKnownToBeTailCall
|
import org.jetbrains.kotlin.backend.jvm.codegen.isKnownToBeTailCall
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -35,72 +32,60 @@ internal val tailCallOptimizationPhase = makeIrFilePhase(
|
|||||||
"Add or move returns to suspension points on tail-call positions"
|
"Add or move returns to suspension points on tail-call positions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Make this lowering common
|
// Find all tail-calls inside suspend function. We should add IrReturn before them, so the codegen will generate
|
||||||
private class TailCallOptimizationLowering(private val context: JvmBackendContext) : IrElementVisitorVoid, FileLoweringPass {
|
// code which is understandable by old BE's tail-call optimizer.
|
||||||
|
private class TailCallOptimizationLowering(private val context: JvmBackendContext) : FileLoweringPass {
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
visitFile(irFile)
|
irFile.transformChildren(object : IrElementTransformer<TailCallOptimizationData?> {
|
||||||
}
|
override fun visitFunction(declaration: IrFunction, data: TailCallOptimizationData?) =
|
||||||
|
super.visitFunction(declaration, TailCallOptimizationData(declaration))
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitCall(expression: IrCall, data: TailCallOptimizationData?): IrExpression {
|
||||||
element.acceptChildrenVoid(this)
|
val transformed = super.visitCall(expression, data) as IrExpression
|
||||||
}
|
return if (data == null || expression !in data.tailCalls) transformed else IrReturnImpl(
|
||||||
|
expression.startOffset, expression.endOffset, context.irBuiltIns.nothingType, data.function.symbol,
|
||||||
override fun visitFunction(function: IrFunction) {
|
if (data.returnsUnit) transformed.coerceToUnit() else transformed
|
||||||
if (!function.isSuspend || function.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA || function.isKnownToBeTailCall()) return
|
|
||||||
// Disable tail-call optimization for functions, returning Unit and overriding function, returning non-unit.
|
|
||||||
if (function.returnType.isUnit() && function.anyOfOverriddenFunctionsReturnsNonUnit()) return
|
|
||||||
|
|
||||||
val tailCalls = mutableSetOf<IrCall>()
|
|
||||||
|
|
||||||
// Find all tail-calls inside suspend function.
|
|
||||||
// We should add IrReturn before them, so the codegen will generate code, which is understandable by old BE's tail-call optimizer.
|
|
||||||
// This function collect all possible tail-calls, if they are not prepended by IrReturns, so we can prepend them.
|
|
||||||
// If the call has IrReturn before it, we do not need to add another one.
|
|
||||||
// If the call is inside a branch of `when` statement (or `if`, which is lowered to `when`), go through the branches and
|
|
||||||
// find tail-calls there.
|
|
||||||
fun findCallsOnTailPositionWithoutImmediateReturn(statement: IrStatement, immediateReturn: Boolean = false) {
|
|
||||||
when (statement) {
|
|
||||||
is IrCall -> if (statement.isSuspend && !immediateReturn) {
|
|
||||||
tailCalls += statement
|
|
||||||
}
|
|
||||||
is IrBlock -> findCallsOnTailPositionWithoutImmediateReturn(
|
|
||||||
statement.statements.findTailCall(function.returnType.isUnit()) ?: return
|
|
||||||
)
|
)
|
||||||
is IrWhen -> for (branch in statement.branches) {
|
}
|
||||||
findCallsOnTailPositionWithoutImmediateReturn(branch.result)
|
}, null)
|
||||||
}
|
}
|
||||||
is IrReturn -> findCallsOnTailPositionWithoutImmediateReturn(statement.value, immediateReturn = true)
|
|
||||||
is IrTypeOperatorCall -> if (statement.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) {
|
private fun IrExpression.coerceToUnit() = IrTypeOperatorCallImpl(
|
||||||
findCallsOnTailPositionWithoutImmediateReturn(statement.argument)
|
startOffset, endOffset, context.irBuiltIns.unitType, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType, this
|
||||||
}
|
)
|
||||||
else -> {
|
}
|
||||||
// Not a call, or something containing a tail-call, break
|
|
||||||
// TODO: Support binary logical operations and elvis, though. KT-23826 and KT-23825
|
private class TailCallOptimizationData(val function: IrFunction) {
|
||||||
}
|
val returnsUnit = function.returnType.isUnit()
|
||||||
|
val tailCalls = mutableSetOf<IrCall>()
|
||||||
|
|
||||||
|
// Collect all tail calls, including those nested in `when`s, which are not arguments to `return`s.
|
||||||
|
private fun findCallsOnTailPositionWithoutImmediateReturn(statement: IrStatement, immediateReturn: Boolean = false) {
|
||||||
|
when {
|
||||||
|
statement is IrCall && statement.isSuspend && !immediateReturn && (returnsUnit || statement.type == function.returnType) ->
|
||||||
|
tailCalls += statement
|
||||||
|
statement is IrBlock ->
|
||||||
|
statement.statements.findTailCall(returnsUnit)?.let(::findCallsOnTailPositionWithoutImmediateReturn)
|
||||||
|
statement is IrWhen ->
|
||||||
|
statement.branches.forEach { findCallsOnTailPositionWithoutImmediateReturn(it.result) }
|
||||||
|
statement is IrReturn ->
|
||||||
|
findCallsOnTailPositionWithoutImmediateReturn(statement.value, immediateReturn = true)
|
||||||
|
statement is IrTypeOperatorCall && statement.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ->
|
||||||
|
findCallsOnTailPositionWithoutImmediateReturn(statement.argument)
|
||||||
|
// TODO: Support binary logical operations and elvis, though. KT-23826 and KT-23825
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (function.isSuspend && function.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && !function.isKnownToBeTailCall() &&
|
||||||
|
// See `disableTailCallOptimizationForFunctionReturningUnit` in `generateStateMachineForNamedFunction`:
|
||||||
|
!(returnsUnit && function.anyOfOverriddenFunctionsReturnsNonUnit())
|
||||||
|
) {
|
||||||
|
when (val body = function.body) {
|
||||||
|
is IrBlockBody -> body.statements.findTailCall(returnsUnit)?.let(::findCallsOnTailPositionWithoutImmediateReturn)
|
||||||
|
is IrExpressionBody -> findCallsOnTailPositionWithoutImmediateReturn(body.expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when (val body = function.body) {
|
|
||||||
null -> return
|
|
||||||
is IrBlockBody -> findCallsOnTailPositionWithoutImmediateReturn(
|
|
||||||
body.statements.findTailCall(function.returnType.isUnit()) ?: return
|
|
||||||
)
|
|
||||||
is IrExpressionBody -> findCallsOnTailPositionWithoutImmediateReturn(body.expression)
|
|
||||||
else -> error("Unexpected $body")
|
|
||||||
}
|
|
||||||
|
|
||||||
function.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitCall(call: IrCall): IrExpression {
|
|
||||||
if (call !in tailCalls) return call
|
|
||||||
if (!function.returnType.isUnit() && call.type != function.returnType) return call
|
|
||||||
// Replace ARETURN with { POP, GETSTATIC kotlin/Unit.INSTANCE, ARETURN } during codegen later.
|
|
||||||
// Otherwise, additional CHECKCAST will break tail-call optimization
|
|
||||||
if (function.returnType.isUnit()) {
|
|
||||||
context.suspendTailCallsWithUnitReplacement += call.attributeOwnerId
|
|
||||||
}
|
|
||||||
return IrReturnImpl(call.startOffset, call.endOffset, context.irBuiltIns.nothingType, function.symbol, call)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-4
@@ -33,7 +33,6 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2 {
|
|||||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2
|
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$2
|
||||||
public method <init>(p0: Sink): void
|
public method <init>(p0: Sink): void
|
||||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
|
|||||||
synthetic final field $this$inlined: SourceCrossinline
|
synthetic final field $this$inlined: SourceCrossinline
|
||||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
|
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
|
||||||
public method <init>(p0: SourceCrossinline): void
|
public method <init>(p0: SourceCrossinline): void
|
||||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +64,6 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1 {
|
|||||||
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
inner class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
||||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +323,6 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
|||||||
synthetic final field $start$inlined: int
|
synthetic final field $start$inlined: int
|
||||||
inner class CrossinlineKt$range$$inlined$source$1
|
inner class CrossinlineKt$range$$inlined$source$1
|
||||||
public method <init>(p0: int, p1: int): void
|
public method <init>(p0: int, p1: int): void
|
||||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
-46
@@ -19,63 +19,25 @@ final class flow/InnerObjectRetransformationKt$box$1 {
|
|||||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull 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 flow/InnerObjectRetransformationKt$check$$inlined$collect$1$1 {
|
|
||||||
field label: int
|
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$collect$1
|
|
||||||
public method <init>(p0: flow.InnerObjectRetransformationKt$check$$inlined$collect$1, p1: kotlin.coroutines.Continuation): void
|
|
||||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$collect$1 {
|
public final class flow/InnerObjectRetransformationKt$check$$inlined$collect$1 {
|
||||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$collect$1
|
inner class flow/InnerObjectRetransformationKt$check$$inlined$collect$1
|
||||||
public method <init>(): void
|
public method <init>(): void
|
||||||
public @org.jetbrains.annotations.Nullable method emit$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
|
||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
|
||||||
final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1$1 {
|
|
||||||
field L$0: java.lang.Object
|
|
||||||
field L$1: java.lang.Object
|
|
||||||
field L$2: java.lang.Object
|
|
||||||
field label: int
|
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flow$1
|
|
||||||
public method <init>(p0: flow.InnerObjectRetransformationKt$check$$inlined$flow$1, p1: kotlin.coroutines.Continuation): void
|
|
||||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
|
public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
|
||||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$flow$1
|
inner class flow/InnerObjectRetransformationKt$check$$inlined$flow$1
|
||||||
public method <init>(): void
|
public method <init>(): void
|
||||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
|
||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
|
||||||
final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 {
|
|
||||||
field L$0: java.lang.Object
|
|
||||||
field L$1: java.lang.Object
|
|
||||||
field L$2: java.lang.Object
|
|
||||||
field label: int
|
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
|
||||||
public method <init>(p0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1, p1: kotlin.coroutines.Continuation): void
|
|
||||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1 {
|
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1 {
|
||||||
synthetic final field $this$inlined: flow.Flow
|
synthetic final field $this$inlined: flow.Flow
|
||||||
inner class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
inner class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
||||||
public method <init>(p0: flow.Flow): void
|
public method <init>(p0: flow.Flow): void
|
||||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,11 +96,7 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
|
||||||
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 {
|
||||||
field L$0: java.lang.Object
|
|
||||||
field L$1: java.lang.Object
|
|
||||||
field L$2: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||||
@@ -157,11 +115,7 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
|
||||||
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 {
|
final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 {
|
||||||
field L$0: java.lang.Object
|
|
||||||
field L$1: java.lang.Object
|
|
||||||
field L$2: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||||
|
|||||||
-12
@@ -3,17 +3,6 @@ public interface Base {
|
|||||||
public abstract @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
public abstract @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
|
||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
|
||||||
final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$1 {
|
|
||||||
field L$0: java.lang.Object
|
|
||||||
field label: int
|
|
||||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
|
||||||
synthetic final field this$0: Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
|
||||||
public method <init>(p0: Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1, p1: kotlin.coroutines.Continuation): void
|
|
||||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2 {
|
public final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2 {
|
||||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
||||||
@@ -28,7 +17,6 @@ public final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1 {
|
|||||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
||||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2
|
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2
|
||||||
public method <init>(): void
|
public method <init>(): void
|
||||||
public @org.jetbrains.annotations.Nullable method generic$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
|
||||||
public @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
public @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
Reference in New Issue
Block a user