JVM_IR. Mostly remove descriptors from InterfaceLowering

Descriptors are only used to generate a new method name via a call to
KotlinTypeMapper.
This commit is contained in:
Georgy Bronnikov
2018-10-25 13:07:08 +03:00
parent 55b65546fa
commit cbc46fe6e4
8 changed files with 99 additions and 121 deletions
@@ -153,10 +153,10 @@ fun IrClass.addSimpleDelegatingConstructor(
val IrCall.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
fun IrValueParameter.copyTo(
irFunction: IrFunction,
shift: Int = 0,
index: Int? = null,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset,
origin: IrDeclarationOrigin = this.origin,
@@ -164,13 +164,16 @@ fun IrValueParameter.copyTo(
type: IrType = this.type.remapTypeParameters(this.parent as IrTypeParametersContainer, irFunction),
varargElementType: IrType? = this.varargElementType
): IrValueParameter {
// You cannot specify both index and nontrivial shift.
assert(index == null || shift == 0)
val newIndex = index ?: (shift + this.index)
val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source)
val symbol = IrValueParameterSymbolImpl(descriptor)
val defaultValueCopy = defaultValue?.deepCopyWithVariables()
defaultValueCopy?.patchDeclarationParents(irFunction)
return IrValueParameterImpl(
startOffset, endOffset, origin, symbol,
name, shift + index, type, varargElementType, isCrossinline, isNoinline
name, newIndex, type, varargElementType, isCrossinline, isNoinline
).also {
descriptor.bind(it)
it.parent = irFunction
@@ -36,6 +36,8 @@ import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import java.io.File
import java.lang.RuntimeException
open class ClassCodegen protected constructor(
internal val irClass: IrClass,
@@ -62,11 +64,15 @@ open class ClassCodegen protected constructor(
private val fileEntry = sourceManager.getFileEntry(irClass.fileParent)
val psiElement = irClass.descriptor.psiElement!!
val psiElement = irClass.descriptor.psiElement
val visitor: ClassBuilder = createClassBuilder()
open fun createClassBuilder() = state.factory.newVisitor(OtherOrigin(psiElement, descriptor), type, psiElement.containingFile)
open fun createClassBuilder() = state.factory.newVisitor(
OtherOrigin(psiElement, descriptor),
type,
psiElement?.containingFile?.let { setOf(it) } ?: emptySet()
)
private var sourceMapper: DefaultSourceMapper? = null
@@ -83,8 +89,10 @@ open class ClassCodegen protected constructor(
signature.superclassName,
signature.interfaces.toTypedArray()
)
AnnotationCodegen.forClass(visitor.visitor, this, state).genAnnotations(descriptor, null)
visitor.visitSource(irClass.symbol.descriptor.source.containingFile.name!!, null)
AnnotationCodegen.forClass(visitor.visitor, this, typeMapper).genAnnotations(descriptor, null)
/* TODO: Temporary workaround: ClassBuilder needs a pathless name. */
val shortName = File(fileEntry.name).name
visitor.visitSource(shortName, null)
irClass.declarations.forEach {
generateDeclaration(it)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.org.objectweb.asm.Type
import java.io.File
class IrFrameMap : FrameMapBase<IrSymbol>()
@@ -52,11 +53,12 @@ fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper
// whole file the class is declared in rather than the class only.
// TODO: revise
val endLineNumber = fileEntry.getSourceRangeInfo(0, fileEntry.maxOffset).endLineNumber
val shortName = File(declaration.fileParent.name).name
return DefaultSourceMapper(
SourceInfo.createInfoForIr(
endLineNumber + 1,
this.state.typeMapper.mapType(declaration.descriptor).internalName,
declaration.descriptor.psiElement!!.containingFile.name
shortName
)
)
}
@@ -5,24 +5,23 @@
package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
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.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.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
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
@@ -187,46 +186,39 @@ class JvmDeclarationFactory(
}
fun getDefaultImplsFunction(interfaceFun: IrFunction): IrFunction {
assert(interfaceFun.parentAsClass.isInterface) { "Parent of ${interfaceFun.dump()} should be interface" }
val parent = interfaceFun.parentAsClass
assert(parent.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, defaultImpls, symbolTable = symbolTable, origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS
val name = Name.identifier(state.typeMapper.mapAsmMethod(interfaceFun.descriptor.original).name)
createStaticFunctionWithReceivers(
defaultImpls, name, interfaceFun,
dispatchReceiverType = parent.defaultType,
origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS
)
}
}
fun getDefaultImplsClass(interfaceClass: IrClass): IrClass =
defaultImplsClasses.getOrPut(interfaceClass) {
val descriptor = WrappedClassDescriptor()
IrClassImpl(
interfaceClass.startOffset, interfaceClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS,
createDefaultImplsClassDescriptor(interfaceClass.descriptor)
).also {
it.parent = interfaceClass
interfaceClass.startOffset, interfaceClass.endOffset,
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS,
IrClassSymbolImpl(descriptor),
Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
ClassKind.CLASS,
Visibilities.PUBLIC,
Modality.FINAL,
isCompanion = false,
isInner = false,
isData = false,
isExternal = false,
isInline = false
).apply {
descriptor.bind(this)
parent = interfaceClass
}
}
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)
}
}
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptor
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmFunctionDescriptorImpl
import org.jetbrains.kotlin.codegen.AsmUtil.isAbstractMethod
@@ -55,6 +56,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.getSuperClassDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
@@ -71,7 +73,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
val classDescriptor = irClass.descriptor
if (classDescriptor is DefaultImplsClassDescriptor) {
if (irClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) {
return /*TODO?*/
}
@@ -88,7 +90,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
//additional bridges for inherited interface methods
if (!DescriptorUtils.isInterface(classDescriptor) && classDescriptor !is DefaultImplsClassDescriptor) {
if (!DescriptorUtils.isInterface(classDescriptor) && irClass.origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) {
for (memberDescriptor in DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)) {
if (memberDescriptor is CallableMemberDescriptor) {
if (!memberDescriptor.kind.isReal && findInterfaceImplementation(memberDescriptor) == null) {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptor
@@ -43,7 +44,7 @@ class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementTra
private fun generateInterfaceMethods(irClass: IrClass) {
val irClassDescriptor = irClass.descriptor
val actualClassDescriptor = (irClassDescriptor as? DefaultImplsClassDescriptor)?.correspondingInterface ?: irClassDescriptor
val actualClassDescriptor = (irClass.takeIf { it.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS }?.parent as? IrClass)?.descriptor ?: irClassDescriptor
val isDefaultImplsGeneration = actualClassDescriptor !== irClassDescriptor
for ((interfaceFun, value) in CodegenUtil.getNonPrivateTraitMethods(actualClassDescriptor, !isDefaultImplsGeneration)) {
//skip java 8 default methods
@@ -6,27 +6,24 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.backend.common.lower.VariableRemapperDesc
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Opcodes
class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass {
@@ -40,10 +37,9 @@ class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVo
val members = defaultImplsIrClass.declarations
irClass.declarations.filterIsInstance<IrFunction>().forEach {
val descriptor = it.descriptor
if (it.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER) {
members.add(it) //just copy $default to DefaultImpls
} else if (descriptor.modality != Modality.ABSTRACT && it.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
} else if (it is IrSimpleFunction && it.modality != Modality.ABSTRACT && it.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
val element = context.declarationFactory.getDefaultImplsFunction(it)
members.add(element)
element.body = it.body
@@ -52,15 +48,11 @@ class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVo
}
}
irClass.transformChildrenVoid(this)
//REMOVE private methods
val privateToRemove = irClass.declarations.filterIsInstance<IrFunction>().mapNotNull {
val visibility = AsmUtil.getVisibilityAccessFlag(it.descriptor)
if (visibility == Opcodes.ACC_PRIVATE && it.descriptor.name != clinitName) {
it
} else null
val privateToRemove = irClass.declarations.filterIsInstance<IrFunction>().filter {
Visibilities.isPrivate(it.visibility) && (it as? IrSimpleFunction)?.name != clinitName
}
val defaultBodies = irClass.declarations.filterIsInstance<IrFunction>().filter {
@@ -73,60 +65,47 @@ class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVo
internal fun createStaticFunctionWithReceivers(
owner: ClassOrPackageFragmentDescriptor,
irParent: IrDeclarationParent,
name: Name,
descriptor: FunctionDescriptor,
dispatchReceiverType: KotlinType
): SimpleFunctionDescriptorImpl {
val newFunction = SimpleFunctionDescriptorImpl.create(
owner,
Annotations.EMPTY,
name,
CallableMemberDescriptor.Kind.DECLARATION, descriptor.source
)
var offset = 0
val dispatchReceiver =
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, offset++, Annotations.EMPTY, Name.identifier("this"),
dispatchReceiverType, false, false, false, null, descriptor.source, null
)
val extensionReceiver =
descriptor.extensionReceiverParameter?.let { extensionReceiver ->
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, offset++, Annotations.EMPTY, Name.identifier("receiver"),
extensionReceiver.value.type, false, false, false, null, extensionReceiver.source, null
)
}
val valueParameters = listOfNotNull(dispatchReceiver, extensionReceiver) +
descriptor.valueParameters.map { it.copy(newFunction, it.name, it.index + offset) }
newFunction.initialize(
null, null, emptyList()/*TODO: type parameters*/,
valueParameters, descriptor.returnType, Modality.FINAL, descriptor.visibility
)
return newFunction
}
internal fun FunctionDescriptor.createFunctionAndMapVariables(
oldFunction: IrFunction,
parentClass: IrDeclarationParent,
visibility: Visibility = oldFunction.visibility,
symbolTable: SymbolTable? = null,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin
) =
IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset, origin, IrSimpleFunctionSymbolImpl(this),
visibility = visibility,
returnType = oldFunction.returnType
): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor(Annotations.EMPTY, oldFunction.descriptor.source)
return IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset,
origin,
IrSimpleFunctionSymbolImpl(descriptor),
name,
oldFunction.visibility,
Modality.FINAL,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
).apply {
parent = parentClass
body = oldFunction.body
createParameterDeclarations(symbolTable)
// TODO: do we really need descriptor here? This workaround is about copying `dispatchReceiver` descriptor
val mapping: Map<ValueDescriptor, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter!!.descriptor, oldFunction.extensionReceiverParameter?.descriptor) + oldFunction.valueParameters.map { it.descriptor })
.zip(valueParameters).toMap()
descriptor.bind(this)
parent = irParent
returnType = oldFunction.returnType
body?.transform(VariableRemapperDesc(mapping), null)
copyTypeParametersFrom(oldFunction)
var offset = 0
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
this,
name = Name.identifier("this"),
index = offset++,
type = dispatchReceiverType!!
)
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
this,
name = Name.identifier("receiver"),
index = offset++
)
valueParameters.addAll(listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map { it.copyTo(this, shift = offset) }
)
val mapping: Map<IrValueParameter, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
.zip(valueParameters).toMap()
body = oldFunction.body?.transform(VariableRemapper(mapping), null)
}
}
@@ -20,8 +20,6 @@ import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -37,16 +35,9 @@ class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLowerin
override fun visitFunction(declaration: IrFunction): IrStatement {
return if (declaration.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
val newFunction = createStaticFunctionWithReceivers(
declaration.descriptor.containingDeclaration as ClassDescriptor,
declaration.descriptor.name,
declaration.descriptor,
declaration.dispatchReceiverParameter!!.descriptor.type
)
// NOTE: Fix it
newFunction.createFunctionAndMapVariables(declaration, declaration.parent, Visibilities.PUBLIC)
createStaticFunctionWithReceivers(declaration.parent, declaration.name, declaration)
} else {
super.visitFunction(declaration)
}
}
}
}