Removed KProperty creation from each call of delegated property.

This commit is contained in:
Igor Chevdar
2017-03-01 14:37:51 +03:00
parent e2f2e31dc1
commit c7e04bfd0e
3 changed files with 126 additions and 63 deletions
@@ -1,10 +1,21 @@
package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import java.io.StringWriter
@@ -76,3 +87,50 @@ fun ir2stringWhole(ir: IrElement?): String {
return strWriter.toString()
}
internal fun ClassDescriptor.createSimpleDelegatingConstructor(superConstructorDescriptor: ClassConstructorDescriptor)
: Pair<ClassConstructorDescriptor, IrConstructor> {
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
this,
Annotations.EMPTY,
superConstructorDescriptor.isPrimary,
SourceElement.NO_SOURCE)
val valueParameters = superConstructorDescriptor.valueParameters.map {
it.copy(constructorDescriptor, it.name, it.index)
}
constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
listOf(
IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, superConstructorDescriptor).apply {
valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter))
}
},
IrInstanceInitializerCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this)
)
)
val constructor = IrConstructorImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, constructorDescriptor, body)
return Pair(constructorDescriptor, constructor)
}
internal fun Context.createArrayOfExpression(arrayElementType: KotlinType,
arrayElements: List<IrExpression>): IrExpression {
val kotlinPackage = irModule!!.descriptor.getPackage(FqName("kotlin"))
val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first()
val typeParameter0 = genericArrayOfFun.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
val typeArguments = mapOf(typeParameter0 to arrayElementType)
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements)
return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply {
putValueArgument(0, arg0)
}
}
@@ -2,13 +2,20 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.jvm.descriptors.initialize
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.OverriddenFunctionDescriptor
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
@@ -18,9 +25,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.*
internal class ClassDelegationLowering(val context: Context) : DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
@@ -89,7 +94,35 @@ internal class ClassDelegationLowering(val context: Context) : DeclarationContai
}
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
private val kotlinReflectPackage = context.irModule!!.descriptor.getPackage(FqName.fromSegments(listOf("kotlin", "reflect")))
private val genericKPropertyImplType = kotlinReflectPackage.memberScope.getContributedClassifier(Name.identifier("KPropertyImpl"),
NoLookupLocation.FROM_BACKEND) as ClassDescriptor
private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin"))
private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
fun getKPropertyImplConstructorDescriptorWithProjection(type: KotlinType): ClassConstructorDescriptor {
val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(type)))
return genericKPropertyImplType.unsubstitutedPrimaryConstructor!!.substitute(typeSubstitutor)!!
}
fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType {
return this.defaultType.replace(type.map(::TypeProjectionImpl))
}
override fun lower(irFile: IrFile) {
val kProperties = mutableListOf<IrExpression>()
val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single()
val typeParameterT = genericArrayType.declaredTypeParameters[0]
val kPropertyImplType = genericKPropertyImplType.replace(context.builtIns.anyType)
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType)))
val substitutedGetter = getter.substitute(typeSubstitutor)!!
val kPropertiesField = createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, genericArrayType.replace(kPropertyImplType))
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitFunction(declaration: IrFunction): IrStatement {
return super.visitFunction(declaration)
@@ -124,26 +157,43 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
return declaration
}
private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName.fromSegments(listOf("kotlin", "reflect")))
private val genericKPropertyImplType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("KPropertyImpl"),
NoLookupLocation.FROM_BACKEND) as ClassDescriptor
private fun transformBridgeToDelegate(name: String, type: KotlinType, irFunction: IrFunction?): IrFunction? {
irFunction?.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCallableReference(expression: IrCallableReference): IrExpression {
val typeParameterT = genericKPropertyImplType.declaredTypeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(type)))
val kPropertyImplType = genericKPropertyImplType.substitute(typeSubstitutor)
return IrCallImpl(expression.startOffset, expression.endOffset,
kPropertyImplType.defaultType, kPropertyImplType.unsubstitutedPrimaryConstructor!!, null).apply {
putValueArgument(0, IrConstImpl<String>(expression.startOffset, expression.endOffset,
val fieldInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
getKPropertyImplConstructorDescriptorWithProjection(type)).apply {
putValueArgument(0, IrConstImpl<String>(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.builtIns.stringType, IrConstKind.String, name))
}
val index = kProperties.size
kProperties.add(fieldInitializer)
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedGetter).apply {
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index))
}
}
})
return irFunction
}
})
irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
kPropertiesField,
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.createArrayOfExpression(kPropertyImplType, kProperties))))
}
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION :
IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
private fun createKPropertiesFieldDescriptor(containingDeclaration: DeclarationDescriptor, fieldType: SimpleType): PropertyDescriptorImpl {
return PropertyDescriptorImpl.create(containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE,
false, "KPROPERTIES".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
false, false, false, false, false, false).initialize(fieldType)
}
}
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression
import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
@@ -171,7 +173,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
descriptor.constructors.forEach {
val loweredEnumConstructor = loweredEnumConstructors[it]!!
val (constructorDescriptor, constructor) = createSimpleDelegatingConstructor(defaultClassDescriptor, loweredEnumConstructor)
val (constructorDescriptor, constructor) = defaultClassDescriptor.createSimpleDelegatingConstructor(loweredEnumConstructor)
constructors.add(constructorDescriptor)
defaultClass.declarations.add(constructor)
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructorDescriptor)
@@ -233,7 +235,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val memberScope = MemberScope.Empty
val constructorOfAny = irClass.descriptor.module.builtIns.any.constructors.first()
val (constructorDescriptor, constructor) = createSimpleDelegatingConstructor(implObjectDescriptor, constructorOfAny)
val (constructorDescriptor, constructor) = implObjectDescriptor.createSimpleDelegatingConstructor(constructorOfAny)
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
@@ -260,34 +262,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
return newDescriptor
}
private fun createSimpleDelegatingConstructor(classDescriptor: ClassDescriptor,
superConstructorDescriptor: ClassConstructorDescriptor)
: Pair<ClassConstructorDescriptor, IrConstructor> {
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
classDescriptor,
Annotations.EMPTY,
superConstructorDescriptor.isPrimary,
SourceElement.NO_SOURCE)
val valueParameters = superConstructorDescriptor.valueParameters.map {
it.copy(constructorDescriptor, it.name, it.index)
}
constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
listOf(
IrDelegatingConstructorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, superConstructorDescriptor).apply {
valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter))
}
},
IrInstanceInitializerCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, classDescriptor)
)
)
val constructor = IrConstructorImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, constructorDescriptor, body)
return Pair(constructorDescriptor, constructor)
}
private fun createSyntheticValuesFieldDeclaration(implObjectDescriptor: ClassDescriptor,
enumEntries: List<IrEnumEntry>): IrFieldImpl {
val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.descriptor.defaultType)
@@ -304,7 +278,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val loweredEnumEntry = LoweredEnumEntry(implObjectDescriptor, valuesFieldDescriptor, substitutedValueOf, entriesMap)
loweredEnumEntries.put(irClass.descriptor, loweredEnumEntry)
val irValuesInitializer = createArrayOfExpression(irClass.descriptor.defaultType, enumEntries.map { it.initializerExpression })
val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType, enumEntries.map { it.initializerExpression })
val irField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED,
valuesFieldDescriptor,
@@ -321,31 +295,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin"))
private val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first()
private val genericValueOfFun = context.builtIns.getKonanInternalFunctions("valueOfForEnum").single()
private val genericValuesFun = context.builtIns.getKonanInternalFunctions("valuesForEnum").single()
private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
private fun createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List<IrExpression>): IrExpression {
val typeParameter0 = genericArrayOfFun.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
val typeArguments = mapOf(typeParameter0 to arrayElementType)
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements)
return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply {
putValueArgument(0, arg0)
}
}
private fun createSyntheticValuesMethodDeclaration(companionObjectDescriptor: ClassDescriptor): IrFunction {
val typeParameterT = genericValuesFun.typeParameters[0]
val enumClassType = irClass.descriptor.defaultType