JVM IR: Implement -Xjvm-default=enable

This commit is contained in:
Kristoffer Andersen
2019-09-19 09:38:26 +02:00
committed by max-kammerer
parent 48e2e1f0c1
commit 5cefd4e443
4 changed files with 14 additions and 8 deletions
@@ -78,7 +78,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
for (function in actualClass.functions.toList()) { // Copy the list, because we are adding new declarations from the loop
if (function.origin !== IrDeclarationOrigin.FAKE_OVERRIDE) continue
// In classes, only generate interface delegation for functions immediately inherited from am interface.
// In classes, only generate interface delegation for functions immediately inherited from an interface.
// (Otherwise, delegation will be present in the parent class)
if (!isDefaultImplsGeneration &&
function.overriddenSymbols.any {
@@ -92,7 +92,9 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
val implementation = function.resolveFakeOverride() ?: continue
if (!implementation.hasInterfaceParent() ||
Visibilities.isPrivate(implementation.visibility) ||
implementation.isDefinitelyNotDefaultImplsMethod() || implementation.isMethodOfAny()
implementation.isDefinitelyNotDefaultImplsMethod() ||
implementation.isMethodOfAny() ||
(!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault())
) {
continue
}
@@ -205,8 +207,9 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
if (expression.superQualifierSymbol?.owner?.isInterface != true) {
return super.visitCall(expression)
}
val superCallee = (expression.symbol.owner as IrSimpleFunction).resolveFakeOverride()!!
if (superCallee.isDefinitelyNotDefaultImplsMethod()) return super.visitCall(expression)
if (superCallee.isDefinitelyNotDefaultImplsMethod() || superCallee.hasJvmDefault()) return super.visitCall(expression)
val redirectTarget = context.declarationFactory.getDefaultImplsFunction(superCallee)
val newCall = irCall(expression, redirectTarget, receiversAsArguments = true)
@@ -222,7 +225,7 @@ internal val interfaceDefaultCallsPhase = makeIrFilePhase(
)
private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
// TODO If there are no default _implementations_ we can avoid generating defaultImpls class entirely by moving default arg dispatchers to the interface class
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(this)
}
@@ -45,6 +45,7 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
if (!irClass.isInterface) return
val defaultImplsIrClass = context.declarationFactory.getDefaultImplsClass(irClass)
//TODO: Don't add DefaultImpls if it's empty. Just like the old backend...?
irClass.declarations.add(defaultImplsIrClass)
val members = defaultImplsIrClass.declarations
@@ -52,8 +53,11 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
if (function !is IrSimpleFunction) continue
if (function.modality != Modality.ABSTRACT && function.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
if(function.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility && !mustMoveToDefaultImpls(function)) continue
val element = context.declarationFactory.getDefaultImplsFunction(function).also {
if (shouldRemoveFunction(function))
if (mustMoveToDefaultImpls(function))
removedFunctions[function.symbol] = it.symbol
}
members.add(element)
@@ -64,7 +68,6 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
if (function.hasJvmDefault() &&
function.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
) {
// TODO: don't touch function and only generate element / DefaultImpls when needed.
function.body = IrExpressionBodyImpl(callDefaultImpls(element, function))
} else {
function.body = null
@@ -98,7 +101,7 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
}
}
private fun shouldRemoveFunction(function: IrFunction): Boolean =
private fun mustMoveToDefaultImpls(function: IrFunction): Boolean =
Visibilities.isPrivate(function.visibility) && function.name != clinitName ||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.name
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_RUNTIME