Fix IR compilation of kotlix.serialization runtime in native
This commit is contained in:
+118
-37
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
@@ -28,10 +29,7 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
@@ -42,6 +40,12 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.FUNCTION0_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.KPROPERTY1_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FUNC_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
|
||||
|
||||
interface IrBuilderExtension {
|
||||
val compilerContext: SerializationPluginContext
|
||||
@@ -82,48 +86,125 @@ interface IrBuilderExtension {
|
||||
) { bodyGen(c) }
|
||||
}
|
||||
|
||||
// function will not be created in the real class
|
||||
fun IrClass.createInlinedFunction(
|
||||
name: Name,
|
||||
visibility: DescriptorVisibility,
|
||||
origin: IrDeclarationOrigin,
|
||||
returnType: IrType,
|
||||
bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit
|
||||
): IrSimpleFunction {
|
||||
val function = factory.buildFun {
|
||||
this.name = name
|
||||
this.visibility = visibility
|
||||
this.origin = origin
|
||||
this.isInline = true
|
||||
this.returnType = returnType
|
||||
}
|
||||
val functionSymbol = function.symbol
|
||||
function.parent = this
|
||||
function.body = DeclarationIrBuilder(compilerContext, functionSymbol, startOffset, endOffset).irBlockBody(
|
||||
startOffset,
|
||||
endOffset
|
||||
) { bodyGen(function) }
|
||||
return function
|
||||
}
|
||||
|
||||
fun IrClass.createSingletonLambda(
|
||||
returnType: IrType,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
fun IrClass.createLambdaExpression(
|
||||
type: IrType,
|
||||
bodyGen: IrBlockBodyBuilder.() -> Unit
|
||||
): IrSimpleFunction {
|
||||
): IrFunctionExpression {
|
||||
val function = compilerContext.irFactory.buildFun {
|
||||
this.startOffset = startOffset
|
||||
this.endOffset = endOffset
|
||||
this.returnType = returnType
|
||||
this.startOffset = this@createLambdaExpression.startOffset
|
||||
this.endOffset = this@createLambdaExpression.endOffset
|
||||
this.returnType = type
|
||||
name = Name.identifier("<anonymous>")
|
||||
visibility = DescriptorVisibilities.LOCAL
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
}
|
||||
function.body =
|
||||
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
||||
function.parent = this
|
||||
|
||||
return function
|
||||
val f0Type = module.findClassAcrossModuleDependencies(ClassId.topLevel(FUNCTION0_FQ))!!.defaultType
|
||||
val f0ParamSymbol = compilerContext.symbolTable.referenceTypeParameter(f0Type.constructor.parameters[0])
|
||||
val f0IrType = f0Type.toIrType().substitute(mapOf(f0ParamSymbol to type))
|
||||
|
||||
return IrFunctionExpressionImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
f0IrType,
|
||||
function,
|
||||
IrStatementOrigin.LAMBDA
|
||||
)
|
||||
}
|
||||
|
||||
fun createLazyProperty(
|
||||
containingClass: IrClass,
|
||||
targetIrType: IrType,
|
||||
name: Name,
|
||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||
): IrProperty {
|
||||
val lazySafeModeClassDescriptor = compilerContext.referenceClass(LAZY_MODE_FQ)!!.descriptor
|
||||
val lazyFunctionSymbol = compilerContext.referenceFunctions(LAZY_FUNC_FQ).single {
|
||||
it.descriptor.valueParameters.size == 2 && it.descriptor.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
|
||||
}
|
||||
val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == LAZY_PUBLICATION_MODE_NAME }
|
||||
|
||||
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
|
||||
val lazyKotlinType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType)).toKotlinType()
|
||||
|
||||
val kPropertyIrClass = compilerContext.referenceClass(KPROPERTY1_FQ)!!.owner
|
||||
val kPropertyKotlinType = kPropertyIrClass.defaultType.substitute(
|
||||
mapOf(
|
||||
kPropertyIrClass.typeParameters[0].symbol to targetIrType,
|
||||
kPropertyIrClass.typeParameters[1].symbol to containingClass.defaultType,
|
||||
)
|
||||
).toKotlinType()
|
||||
|
||||
val targetKotlinType = targetIrType.toKotlinType()
|
||||
|
||||
val propertyDescriptor =
|
||||
KSerializerDescriptorResolver.createValPropertyDescriptor(name, containingClass.descriptor, targetKotlinType)
|
||||
|
||||
val delegate = IrPropertyDelegateDescriptorImpl(propertyDescriptor, lazyKotlinType, kPropertyKotlinType)
|
||||
|
||||
return generateSimplePropertyWithBackingField(delegate, containingClass, delegate.name).apply {
|
||||
val builder = DeclarationIrBuilder(compilerContext, containingClass.symbol, startOffset, endOffset)
|
||||
val initializerBody = builder.run {
|
||||
val enumElement = IrGetEnumValueImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
publicationEntryDescriptor.classValueType!!.toIrType(),
|
||||
compilerContext.symbolTable.referenceEnumEntry(publicationEntryDescriptor)
|
||||
)
|
||||
|
||||
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
|
||||
|
||||
irExprBody(
|
||||
irInvoke(null, lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), targetIrType)
|
||||
)
|
||||
}
|
||||
backingField!!.initializer = initializerBody
|
||||
}
|
||||
}
|
||||
|
||||
fun createCompanionValProperty(
|
||||
companionClass: IrClass,
|
||||
type: IrType,
|
||||
name: Name,
|
||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||
): IrProperty {
|
||||
val targetKotlinType = type.toKotlinType()
|
||||
val propertyDescriptor =
|
||||
KSerializerDescriptorResolver.createValPropertyDescriptor(name, companionClass.descriptor, targetKotlinType)
|
||||
|
||||
return generateSimplePropertyWithBackingField(propertyDescriptor, companionClass, name).apply {
|
||||
companionClass.contributeAnonymousInitializer {
|
||||
val irBlockBody = irBlockBody(startOffset, endOffset, initializerBuilder)
|
||||
irBlockBody.statements.dropLast(1).forEach { +it }
|
||||
val expression = irBlockBody.statements.last() as? IrExpression
|
||||
?: throw AssertionError("Last statement in property initializer builder is not an a expression")
|
||||
+irSetField(irGetObject(companionClass), backingField!!, expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.contributeAnonymousInitializer(bodyGen: IrBlockBodyBuilder.() -> Unit) {
|
||||
val symbol = IrAnonymousInitializerSymbolImpl(descriptor)
|
||||
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZABLE_PLUGIN_ORIGIN, symbol).also {
|
||||
it.parent = this
|
||||
declarations.add(it)
|
||||
it.body = DeclarationIrBuilder(compilerContext, symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBlockBodyBuilder.getLazyValueExpression(companionClass: IrClass, property: IrProperty): IrExpression {
|
||||
val lazyIrClass = compilerContext.referenceClass(LAZY_FQ)!!.owner
|
||||
val valueGetter = lazyIrClass.getPropertyGetter("value")!!
|
||||
|
||||
val backingField = property.backingField!!
|
||||
return irGet(
|
||||
backingField.type,
|
||||
irGetField(irGetObject(companionClass), backingField),
|
||||
valueGetter
|
||||
)
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irInvoke(
|
||||
|
||||
+12
-72
@@ -12,17 +12,12 @@ import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
import org.jetbrains.kotlin.ir.util.module
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||
@@ -36,25 +31,6 @@ class SerializableCompanionIrGenerator(
|
||||
bindingContext: BindingContext
|
||||
) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
||||
|
||||
private val lazyDescriptor = irClass.module.findClassAcrossModuleDependencies(
|
||||
ClassId(FqName("kotlin"), Name.identifier("Lazy"))
|
||||
)!!
|
||||
|
||||
private val lazySafeModeClassDescriptor = irClass.module.findClassAcrossModuleDependencies(
|
||||
ClassId(FqName("kotlin"), Name.identifier("LazyThreadSafetyMode"))
|
||||
)!!
|
||||
|
||||
private val lazyFunctionSymbol = compilerContext.referenceFunctions(FqName("kotlin").child(Name.identifier("lazy"))).single {
|
||||
it.descriptor.valueParameters.size == 2 && it.descriptor.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
|
||||
}
|
||||
|
||||
private val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == Name.identifier("PUBLICATION") }
|
||||
|
||||
private val function0Descriptor = irClass.module.findClassAcrossModuleDependencies(
|
||||
ClassId(FqName("kotlin"), Name.identifier("Function0"))
|
||||
)!!
|
||||
|
||||
|
||||
companion object {
|
||||
fun generate(
|
||||
irClass: IrClass,
|
||||
@@ -113,58 +89,22 @@ class SerializableCompanionIrGenerator(
|
||||
)
|
||||
)
|
||||
|
||||
val field = irClass.addField {
|
||||
name = Name.identifier(SerialEntityNames.SERIALIZER_LAZY_DELEGATE_FIELD_NAME)
|
||||
visibility = DescriptorVisibilities.PRIVATE
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
isFinal = true
|
||||
isStatic = true
|
||||
type = lazyDescriptor.defaultType.toIrType()
|
||||
}.apply {
|
||||
val lambda = irClass.createSingletonLambda(serializerDescriptor.defaultType.toIrType(), startOffset, endOffset) {
|
||||
val expr = serializerInstance(
|
||||
this@SerializableCompanionIrGenerator,
|
||||
serializerDescriptor, serializableDescriptor.module,
|
||||
serializableDescriptor.defaultType
|
||||
)
|
||||
patchSerializableClassWithMarkerAnnotation(serializerDescriptor)
|
||||
+irReturn(requireNotNull(expr))
|
||||
}
|
||||
val kSerializerIrClass = compilerContext.referenceClass(SerialEntityNames.KSERIALIZER_NAME_FQ)!!.owner
|
||||
val targetIrType =
|
||||
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.builtIns.anyType.toIrType()))
|
||||
|
||||
val call = IrCallImpl(startOffset, endOffset, type, lazyFunctionSymbol, 0, 2)
|
||||
call.putValueArgument(
|
||||
0,
|
||||
IrGetEnumValueImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
publicationEntryDescriptor.classValueType!!.toIrType(),
|
||||
compilerContext.symbolTable.referenceEnumEntry(publicationEntryDescriptor)
|
||||
),
|
||||
val property = createLazyProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
|
||||
val expr = serializerInstance(
|
||||
this@SerializableCompanionIrGenerator,
|
||||
serializerDescriptor, serializableDescriptor.module,
|
||||
serializableDescriptor.defaultType
|
||||
)
|
||||
|
||||
call.putValueArgument(
|
||||
1,
|
||||
IrFunctionExpressionImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
function0Descriptor.defaultType.toIrType(),
|
||||
lambda,
|
||||
IrStatementOrigin.LAMBDA
|
||||
),
|
||||
)
|
||||
|
||||
initializer = irClass.factory.createExpressionBody(startOffset, endOffset, call)
|
||||
patchSerializableClassWithMarkerAnnotation(serializerDescriptor)
|
||||
+irReturn(requireNotNull(expr))
|
||||
}
|
||||
|
||||
val valueGetter = compilerContext.referenceClass(lazyDescriptor.fqNameSafe)!!.getPropertyGetter("value")!!
|
||||
|
||||
irClass.contributeFunction(methodDescriptor) {
|
||||
+irReturn(
|
||||
irGet(
|
||||
serializerDescriptor.defaultType.toIrType(),
|
||||
irGetField(null, field), valueGetter
|
||||
)
|
||||
)
|
||||
+irReturn(getLazyValueExpression(irClass, property))
|
||||
}
|
||||
generateSerializerFactoryIfNeeded(methodDescriptor)
|
||||
}
|
||||
|
||||
+26
-36
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.codegen.CompilationException
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
@@ -19,7 +18,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -29,7 +27,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.INITIALIZED_DESCRIPTOR_FIELD_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_DESCRIPTOR_FIELD_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESC_FIELD
|
||||
|
||||
@@ -39,8 +37,6 @@ class SerializableIrGenerator(
|
||||
bindingContext: BindingContext
|
||||
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
||||
|
||||
private val descriptorGenerationFunctionName = Name.identifier("createInitializedDescriptor")
|
||||
|
||||
private val serialDescClass: ClassDescriptor = serializableDescriptor.module
|
||||
.getClassFromSerializationDescriptorsPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS)
|
||||
|
||||
@@ -116,7 +112,14 @@ class SerializableIrGenerator(
|
||||
// for abstract classes fields MUST BE checked in child classes
|
||||
!serializableDescriptor.isAbstractSerializableClass() && !serializableDescriptor.isSealedSerializableClass()
|
||||
) {
|
||||
generateGoldenMaskCheck(seenVars, properties, getSerialDescriptorExpr())
|
||||
val getDescriptorExpr = if (serializableDescriptor.isStaticSerializable) {
|
||||
getStaticSerialDescriptorExpr()
|
||||
} else {
|
||||
// synthetic constructor is created only for internally serializable classes - so companion definitely exists
|
||||
val companionObject = irClass.companionObject()!!
|
||||
getParametrizedSerialDescriptorExpr(companionObject, createCachedDescriptorProperty(companionObject))
|
||||
}
|
||||
generateGoldenMaskCheck(seenVars, properties, getDescriptorExpr)
|
||||
}
|
||||
when {
|
||||
superClass.symbol == compilerContext.irBuiltIns.anyClass -> generateAnySuperConstructorCall(toBuilder = this@contributeConstructor)
|
||||
@@ -167,29 +170,25 @@ class SerializableIrGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBlockBodyBuilder.getSerialDescriptorExpr(): IrExpression {
|
||||
return if (serializableDescriptor.isStaticSerializable) {
|
||||
val serializer = serializableDescriptor.classSerializer!!
|
||||
val serialDescriptorGetter = compilerContext.referenceClass(serializer.fqNameSafe)!!.getPropertyGetter(SERIAL_DESC_FIELD)!!
|
||||
irGet(
|
||||
serialDescriptorGetter.owner.returnType,
|
||||
irGetObject(serializer),
|
||||
serialDescriptorGetter.owner.symbol
|
||||
)
|
||||
} else {
|
||||
irGetField(null, generateStaticDescriptorField())
|
||||
}
|
||||
private fun IrBlockBodyBuilder.getStaticSerialDescriptorExpr(): IrExpression {
|
||||
val serializer = serializableDescriptor.classSerializer!!
|
||||
val serialDescriptorGetter = compilerContext.referenceClass(serializer.fqNameSafe)?.getPropertyGetter(SERIAL_DESC_FIELD)
|
||||
?: throw Exception("No class with name ${serializer.fqNameSafe}")
|
||||
return irGet(
|
||||
serialDescriptorGetter.owner.returnType,
|
||||
irGetObject(serializer),
|
||||
serialDescriptorGetter.owner.symbol
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrBlockBodyBuilder.generateStaticDescriptorField(): IrField {
|
||||
val serialDescItType = serialDescClass.defaultType.toIrType()
|
||||
private fun IrBlockBodyBuilder.getParametrizedSerialDescriptorExpr(companionObject: IrClass, property: IrProperty): IrExpression {
|
||||
return irGetField(irGetObject(companionObject), property.backingField!!)
|
||||
}
|
||||
|
||||
val function = irClass.createInlinedFunction(
|
||||
descriptorGenerationFunctionName,
|
||||
DescriptorVisibilities.PRIVATE,
|
||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||
serialDescItType
|
||||
) {
|
||||
private fun IrBlockBodyBuilder.createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
|
||||
val serialDescIrType = serialDescClass.defaultType.toIrType()
|
||||
|
||||
return createCompanionValProperty(companionObject, serialDescIrType, CACHED_DESCRIPTOR_FIELD_NAME) {
|
||||
val serialDescVar = irTemporary(
|
||||
getInstantiateDescriptorExpr(),
|
||||
nameHint = "serialDesc"
|
||||
@@ -197,17 +196,8 @@ class SerializableIrGenerator(
|
||||
for (property in properties.serializableProperties) {
|
||||
+getAddElementToDescriptorExpr(property, serialDescVar)
|
||||
}
|
||||
+irReturn(irGet(serialDescVar))
|
||||
+irGet(serialDescVar)
|
||||
}
|
||||
|
||||
return irClass.addField {
|
||||
name = Name.identifier(INITIALIZED_DESCRIPTOR_FIELD_NAME)
|
||||
visibility = DescriptorVisibilities.PRIVATE
|
||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||
isFinal = true
|
||||
isStatic = true
|
||||
type = serialDescItType
|
||||
}.apply { initializer = irClass.factory.createExpressionBody(irCall(function)) }
|
||||
}
|
||||
|
||||
private fun IrBlockBodyBuilder.getInstantiateDescriptorExpr(): IrExpression {
|
||||
|
||||
+4
-4
@@ -35,7 +35,7 @@ import org.jetbrains.kotlinx.serialization.compiler.diagnostic.VersionReader
|
||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.INITIALIZED_DESCRIPTOR_FIELD_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_DESCRIPTOR_FIELD
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -354,7 +354,7 @@ class SerializableCodegenImpl(
|
||||
} else {
|
||||
generateStaticDescriptorField()
|
||||
|
||||
getstatic(thisAsmType.internalName, INITIALIZED_DESCRIPTOR_FIELD_NAME, descType.descriptor)
|
||||
getstatic(thisAsmType.internalName, CACHED_DESCRIPTOR_FIELD, descType.descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ class SerializableCodegenImpl(
|
||||
val flags = Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_STATIC
|
||||
classCodegen.v.newField(
|
||||
OtherOrigin(classCodegen.myClass.psiOrParent), flags,
|
||||
INITIALIZED_DESCRIPTOR_FIELD_NAME, descType.descriptor, null, null
|
||||
CACHED_DESCRIPTOR_FIELD, descType.descriptor, null, null
|
||||
)
|
||||
|
||||
val clInit = classCodegen.createOrGetClInitCodegen()
|
||||
@@ -380,7 +380,7 @@ class SerializableCodegenImpl(
|
||||
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false)
|
||||
}
|
||||
|
||||
putstatic(thisAsmType.internalName, INITIALIZED_DESCRIPTOR_FIELD_NAME, descType.descriptor)
|
||||
putstatic(thisAsmType.internalName, CACHED_DESCRIPTOR_FIELD, descType.descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -23,11 +23,12 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_LAZY_DELEGATE_FIELD_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_SERIALIZER_PROPERTY
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getKSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.shouldHaveGeneratedMethodsInCompanion
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.toSimpleType
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationBodyCodegen) :
|
||||
@@ -42,11 +43,13 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
||||
}
|
||||
|
||||
override fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||
val fieldName = "$CACHED_SERIALIZER_PROPERTY\$delegate"
|
||||
|
||||
// Create field for lazy delegate
|
||||
classCodegen.v.newField(
|
||||
OtherOrigin(classCodegen.myClass.psiOrParent),
|
||||
Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_STATIC,
|
||||
SERIALIZER_LAZY_DELEGATE_FIELD_NAME,
|
||||
fieldName,
|
||||
kotlinLazyType.descriptor,
|
||||
"L${kotlinLazyType.internalName}<L${kSerializerType.internalName}<*>;>;",
|
||||
null
|
||||
@@ -75,7 +78,7 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
||||
// initialize lazy delegate
|
||||
val clInit = classCodegen.createOrGetClInitCodegen()
|
||||
with(clInit.v) {
|
||||
getstatic(threadSafeModeType.internalName, "PUBLICATION", threadSafeModeType.descriptor)
|
||||
getstatic(threadSafeModeType.internalName, LAZY_PUBLICATION_MODE_NAME.identifier, threadSafeModeType.descriptor)
|
||||
getstatic(lambdaType.internalName, JvmAbi.INSTANCE_FIELD, lambdaType.descriptor)
|
||||
checkcast(function0Type)
|
||||
invokestatic(
|
||||
@@ -84,12 +87,12 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
||||
"(${threadSafeModeType.descriptor}${function0Type.descriptor})${kotlinLazyType.descriptor}",
|
||||
false
|
||||
)
|
||||
putstatic(classCodegen.className, SERIALIZER_LAZY_DELEGATE_FIELD_NAME, kotlinLazyType.descriptor)
|
||||
putstatic(classCodegen.className, fieldName, kotlinLazyType.descriptor)
|
||||
}
|
||||
|
||||
// create serializer getter
|
||||
classCodegen.generateMethod(methodDescriptor) { _, _ ->
|
||||
getstatic(classCodegen.className, SERIALIZER_LAZY_DELEGATE_FIELD_NAME, kotlinLazyType.descriptor)
|
||||
getstatic(classCodegen.className, fieldName, kotlinLazyType.descriptor)
|
||||
invokeinterface(kotlinLazyType.internalName, getLazyValueName, "()Ljava/lang/Object;")
|
||||
checkcast(kSerializerType)
|
||||
areturn(kSerializerType)
|
||||
|
||||
+34
@@ -290,6 +290,40 @@ object KSerializerDescriptorResolver {
|
||||
return functionDescriptor
|
||||
}
|
||||
|
||||
fun createValPropertyDescriptor(
|
||||
name: Name,
|
||||
containingClassDescriptor: ClassDescriptor,
|
||||
type: KotlinType,
|
||||
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE,
|
||||
createGetter: Boolean = false
|
||||
): PropertyDescriptor {
|
||||
val propertyDescriptor = PropertyDescriptorImpl.create(
|
||||
containingClassDescriptor,
|
||||
Annotations.EMPTY, Modality.FINAL, visibility, false, name,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED, containingClassDescriptor.source, false, false, false, false, false, false
|
||||
)
|
||||
val extensionReceiverParameter: ReceiverParameterDescriptor? = null // kludge to disambiguate call
|
||||
propertyDescriptor.setType(
|
||||
type,
|
||||
emptyList(), // no need type parameters?
|
||||
containingClassDescriptor.thisAsReceiverParameter,
|
||||
extensionReceiverParameter
|
||||
)
|
||||
|
||||
val propertyGetter: PropertyGetterDescriptorImpl? = if (createGetter) {
|
||||
PropertyGetterDescriptorImpl(
|
||||
propertyDescriptor, Annotations.EMPTY, Modality.FINAL, visibility, false, false, false,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED, null, containingClassDescriptor.source
|
||||
).apply { initialize(type) }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
propertyDescriptor.initialize(propertyGetter, null)
|
||||
|
||||
return propertyDescriptor
|
||||
}
|
||||
|
||||
fun createLoadConstructorDescriptor(
|
||||
classDescriptor: ClassDescriptor,
|
||||
bindingContext: BindingContext,
|
||||
|
||||
+13
-2
@@ -44,8 +44,8 @@ object SerialEntityNames {
|
||||
const val LOAD = "deserialize"
|
||||
const val SERIALIZER_CLASS = "\$serializer"
|
||||
|
||||
const val INITIALIZED_DESCRIPTOR_FIELD_NAME = "\$initializedDescriptor"
|
||||
const val SERIALIZER_LAZY_DELEGATE_FIELD_NAME = "\$serializer\$delegate"
|
||||
const val CACHED_DESCRIPTOR_FIELD = "\$cachedDescriptor"
|
||||
const val CACHED_SERIALIZER_PROPERTY = "\$cachedSerializer"
|
||||
|
||||
// classes
|
||||
val KSERIALIZER_NAME = Name.identifier(KSERIALIZER_CLASS)
|
||||
@@ -91,6 +91,8 @@ object SerialEntityNames {
|
||||
val ARRAY_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwArrayMissingFieldException")
|
||||
val SINGLE_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(SINGLE_MASK_FIELD_MISSING_FUNC_NAME)
|
||||
val ARRAY_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ARRAY_MASK_FIELD_MISSING_FUNC_NAME)
|
||||
val CACHED_SERIALIZER_PROPERTY_NAME = Name.identifier(CACHED_SERIALIZER_PROPERTY)
|
||||
val CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
|
||||
|
||||
// parameters
|
||||
val dummyParamName = Name.identifier("serializationConstructorMarker")
|
||||
@@ -129,3 +131,12 @@ object CallingConventions {
|
||||
const val addAnnotation = "pushAnnotation"
|
||||
const val addClassAnnotation = "pushClassAnnotation"
|
||||
}
|
||||
|
||||
internal object SerializationDependencies {
|
||||
val LAZY_FQ = FqName("kotlin.Lazy")
|
||||
val LAZY_FUNC_FQ = FqName("kotlin.lazy")
|
||||
val LAZY_MODE_FQ = FqName("kotlin.LazyThreadSafetyMode")
|
||||
val KPROPERTY1_FQ = FqName("kotlin.reflect.KProperty1")
|
||||
val FUNCTION0_FQ = FqName("kotlin.Function0")
|
||||
val LAZY_PUBLICATION_MODE_NAME = Name.identifier("PUBLICATION")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user