[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.
This commit is contained in:
Mads Ager
2019-10-22 17:13:59 +02:00
committed by Ilmir Usmanov
parent d16a1b14d8
commit 52febbcc07
10 changed files with 20 additions and 15 deletions
@@ -7,10 +7,8 @@ package org.jetbrains.kotlin.ir.builders.declarations
import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.symbols.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 { fun IrFunctionBuilder.buildFun(originalDescriptor: FunctionDescriptor? = null): IrFunctionImpl {
val wrappedDescriptor = if (originalDescriptor is DescriptorWithContainerSource) val wrappedDescriptor = if (originalDescriptor is DescriptorWithContainerSource)
WrappedFunctionDescriptorWithContainerSource(originalDescriptor.containerSource) WrappedFunctionDescriptorWithContainerSource(originalDescriptor.containerSource)
else if (originalDescriptor != null)
WrappedSimpleFunctionDescriptor(originalDescriptor)
else else
WrappedSimpleFunctionDescriptor() WrappedSimpleFunctionDescriptor()
return IrFunctionImpl( return IrFunctionImpl(
@@ -217,8 +217,6 @@ private val jvmFilePhases =
returnableBlocksPhase then returnableBlocksPhase then
localDeclarationsPhase then localDeclarationsPhase then
addContinuationPhase then
jvmOverloadsAnnotationPhase then jvmOverloadsAnnotationPhase then
jvmDefaultConstructorPhase then jvmDefaultConstructorPhase then
@@ -235,6 +233,8 @@ private val jvmFilePhases =
interfaceSuperCallsPhase then interfaceSuperCallsPhase then
interfaceDefaultCallsPhase then interfaceDefaultCallsPhase then
addContinuationPhase then
innerClassesPhase then innerClassesPhase then
innerClassConstructorCallsPhase then innerClassConstructorCallsPhase then
forLoopsPhase then forLoopsPhase then
@@ -108,8 +108,16 @@ internal fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspen
(parent as? IrClass)?.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL (parent as? IrClass)?.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
internal fun IrFunction.isKnownToBeTailCall(): Boolean = internal fun IrFunction.isKnownToBeTailCall(): Boolean =
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR || when (origin) {
isInvokeOfSuspendCallableReference() 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 = internal fun IrFunction.shouldNotContainSuspendMarkers(context: JvmBackendContext): Boolean =
isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall() isInvokeSuspendOfContinuation(context) || isKnownToBeTailCall()
@@ -78,7 +78,8 @@ open class FunctionCodegen(
val continuationClassBuilder = context.continuationClassBuilders[irClass] val continuationClassBuilder = context.continuationClassBuilders[irClass]
methodVisitor = when { methodVisitor = when {
irFunction.isSuspend && 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() && !irFunction.isKnownToBeTailCall() &&
// TODO: We should generate two versions of inline suspend function: one with state-machine and one without // TODO: We should generate two versions of inline suspend function: one with state-machine and one without
!irFunction.isInline -> !irFunction.isInline ->
@@ -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.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase 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.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
@@ -108,7 +109,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
IrFunctionImpl( IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
IrDeclarationOrigin.DEFINED, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE,
IrSimpleFunctionSymbolImpl(descriptor), IrSimpleFunctionSymbolImpl(descriptor),
classOverride.name, classOverride.name,
Visibilities.PUBLIC, Visibilities.PUBLIC,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// WITH_COROUTINES // WITH_COROUTINES
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// WITH_COROUTINES // WITH_COROUTINES
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// WITH_COROUTINES // WITH_COROUTINES
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// WITH_COROUTINES // WITH_COROUTINES
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// WITH_COROUTINES // WITH_COROUTINES
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST