JVM_IR: Generate $$forInline companion for suspend inline functions
Set isInline flag for $$forInline functions. Otherwise, SMAP will not be generated for inner objects/lambdas, leading to error in inliner.
This commit is contained in:
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2014 JetBrains s.r.o.
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
*
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ class JvmBackendContext(
|
|||||||
val continuationClassBuilders = mutableMapOf<IrSimpleFunction, ClassBuilder>()
|
val continuationClassBuilders = mutableMapOf<IrSimpleFunction, ClassBuilder>()
|
||||||
val suspendFunctionOriginalToView = mutableMapOf<IrFunction, IrFunction>()
|
val suspendFunctionOriginalToView = mutableMapOf<IrFunction, IrFunction>()
|
||||||
val suspendFunctionViewToOriginal = mutableMapOf<IrFunction, IrFunction>()
|
val suspendFunctionViewToOriginal = mutableMapOf<IrFunction, IrFunction>()
|
||||||
|
val originalToForInline = mutableMapOf<IrFunction, IrFunction>()
|
||||||
val fakeContinuation: IrExpression = createFakeContinuation(this)
|
val fakeContinuation: IrExpression = createFakeContinuation(this)
|
||||||
|
|
||||||
val staticDefaultStubs = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
val staticDefaultStubs = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
||||||
|
|||||||
+28
-4
@@ -407,13 +407,13 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
expression.dispatchReceiver?.let { receiver ->
|
expression.dispatchReceiver?.let { receiver ->
|
||||||
val type = if ((expression as? IrCall)?.superQualifierSymbol != null) receiver.asmType else callable.owner
|
val type = if ((expression as? IrCall)?.superQualifierSymbol != null) receiver.asmType else callable.owner
|
||||||
callGenerator.genValueAndPut(callee.dispatchReceiverParameter!!, receiver, type, this, data)
|
continuationAwareGenValueAndPut(receiver, type, callee.dispatchReceiverParameter!!, data, callGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
expression.extensionReceiver?.let { receiver ->
|
expression.extensionReceiver?.let { receiver ->
|
||||||
val type = callable.signature.valueParameters.singleOrNull { it.kind == JvmMethodParameterKind.RECEIVER }?.asmType
|
val type = callable.signature.valueParameters.singleOrNull { it.kind == JvmMethodParameterKind.RECEIVER }?.asmType
|
||||||
?: error("No single extension receiver parameter: ${callable.signature.valueParameters}")
|
?: error("No single extension receiver parameter: ${callable.signature.valueParameters}")
|
||||||
callGenerator.genValueAndPut(callee.extensionReceiverParameter!!, receiver, type, this, data)
|
continuationAwareGenValueAndPut(receiver, type, callee.extensionReceiverParameter!!, data, callGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator.beforeValueParametersStart()
|
callGenerator.beforeValueParametersStart()
|
||||||
@@ -421,7 +421,7 @@ class ExpressionCodegen(
|
|||||||
val arg = expression.getValueArgument(i)
|
val arg = expression.getValueArgument(i)
|
||||||
val parameterType = callable.valueParameterTypes[i]
|
val parameterType = callable.valueParameterTypes[i]
|
||||||
require(arg != null) { "Null argument in ExpressionCodegen for parameter ${irParameter.render()}" }
|
require(arg != null) { "Null argument in ExpressionCodegen for parameter ${irParameter.render()}" }
|
||||||
callGenerator.genValueAndPut(irParameter, arg, parameterType, this, data)
|
continuationAwareGenValueAndPut(arg, parameterType, irParameter, data, callGenerator)
|
||||||
}
|
}
|
||||||
|
|
||||||
expression.markLineNumber(true)
|
expression.markLineNumber(true)
|
||||||
@@ -431,7 +431,14 @@ class ExpressionCodegen(
|
|||||||
addSuspendMarker(mv, isStartNotEnd = true)
|
addSuspendMarker(mv, isStartNotEnd = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator.genCall(callable, this, expression)
|
if (irFunction.isInvokeSuspendOfContinuation()) {
|
||||||
|
// Do not inline callee to continuation, instead, call it
|
||||||
|
with(callable) {
|
||||||
|
mv.visitMethodInsn(invokeOpcode, owner.internalName, asmMethod.name, asmMethod.descriptor, isInterfaceMethod)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callGenerator.genCall(callable, this, expression)
|
||||||
|
}
|
||||||
|
|
||||||
if (callee.shouldGenerateSuspendMarkers()) {
|
if (callee.shouldGenerateSuspendMarkers()) {
|
||||||
// Check return type of non-lowered suspend call, in order to replace the result of the call with Unit,
|
// Check return type of non-lowered suspend call, in order to replace the result of the call with Unit,
|
||||||
@@ -465,6 +472,23 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In order to support java interop of inline suspend functions, we generate continuations of inline suspend functions.
|
||||||
|
// They should behave as ordinary suspend functions, i.e. we should not inline the content of the inline function into continuation.
|
||||||
|
// Thus, we should put its arguments to stack.
|
||||||
|
private fun continuationAwareGenValueAndPut(
|
||||||
|
arg: IrExpression,
|
||||||
|
parameterType: Type,
|
||||||
|
irParameter: IrValueParameter,
|
||||||
|
data: BlockInfo,
|
||||||
|
callGenerator: IrCallGenerator
|
||||||
|
) {
|
||||||
|
if (irFunction.isInvokeSuspendOfContinuation()) {
|
||||||
|
gen(arg, parameterType, irParameter.type, data)
|
||||||
|
} else {
|
||||||
|
callGenerator.genValueAndPut(irParameter, arg, parameterType, this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrFunction.shouldGenerateSuspendMarkers(): Boolean {
|
private fun IrFunction.shouldGenerateSuspendMarkers(): Boolean {
|
||||||
if (!isSuspend) return false
|
if (!isSuspend) return false
|
||||||
if (irFunction.shouldNotContainSuspendMarkers()) return false
|
if (irFunction.shouldNotContainSuspendMarkers()) return false
|
||||||
|
|||||||
+8
-4
@@ -14,6 +14,9 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
|
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
|
||||||
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
|
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||||
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
|
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -31,6 +34,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_N
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
@@ -125,17 +129,17 @@ open class FunctionCodegen(
|
|||||||
// We do not generate continuation and state-machine for synthetic accessors, bridges, and delegated members,
|
// We do not generate continuation and state-machine for synthetic accessors, bridges, and delegated members,
|
||||||
// in a sense, they are tail-call
|
// in a sense, they are tail-call
|
||||||
!isKnownToBeTailCall() &&
|
!isKnownToBeTailCall() &&
|
||||||
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without
|
|
||||||
!isInline &&
|
|
||||||
// This is suspend lambda parameter of inline function
|
// This is suspend lambda parameter of inline function
|
||||||
origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
|
origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
|
||||||
// This is just a template for inliner
|
// This is just a template for inliner
|
||||||
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE &&
|
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE &&
|
||||||
// Continuations are generated for suspendImpls
|
// Continuations are generated for suspendImpls
|
||||||
parentAsClass.functions.none { it.name.asString() == name.asString() + SUSPEND_IMPL_NAME_SUFFIX }
|
parentAsClass.functions.none { it.name.asString() == name.asString() + SUSPEND_IMPL_NAME_SUFFIX } &&
|
||||||
|
// $$forInline functions never have a continuation
|
||||||
|
origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
|
||||||
|
|
||||||
private fun continuationClass(): IrClass =
|
private fun continuationClass(): IrClass =
|
||||||
irFunction.body!!.statements[0] as IrClass
|
irFunction.body!!.statements.firstIsInstance() ?: error("No continuation class generated for ${irFunction.name}")
|
||||||
|
|
||||||
private fun IrFunction.getVisibilityForDefaultArgumentStub(): Int =
|
private fun IrFunction.getVisibilityForDefaultArgumentStub(): Int =
|
||||||
when (visibility) {
|
when (visibility) {
|
||||||
|
|||||||
+17
-6
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
|||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
|
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
@@ -23,11 +24,9 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
|||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -35,6 +34,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
@@ -80,10 +80,21 @@ class IrSourceCompilerForInline(
|
|||||||
|
|
||||||
private fun makeInlineNode(function: IrFunction, classCodegen: ClassCodegen, isLambda: Boolean): SMAPAndMethodNode {
|
private fun makeInlineNode(function: IrFunction, classCodegen: ClassCodegen, isLambda: Boolean): SMAPAndMethodNode {
|
||||||
var node: MethodNode? = null
|
var node: MethodNode? = null
|
||||||
val functionCodegen = object : FunctionCodegen(function, classCodegen, codegen.takeIf { isLambda }) {
|
val forInlineFunctionView =
|
||||||
|
if (function.isSuspend)
|
||||||
|
codegen.context.originalToForInline[codegen.context.suspendFunctionViewToOriginal[function]] ?: function
|
||||||
|
else function
|
||||||
|
val functionCodegen = object : FunctionCodegen(forInlineFunctionView, classCodegen, codegen.takeIf { isLambda }) {
|
||||||
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
|
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
|
||||||
val asmMethod = signature.asmMethod
|
val asmMethod = signature.asmMethod
|
||||||
node = MethodNode(Opcodes.API_VERSION, flags, asmMethod.name, asmMethod.descriptor, signature.genericsSignature, null)
|
node = MethodNode(
|
||||||
|
Opcodes.API_VERSION,
|
||||||
|
flags,
|
||||||
|
asmMethod.name.removeSuffix(FOR_INLINE_SUFFIX),
|
||||||
|
asmMethod.descriptor,
|
||||||
|
signature.genericsSignature,
|
||||||
|
null
|
||||||
|
)
|
||||||
return wrapWithMaxLocalCalc(node!!)
|
return wrapWithMaxLocalCalc(node!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.inline.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
@@ -279,9 +279,13 @@ fun IrDeclarationWithVisibility.isInlineOnlyOrReifiable(): Boolean =
|
|||||||
this is IrFunction && (isReifiable() || isInlineOnly())
|
this is IrFunction && (isReifiable() || isInlineOnly())
|
||||||
|
|
||||||
fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean =
|
fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean =
|
||||||
isInlineOnlyOrReifiable() ||
|
isInlineOnlyOrReifiable() || isInlineOnlyPrivateInBytecode()
|
||||||
(this is IrSimpleFunction && isSuspend && isInline &&
|
|
||||||
(valueParameters.any { it.isCrossinline } || visibility === Visibilities.PRIVATE))
|
fun IrDeclarationWithVisibility.isInlineOnlyPrivateInBytecode(): Boolean =
|
||||||
|
(this is IrFunction && isInlineOnly()) || isPrivateInlineSuspend()
|
||||||
|
|
||||||
|
private fun IrDeclarationWithVisibility.isPrivateInlineSuspend(): Boolean =
|
||||||
|
this is IrFunction && isSuspend && isInline && visibility == Visibilities.PRIVATE
|
||||||
|
|
||||||
fun IrFunction.isInlineOnly() =
|
fun IrFunction.isInlineOnly() =
|
||||||
isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||||
|
|||||||
+26
-17
@@ -47,16 +47,10 @@ internal val addContinuationPhase = makeIrFilePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private class AddContinuationLowering(private val context: JvmBackendContext) : FileLoweringPass {
|
private class AddContinuationLowering(private val context: JvmBackendContext) : FileLoweringPass {
|
||||||
private val functionsToAdd = mutableMapOf<IrClass, MutableSet<IrFunction>>()
|
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val (suspendLambdas, inlineLambdas) = markSuspendLambdas(irFile)
|
val (suspendLambdas, inlineLambdas) = markSuspendLambdas(irFile)
|
||||||
transformSuspendFunctions(irFile, (suspendLambdas.map { it.function } + inlineLambdas).toSet())
|
transformSuspendFunctions(irFile, (suspendLambdas.map { it.function } + inlineLambdas).toSet())
|
||||||
for ((clazz, functions) in functionsToAdd) {
|
|
||||||
for (function in functions) {
|
|
||||||
clazz.declarations.add(function)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transformReferencesToSuspendLambdas(irFile, suspendLambdas)
|
transformReferencesToSuspendLambdas(irFile, suspendLambdas)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,11 +527,19 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
return static
|
return static
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Generate two copies of inline suspend functions
|
|
||||||
private fun transformSuspendFunctions(irFile: IrFile, suspendAndInlineLambdas: Set<IrFunction>) {
|
private fun transformSuspendFunctions(irFile: IrFile, suspendAndInlineLambdas: Set<IrFunction>) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
private val functionsStack = arrayListOf<IrFunction>()
|
private val functionsStack = arrayListOf<IrFunction>()
|
||||||
private val suspendFunctionsCapturingCrossinline = mutableSetOf<IrFunction>()
|
private val suspendFunctionsCapturingCrossinline = mutableSetOf<IrFunction>()
|
||||||
|
private val functionsToAdd = arrayListOf<MutableSet<IrFunction>>()
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
|
functionsToAdd.push(mutableSetOf())
|
||||||
|
val res = super.visitClass(declaration)
|
||||||
|
(res as IrClass).declarations.addAll(functionsToAdd.peek()!!)
|
||||||
|
functionsToAdd.pop()
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
functionsStack.push(declaration)
|
functionsStack.push(declaration)
|
||||||
@@ -546,27 +548,34 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
if (skip(function)) return function
|
if (skip(function)) return function
|
||||||
|
|
||||||
function as IrSimpleFunction
|
function as IrSimpleFunction
|
||||||
if (function in suspendFunctionsCapturingCrossinline) {
|
if (function in suspendFunctionsCapturingCrossinline || function.isInline) {
|
||||||
val newFunction = buildFun {
|
val newFunction = buildFunWithDescriptorForInlining(function.descriptor) {
|
||||||
name = Name.identifier(function.name.asString() + FOR_INLINE_SUFFIX)
|
name = Name.identifier(function.name.asString() + FOR_INLINE_SUFFIX)
|
||||||
returnType = function.returnType
|
returnType = function.returnType
|
||||||
modality = function.modality
|
modality = function.modality
|
||||||
isSuspend = function.isSuspend
|
isSuspend = function.isSuspend
|
||||||
origin = JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
isInline = function.isInline
|
||||||
|
origin =
|
||||||
|
if (function.isInline) JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE
|
||||||
|
else JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
||||||
}.apply {
|
}.apply {
|
||||||
|
copyTypeParameters(function.typeParameters)
|
||||||
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this)
|
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this)
|
||||||
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
|
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
|
||||||
function.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
function.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
||||||
body = function.copyBodyTo(this)
|
body = function.copyBodyTo(this)
|
||||||
copyAttributes(function)
|
copyAttributes(function)
|
||||||
}
|
}
|
||||||
registerNewFunction(function.parentAsClass, newFunction)
|
registerNewFunction(newFunction)
|
||||||
|
if (function.isInline) {
|
||||||
|
context.originalToForInline[function] = newFunction
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val newFunction = if (function.isOverridable) {
|
val newFunction = if (function.isOverridable) {
|
||||||
// Create static method for the suspend state machine method so that reentering the method
|
// Create static method for the suspend state machine method so that reentering the method
|
||||||
// does not lead to virtual dispatch to the wrong method.
|
// does not lead to virtual dispatch to the wrong method.
|
||||||
registerNewFunction(function.parentAsClass, function)
|
registerNewFunction(function)
|
||||||
createStaticSuspendImpl(function)
|
createStaticSuspendImpl(function)
|
||||||
} else function
|
} else function
|
||||||
|
|
||||||
@@ -584,11 +593,15 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun skip(function: IrFunction) =
|
private fun skip(function: IrFunction) =
|
||||||
!function.isSuspend || function in suspendAndInlineLambdas || function.isInline || function.body == null ||
|
!function.isSuspend || function in suspendAndInlineLambdas || function.body == null ||
|
||||||
function.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
function.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
|
||||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||||
function.parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
function.parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||||
|
|
||||||
|
private fun registerNewFunction(function: IrFunction) {
|
||||||
|
functionsToAdd.peek()!!.add(function)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFieldAccess(expression: IrFieldAccessExpression): IrExpression {
|
override fun visitFieldAccess(expression: IrFieldAccessExpression): IrExpression {
|
||||||
val result = super.visitFieldAccess(expression)
|
val result = super.visitFieldAccess(expression)
|
||||||
val function = functionsStack.peek() ?: return result
|
val function = functionsStack.peek() ?: return result
|
||||||
@@ -602,10 +615,6 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerNewFunction(container: IrClass, function: IrFunction) {
|
|
||||||
functionsToAdd.getOrPut(container) { mutableSetOf() }.add(function)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun markSuspendLambdas(irElement: IrElement): Pair<List<SuspendLambdaInfo>, List<IrFunction>> {
|
private fun markSuspendLambdas(irElement: IrElement): Pair<List<SuspendLambdaInfo>, List<IrFunction>> {
|
||||||
val suspendLambdas = arrayListOf<SuspendLambdaInfo>()
|
val suspendLambdas = arrayListOf<SuspendLambdaInfo>()
|
||||||
val capturesCrossinline = mutableSetOf<IrCallableReference>()
|
val capturesCrossinline = mutableSetOf<IrCallableReference>()
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// COMMON_COROUTINES_TEST
|
// COMMON_COROUTINES_TEST
|
||||||
|
|||||||
Vendored
+9
@@ -31,6 +31,14 @@ final class InlineWithoutStateMachineKt$suspendHere$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 InlineWithoutStateMachineKt$suspendThere$1 {
|
||||||
|
field label: int
|
||||||
|
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||||
|
public method <init>(p0: 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 InlineWithoutStateMachineKt {
|
public final class InlineWithoutStateMachineKt {
|
||||||
inner class InlineWithoutStateMachineKt$box$1
|
inner class InlineWithoutStateMachineKt$box$1
|
||||||
@@ -38,5 +46,6 @@ public final class InlineWithoutStateMachineKt {
|
|||||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||||
public final static @org.jetbrains.annotations.Nullable method complexSuspend(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method complexSuspend(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method suspendThere$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+10
-1
@@ -76,6 +76,14 @@ final class flow/InnerObjectRetransformationKt$check$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$collect$1 {
|
||||||
|
field label: int
|
||||||
|
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||||
|
public method <init>(p0: 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
|
||||||
final class flow/InnerObjectRetransformationKt$collect$2$emit$1 {
|
final class flow/InnerObjectRetransformationKt$collect$2$emit$1 {
|
||||||
field label: int
|
field label: int
|
||||||
@@ -164,7 +172,8 @@ public final class flow/InnerObjectRetransformationKt {
|
|||||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||||
public final static @org.jetbrains.annotations.Nullable method check(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method check(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
private final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object
|
public final static @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
|
public final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): flow.Flow
|
public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): flow.Flow
|
||||||
public final static @org.jetbrains.annotations.NotNull method flowWith(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): flow.Flow
|
public final static @org.jetbrains.annotations.NotNull method flowWith(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): flow.Flow
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user