From 52febbcc07aa58cd98294f73b9cb801bba86c2c6 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Tue, 22 Oct 2019 17:13:59 +0200 Subject: [PATCH] [JVM_IR] Support default interface suspend functions. Do this by reordering the lowerings so that the lowering that adds continuations happen after default methods have been eliminated if needed. Mark more functions as known to be tail-calls: bridges and delegated members. Preserve source info and annotations when creating replacement functions. --- .../ir/builders/declarations/declarationBuilders.kt | 8 ++++---- .../src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt | 4 ++-- .../kotlin/backend/jvm/codegen/CoroutineCodegen.kt | 12 ++++++++++-- .../kotlin/backend/jvm/codegen/FunctionCodegen.kt | 3 ++- .../backend/jvm/lower/InterfaceDelegationLowering.kt | 3 ++- .../codegen/box/coroutines/delegatedSuspendMember.kt | 1 - .../inlineClasses/bridgeGenerationCrossinline.kt | 1 - .../inlineClasses/bridgeGenerationNonInline.kt | 1 - .../codegen/box/coroutines/suspendDefaultImpl.kt | 1 - .../suspendFunctionAsCoroutine/superCallInterface.kt | 1 - 10 files changed, 20 insertions(+), 15 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt index 128495024d4..d17807a264a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt @@ -7,10 +7,8 @@ package org.jetbrains.kotlin.ir.builders.declarations import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.ir.copyTo -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.symbols.impl.* @@ -117,6 +115,8 @@ inline fun IrProperty.addSetter(builder: IrFunctionBuilder.() -> Unit = {}): IrS fun IrFunctionBuilder.buildFun(originalDescriptor: FunctionDescriptor? = null): IrFunctionImpl { val wrappedDescriptor = if (originalDescriptor is DescriptorWithContainerSource) WrappedFunctionDescriptorWithContainerSource(originalDescriptor.containerSource) + else if (originalDescriptor != null) + WrappedSimpleFunctionDescriptor(originalDescriptor) else WrappedSimpleFunctionDescriptor() return IrFunctionImpl( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index e93ecd690f6..1128bc86338 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -217,8 +217,6 @@ private val jvmFilePhases = returnableBlocksPhase then localDeclarationsPhase then - addContinuationPhase then - jvmOverloadsAnnotationPhase then jvmDefaultConstructorPhase then @@ -235,6 +233,8 @@ private val jvmFilePhases = interfaceSuperCallsPhase then interfaceDefaultCallsPhase then + addContinuationPhase then + innerClassesPhase then innerClassConstructorCallsPhase then forLoopsPhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index e909be88719..c92644c2279 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -108,8 +108,16 @@ internal fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspen (parent as? IrClass)?.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL internal fun IrFunction.isKnownToBeTailCall(): Boolean = - origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR || - isInvokeOfSuspendCallableReference() + when (origin) { + IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, + JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, + JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE, + JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC, + IrDeclarationOrigin.BRIDGE, + IrDeclarationOrigin.BRIDGE_SPECIAL, + IrDeclarationOrigin.DELEGATED_MEMBER -> true + else -> isInvokeOfSuspendCallableReference() + } internal fun IrFunction.shouldNotContainSuspendMarkers(context: JvmBackendContext): Boolean = isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index e29130b4e79..7f9841a5ba5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -78,7 +78,8 @@ open class FunctionCodegen( val continuationClassBuilder = context.continuationClassBuilders[irClass] methodVisitor = when { irFunction.isSuspend && - // We do not generate continuation and state-machine for synthetic accessors, in a sense, they are tail-call + // We do not generate continuation and state-machine for synthetic accessors, bridges, and delegated members, + // in a sense, they are tail-call !irFunction.isKnownToBeTailCall() && // TODO: We should generate two versions of inline suspend function: one with state-machine and one without !irFunction.isInline -> diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index d411732b884..9bf3e946f68 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.lower.createIrBuilder 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.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.descriptors.Modality @@ -108,7 +109,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl IrFunctionImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, - IrDeclarationOrigin.DEFINED, + JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE, IrSimpleFunctionSymbolImpl(descriptor), classOverride.name, Visibilities.PUBLIC, diff --git a/compiler/testData/codegen/box/coroutines/delegatedSuspendMember.kt b/compiler/testData/codegen/box/coroutines/delegatedSuspendMember.kt index ffb472ab7bf..0ab41fbf21d 100644 --- a/compiler/testData/codegen/box/coroutines/delegatedSuspendMember.kt +++ b/compiler/testData/codegen/box/coroutines/delegatedSuspendMember.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationCrossinline.kt b/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationCrossinline.kt index fda7a7d9eec..019248de7f6 100644 --- a/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationCrossinline.kt +++ b/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationCrossinline.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt b/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt index 04776cee904..cc9552b170f 100644 --- a/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt +++ b/compiler/testData/codegen/box/coroutines/inlineClasses/bridgeGenerationNonInline.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/suspendDefaultImpl.kt b/compiler/testData/codegen/box/coroutines/suspendDefaultImpl.kt index 9033ec08dd0..06f7be45741 100644 --- a/compiler/testData/codegen/box/coroutines/suspendDefaultImpl.kt +++ b/compiler/testData/codegen/box/coroutines/suspendDefaultImpl.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt b/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt index f55f0a1f586..cda43f8cee3 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST