JVM_IR. Cache defaultImpls function declarations
This commit is contained in:
committed by
romanart
parent
5c0cdac69f
commit
92ce50b22c
@@ -49,7 +49,8 @@ object CodegenUtil {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getNonPrivateTraitMethods(descriptor: ClassDescriptor): Map<FunctionDescriptor, FunctionDescriptor> {
|
||||
@JvmOverloads
|
||||
fun getNonPrivateTraitMethods(descriptor: ClassDescriptor, copy: Boolean = true): Map<FunctionDescriptor, FunctionDescriptor> {
|
||||
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
|
||||
for (declaration in DescriptorUtils.getAllDescriptors(descriptor.defaultType.memberScope)) {
|
||||
if (declaration !is CallableMemberDescriptor) continue
|
||||
@@ -63,29 +64,39 @@ object CodegenUtil {
|
||||
|
||||
// inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
|
||||
// with traitMember's modality
|
||||
result.putAll(copyFunctions(declaration, traitMember, declaration.containingDeclaration, traitMember.modality,
|
||||
Visibilities.PUBLIC, CallableMemberDescriptor.Kind.DECLARATION, true))
|
||||
result.putAll(
|
||||
if (copy)
|
||||
copyFunctions(
|
||||
declaration, traitMember, declaration.containingDeclaration, traitMember.modality,
|
||||
Visibilities.PUBLIC, CallableMemberDescriptor.Kind.DECLARATION, true
|
||||
)
|
||||
else mapMembers(declaration, traitMember)
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun copyFunctions(
|
||||
inheritedMember: CallableMemberDescriptor,
|
||||
traitMember: CallableMemberDescriptor,
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
): Map<FunctionDescriptor, FunctionDescriptor> {
|
||||
val copy = inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides)
|
||||
inheritedMember: CallableMemberDescriptor,
|
||||
traitMember: CallableMemberDescriptor,
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
): Map<FunctionDescriptor, FunctionDescriptor> =
|
||||
mapMembers(inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides), traitMember)
|
||||
|
||||
private fun mapMembers(
|
||||
inherited: CallableMemberDescriptor,
|
||||
traitMember: CallableMemberDescriptor
|
||||
): LinkedHashMap<FunctionDescriptor, FunctionDescriptor> {
|
||||
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
|
||||
if (traitMember is SimpleFunctionDescriptor) {
|
||||
result[traitMember] = copy as FunctionDescriptor
|
||||
}
|
||||
else if (traitMember is PropertyDescriptor) {
|
||||
result[traitMember] = inherited as FunctionDescriptor
|
||||
} else if (traitMember is PropertyDescriptor) {
|
||||
for (traitAccessor in traitMember.accessors) {
|
||||
for (inheritedAccessor in (copy as PropertyDescriptor).accessors) {
|
||||
for (inheritedAccessor in (inherited as PropertyDescriptor).accessors) {
|
||||
if (inheritedAccessor::class.java == traitAccessor::class.java) { // same accessor kind
|
||||
result.put(traitAccessor, inheritedAccessor)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class JvmBackendContext(
|
||||
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
|
||||
) : CommonBackendContext {
|
||||
override val builtIns = state.module.builtIns
|
||||
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(psiSourceManager, builtIns)
|
||||
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(psiSourceManager, builtIns, state)
|
||||
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns, irBuiltIns)
|
||||
|
||||
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
|
||||
@@ -41,8 +41,8 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
//Should be before interface lowering
|
||||
DefaultArgumentStubGenerator(context, false).runOnFilePostfix(irFile)
|
||||
|
||||
InterfaceLowering(context.state).runOnFilePostfix(irFile)
|
||||
InterfaceDelegationLowering(context.state).runOnFilePostfix(irFile)
|
||||
InterfaceLowering(context).runOnFilePostfix(irFile)
|
||||
InterfaceDelegationLowering(context).runOnFilePostfix(irFile)
|
||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
||||
|
||||
irFile.acceptVoid(PatchDeclarationParentsVisitor())
|
||||
|
||||
+54
-1
@@ -7,17 +7,23 @@ package org.jetbrains.kotlin.backend.jvm.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.createFunctionAndMapVariables
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.createStaticFunctionWithReceivers
|
||||
import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
@@ -29,7 +35,10 @@ import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
@@ -38,12 +47,16 @@ import java.util.*
|
||||
|
||||
class JvmDeclarationFactory(
|
||||
private val psiSourceManager: PsiSourceManager,
|
||||
private val builtIns: KotlinBuiltIns
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val state: GenerationState
|
||||
) : DeclarationFactory {
|
||||
private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
|
||||
private val outerThisDeclarations = HashMap<IrClass, IrField>()
|
||||
private val innerClassConstructors = HashMap<IrConstructor, IrConstructor>()
|
||||
|
||||
private val defaultImplsMethods = HashMap<IrFunction, IrFunction>()
|
||||
private val defaultImplsClasses = HashMap<IrClass, IrClass>()
|
||||
|
||||
override fun getFieldForEnumEntry(enumEntry: IrEnumEntry, type: IrType): IrField =
|
||||
singletonFieldDeclarations.getOrPut(enumEntry) {
|
||||
val symbol = IrFieldSymbolImpl(createEnumEntryFieldDescriptor(enumEntry.descriptor))
|
||||
@@ -186,4 +199,44 @@ class JvmDeclarationFactory(
|
||||
/* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false
|
||||
).initialize(objectDescriptor.defaultType)
|
||||
}
|
||||
|
||||
fun getDefaultImplsFunction(interfaceFun: IrFunction): IrFunction {
|
||||
assert(interfaceFun.parentAsClass.isInterface) { "Parent of ${interfaceFun.dump()} should be interface" }
|
||||
return defaultImplsMethods.getOrPut(interfaceFun) {
|
||||
val defaultImpls = getDefaultImplsClass(interfaceFun.parentAsClass)
|
||||
|
||||
createDefaultImplFunDescriptor(
|
||||
defaultImpls.descriptor as DefaultImplsClassDescriptor,
|
||||
interfaceFun.descriptor.original,
|
||||
interfaceFun.parentAsClass.descriptor,
|
||||
state.typeMapper
|
||||
).createFunctionAndMapVariables(interfaceFun, origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS)
|
||||
}
|
||||
}
|
||||
|
||||
fun getDefaultImplsClass(interfaceClass: IrClass): IrClass =
|
||||
defaultImplsClasses.getOrPut(interfaceClass) {
|
||||
IrClassImpl(
|
||||
interfaceClass.startOffset, interfaceClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS,
|
||||
createDefaultImplsClassDescriptor(interfaceClass.descriptor)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private fun createDefaultImplsClassDescriptor(interfaceDescriptor: ClassDescriptor): DefaultImplsClassDescriptorImpl {
|
||||
return DefaultImplsClassDescriptorImpl(
|
||||
Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME), interfaceDescriptor, interfaceDescriptor.source
|
||||
)
|
||||
}
|
||||
|
||||
private fun createDefaultImplFunDescriptor(
|
||||
defaultImplsDescriptor: DefaultImplsClassDescriptor,
|
||||
descriptor: FunctionDescriptor,
|
||||
interfaceDescriptor: ClassDescriptor, typeMapper: KotlinTypeMapper
|
||||
): SimpleFunctionDescriptorImpl {
|
||||
val name = Name.identifier(typeMapper.mapAsmMethod(descriptor).name)
|
||||
return createStaticFunctionWithReceivers(defaultImplsDescriptor, name, descriptor, interfaceDescriptor.defaultType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
-34
@@ -7,79 +7,92 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptor
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
|
||||
import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
|
||||
class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||
|
||||
val state: GenerationState = context.state
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
if (irClass.isJvmInterface) return
|
||||
|
||||
irClass.transformChildrenVoid(this)
|
||||
generateInterfaceMethods(irClass, irClass.descriptor)
|
||||
generateInterfaceMethods(irClass)
|
||||
}
|
||||
|
||||
|
||||
private fun generateInterfaceMethods(irClass: IrClass, descriptor: ClassDescriptor) {
|
||||
val classDescriptor = (descriptor as? DefaultImplsClassDescriptor)?.correspondingInterface ?: descriptor
|
||||
for ((interfaceFun, value) in CodegenUtil.getNonPrivateTraitMethods(classDescriptor)) {
|
||||
private fun generateInterfaceMethods(irClass: IrClass) {
|
||||
val irClassDescriptor = irClass.descriptor
|
||||
val actualClassDescriptor = (irClassDescriptor as? DefaultImplsClassDescriptor)?.correspondingInterface ?: irClassDescriptor
|
||||
val isDefaultImplsGeneration = actualClassDescriptor !== irClassDescriptor
|
||||
for ((interfaceFun, value) in CodegenUtil.getNonPrivateTraitMethods(actualClassDescriptor, !isDefaultImplsGeneration)) {
|
||||
//skip java 8 default methods
|
||||
if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) {
|
||||
val inheritedFun =
|
||||
if (classDescriptor !== descriptor) {
|
||||
InterfaceLowering.createDefaultImplFunDescriptor(
|
||||
descriptor as DefaultImplsClassDescriptorImpl,
|
||||
interfaceFun,
|
||||
classDescriptor,
|
||||
state.typeMapper
|
||||
)
|
||||
} else {
|
||||
value
|
||||
}
|
||||
generateDelegationToDefaultImpl(irClass, interfaceFun, inheritedFun)
|
||||
if (!interfaceFun.isDefinitelyNotDefaultImplsMethod() && !FunctionCodegen.isMethodOfAny(interfaceFun)) {
|
||||
generateDelegationToDefaultImpl(
|
||||
irClass, context.ir.symbols.externalSymbolTable.referenceSimpleFunction(
|
||||
interfaceFun.original
|
||||
).owner, value, isDefaultImplsGeneration
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDelegationToDefaultImpl(irClass: IrClass, interfaceFun: FunctionDescriptor, inheritedFun: FunctionDescriptor) {
|
||||
private fun generateDelegationToDefaultImpl(
|
||||
irClass: IrClass,
|
||||
interfaceFun: IrFunction,
|
||||
inheritedFun: FunctionDescriptor,
|
||||
isDefaultImplsGeneration: Boolean
|
||||
) {
|
||||
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceFun)
|
||||
|
||||
val irFunction =
|
||||
if (!isDefaultImplsGeneration) IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
inheritedFun,
|
||||
null
|
||||
).also {
|
||||
it.createParameterDeclarations()
|
||||
it.returnType = defaultImplFun.returnType
|
||||
}
|
||||
else context.declarationFactory.getDefaultImplsFunction(
|
||||
context.ir.symbols.externalSymbolTable.referenceSimpleFunction(
|
||||
inheritedFun.original
|
||||
).owner
|
||||
)
|
||||
val irBody = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, inheritedFun, irBody)
|
||||
irFunction.createParameterDeclarations()
|
||||
irFunction.body = irBody
|
||||
irClass.declarations.add(irFunction)
|
||||
|
||||
val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor
|
||||
val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor)
|
||||
val defaultImplFun =
|
||||
InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun.original, interfaceDescriptor, state.typeMapper)
|
||||
irFunction.returnType = defaultImplFun.returnType!!.toIrType()!!
|
||||
val irCallImpl =
|
||||
IrCallImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
defaultImplFun.returnType!!.toIrType()!!,
|
||||
defaultImplFun,
|
||||
defaultImplFun.typeParametersCount,
|
||||
JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION
|
||||
defaultImplFun.returnType,
|
||||
defaultImplFun.symbol,
|
||||
defaultImplFun.descriptor,
|
||||
origin = JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION
|
||||
)
|
||||
irBody.statements.add(
|
||||
IrReturnImpl(
|
||||
|
||||
Reference in New Issue
Block a user