Lazy delegate for serializer in objects, sealed and abstract classes
Fixes Kotlin/kotlinx.serialization#585
This commit is contained in:
-1
@@ -17,7 +17,6 @@ abstract class SerializableCodegen(
|
|||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
|
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
|
||||||
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
|
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
|
||||||
protected val staticDescriptor = serializableDescriptor.declaredTypeParameters.isEmpty()
|
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
generateSyntheticInternalConstructor()
|
generateSyntheticInternalConstructor()
|
||||||
|
|||||||
+12
-4
@@ -21,9 +21,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
|
|
||||||
|
|
||||||
abstract class SerializableCompanionCodegen(
|
abstract class SerializableCompanionCodegen(
|
||||||
protected val companionDescriptor: ClassDescriptor,
|
protected val companionDescriptor: ClassDescriptor,
|
||||||
@@ -44,8 +43,17 @@ abstract class SerializableCompanionCodegen(
|
|||||||
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
||||||
"probably clash with user-defined function has occurred"
|
"probably clash with user-defined function has occurred"
|
||||||
)
|
)
|
||||||
generateSerializerGetter(serializerGetterDescriptor)
|
|
||||||
|
if (serializableDescriptor.isSerializableObject || serializableDescriptor.isSealedSerializableClass() || serializableDescriptor.isAbstractSerializableClass()) {
|
||||||
|
generateLazySerializerGetter(serializerGetterDescriptor)
|
||||||
|
} else {
|
||||||
|
generateSerializerGetter(serializerGetterDescriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun generateSerializerGetter(methodDescriptor: FunctionDescriptor)
|
protected abstract fun generateSerializerGetter(methodDescriptor: FunctionDescriptor)
|
||||||
}
|
|
||||||
|
protected open fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
|
generateSerializerGetter(methodDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
@@ -101,6 +101,8 @@ fun ClassDescriptor.serialName(): String {
|
|||||||
return annotations.serialNameValue ?: fqNameUnsafe.asString()
|
return annotations.serialNameValue ?: fqNameUnsafe.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val ClassDescriptor.isStaticSerializable: Boolean get() = this.declaredTypeParameters.isEmpty()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns class descriptor for ContextSerializer or PolymorphicSerializer
|
* Returns class descriptor for ContextSerializer or PolymorphicSerializer
|
||||||
* if [annotations] contains @Contextual or @Polymorphic annotation
|
* if [annotations] contains @Contextual or @Polymorphic annotation
|
||||||
|
|||||||
+30
@@ -105,6 +105,26 @@ interface IrBuilderExtension {
|
|||||||
return function
|
return function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrClass.createSingletonLambda(
|
||||||
|
returnType: IrType,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
bodyGen: IrBlockBodyBuilder.() -> Unit
|
||||||
|
): IrSimpleFunction {
|
||||||
|
val function = compilerContext.irFactory.buildFun {
|
||||||
|
this.startOffset = startOffset
|
||||||
|
this.endOffset = endOffset
|
||||||
|
this.returnType = returnType
|
||||||
|
name = Name.identifier("<anonymous>")
|
||||||
|
visibility = DescriptorVisibilities.LOCAL
|
||||||
|
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||||
|
}
|
||||||
|
function.body =
|
||||||
|
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
||||||
|
|
||||||
|
return function
|
||||||
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irInvoke(
|
fun IrBuilderWithScope.irInvoke(
|
||||||
dispatchReceiver: IrExpression? = null,
|
dispatchReceiver: IrExpression? = null,
|
||||||
callee: IrFunctionSymbol,
|
callee: IrFunctionSymbol,
|
||||||
@@ -147,6 +167,16 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ClassDescriptor.referenceFunctionSymbol(
|
||||||
|
functionName: String,
|
||||||
|
predicate: (IrSimpleFunction) -> Boolean = { true }
|
||||||
|
): IrFunctionSymbol {
|
||||||
|
val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this")
|
||||||
|
val simpleFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
||||||
|
|
||||||
|
return simpleFunctions.filter { it.name.asString() == functionName }.single { predicate(it) }.symbol
|
||||||
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.createPrimitiveArrayOfExpression(
|
fun IrBuilderWithScope.createPrimitiveArrayOfExpression(
|
||||||
elementPrimitiveType: IrType,
|
elementPrimitiveType: IrType,
|
||||||
arrayElements: List<IrExpression>
|
arrayElements: List<IrExpression>
|
||||||
|
|||||||
+92
-7
@@ -7,20 +7,22 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irInt
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
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.patchDeclarationParents
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
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.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||||
@@ -34,6 +36,25 @@ class SerializableCompanionIrGenerator(
|
|||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
) : 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 {
|
companion object {
|
||||||
fun generate(
|
fun generate(
|
||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
@@ -84,6 +105,70 @@ class SerializableCompanionIrGenerator(
|
|||||||
irSerializableClass.annotations += annotationCtorCall
|
irSerializableClass.annotations += annotationCtorCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
|
val serializerDescriptor = requireNotNull(
|
||||||
|
findTypeSerializer(
|
||||||
|
serializableDescriptor.module,
|
||||||
|
serializableDescriptor.toSimpleType()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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 call = IrCallImpl(startOffset, endOffset, type, lazyFunctionSymbol, 0, 2)
|
||||||
|
call.putValueArgument(
|
||||||
|
0,
|
||||||
|
IrGetEnumValueImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
publicationEntryDescriptor.classValueType!!.toIrType(),
|
||||||
|
compilerContext.symbolTable.referenceEnumEntry(publicationEntryDescriptor)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
call.putValueArgument(
|
||||||
|
1,
|
||||||
|
IrFunctionExpressionImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
function0Descriptor.defaultType.toIrType(),
|
||||||
|
lambda,
|
||||||
|
IrStatementOrigin.LAMBDA
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
initializer = irClass.factory.createExpressionBody(startOffset, endOffset, call)
|
||||||
|
}
|
||||||
|
|
||||||
|
val valueGetter = compilerContext.referenceClass(lazyDescriptor.fqNameSafe)!!.getPropertyGetter("value")!!
|
||||||
|
|
||||||
|
irClass.contributeFunction(methodDescriptor) {
|
||||||
|
+irReturn(
|
||||||
|
irGet(
|
||||||
|
serializerDescriptor.defaultType.toIrType(),
|
||||||
|
irGetField(null, field), valueGetter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
generateSerializerFactoryIfNeeded(methodDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
irClass.contributeFunction(methodDescriptor) { getter ->
|
irClass.contributeFunction(methodDescriptor) { getter ->
|
||||||
val serializer = requireNotNull(
|
val serializer = requireNotNull(
|
||||||
@@ -138,4 +223,4 @@ class SerializableCompanionIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-17
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
@@ -27,13 +26,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
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.MISSING_FIELD_EXC
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESC_FIELD
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESC_FIELD
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.initializedDescriptorFieldName
|
|
||||||
|
|
||||||
class SerializableIrGenerator(
|
class SerializableIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
@@ -41,7 +41,7 @@ class SerializableIrGenerator(
|
|||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
) : SerializableCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
||||||
|
|
||||||
private val descriptorGenerationFunctionName = "createInitializedDescriptor"
|
private val descriptorGenerationFunctionName = Name.identifier("createInitializedDescriptor")
|
||||||
|
|
||||||
private val serialDescClass: ClassDescriptor = serializableDescriptor.module
|
private val serialDescClass: ClassDescriptor = serializableDescriptor.module
|
||||||
.getClassFromSerializationDescriptorsPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS)
|
.getClassFromSerializationDescriptorsPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS)
|
||||||
@@ -49,7 +49,7 @@ class SerializableIrGenerator(
|
|||||||
private val serialDescImplClass: ClassDescriptor = serializableDescriptor
|
private val serialDescImplClass: ClassDescriptor = serializableDescriptor
|
||||||
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
.getClassFromInternalSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL)
|
||||||
|
|
||||||
private val addElementFun = serialDescImplClass.findFunctionSymbol(CallingConventions.addElement)
|
private val addElementFun = serialDescImplClass.referenceFunctionSymbol(CallingConventions.addElement)
|
||||||
|
|
||||||
private fun IrClass.hasSerializableAnnotationWithoutArgs(): Boolean {
|
private fun IrClass.hasSerializableAnnotationWithoutArgs(): Boolean {
|
||||||
val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName) ?: return false
|
val annot = getAnnotation(SerializationAnnotations.serializableAnnotationFqName) ?: return false
|
||||||
@@ -170,7 +170,7 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.getSerialDescriptorExpr(): IrExpression {
|
private fun IrBlockBodyBuilder.getSerialDescriptorExpr(): IrExpression {
|
||||||
return if (serializableDescriptor.shouldHaveGeneratedSerializer && staticDescriptor) {
|
return if (serializableDescriptor.isStaticSerializable) {
|
||||||
val serializer = serializableDescriptor.classSerializer!!
|
val serializer = serializableDescriptor.classSerializer!!
|
||||||
val serialDescriptorGetter = compilerContext.referenceClass(serializer.fqNameSafe)!!.getPropertyGetter(SERIAL_DESC_FIELD)!!
|
val serialDescriptorGetter = compilerContext.referenceClass(serializer.fqNameSafe)!!.getPropertyGetter(SERIAL_DESC_FIELD)!!
|
||||||
irGet(
|
irGet(
|
||||||
@@ -187,7 +187,7 @@ class SerializableIrGenerator(
|
|||||||
val serialDescItType = serialDescClass.defaultType.toIrType()
|
val serialDescItType = serialDescClass.defaultType.toIrType()
|
||||||
|
|
||||||
val function = irClass.createInlinedFunction(
|
val function = irClass.createInlinedFunction(
|
||||||
Name.identifier(descriptorGenerationFunctionName),
|
descriptorGenerationFunctionName,
|
||||||
DescriptorVisibilities.PRIVATE,
|
DescriptorVisibilities.PRIVATE,
|
||||||
SERIALIZABLE_PLUGIN_ORIGIN,
|
SERIALIZABLE_PLUGIN_ORIGIN,
|
||||||
serialDescItType
|
serialDescItType
|
||||||
@@ -203,7 +203,7 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return irClass.addField {
|
return irClass.addField {
|
||||||
name = Name.identifier(initializedDescriptorFieldName)
|
name = Name.identifier(INITIALIZED_DESCRIPTOR_FIELD_NAME)
|
||||||
visibility = DescriptorVisibilities.PRIVATE
|
visibility = DescriptorVisibilities.PRIVATE
|
||||||
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
origin = SERIALIZABLE_PLUGIN_ORIGIN
|
||||||
isFinal = true
|
isFinal = true
|
||||||
@@ -234,16 +234,6 @@ class SerializableIrGenerator(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun ClassDescriptor.findFunctionSymbol(
|
|
||||||
functionName: String,
|
|
||||||
predicate: (IrSimpleFunction) -> Boolean = { true }
|
|
||||||
): IrFunctionSymbol {
|
|
||||||
val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this")
|
|
||||||
val simpleFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
|
||||||
|
|
||||||
return simpleFunctions.filter { it.name.asString() == functionName }.single { predicate(it) }.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) {
|
private fun IrBlockBodyBuilder.generateSuperNonSerializableCall(superClass: IrClass) {
|
||||||
val ctorRef = superClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.valueParameters.isEmpty() }
|
val ctorRef = superClass.declarations.filterIsInstance<IrConstructor>().singleOrNull { it.valueParameters.isEmpty() }
|
||||||
?: error("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
|
?: error("Non-serializable parent of serializable $serializableDescriptor must have no arg constructor")
|
||||||
|
|||||||
+3
-3
@@ -36,7 +36,7 @@ class SerializerForEnumsGenerator(
|
|||||||
|
|
||||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||||
val encodeEnum = encoderClass.referenceMethod(CallingConventions.encodeEnum)
|
val encodeEnum = encoderClass.referenceFunctionSymbol(CallingConventions.encodeEnum)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
||||||
@@ -52,7 +52,7 @@ class SerializerForEnumsGenerator(
|
|||||||
|
|
||||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||||
val decode = decoderClass.referenceMethod(CallingConventions.decodeEnum)
|
val decode = decoderClass.referenceFunctionSymbol(CallingConventions.decodeEnum)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
|
||||||
@@ -109,7 +109,7 @@ class SerializerForEnumsGenerator(
|
|||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
entry.annotations.mapNotNull(compilerContext.typeTranslator.constantValueGenerator::generateAnnotationConstructorCall),
|
entry.annotations.mapNotNull(compilerContext.typeTranslator.constantValueGenerator::generateAnnotationConstructorCall),
|
||||||
localDescriptor,
|
localDescriptor,
|
||||||
serialDescImplClass.referenceMethod(CallingConventions.addAnnotation)
|
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addAnnotation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -32,7 +32,7 @@ class SerializerForInlineClassGenerator(
|
|||||||
|
|
||||||
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
val encoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.ENCODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||||
val encodeInline = encoderClass.referenceMethod(CallingConventions.encodeInline)
|
val encodeInline = encoderClass.referenceFunctionSymbol(CallingConventions.encodeInline)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
// val inlineEncoder = encoder.encodeInline()
|
// val inlineEncoder = encoder.encodeInline()
|
||||||
@@ -45,14 +45,14 @@ class SerializerForInlineClassGenerator(
|
|||||||
// inlineEncoder.encodeInt/String/SerializableValue
|
// inlineEncoder.encodeInt/String/SerializableValue
|
||||||
val elementCall = formEncodeDecodePropertyCall(irGet(inlineEncoder), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
val elementCall = formEncodeDecodePropertyCall(irGet(inlineEncoder), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||||
val f =
|
val f =
|
||||||
encoderClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}SerializableValue")
|
encoderClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}SerializableValue")
|
||||||
f to listOf(
|
f to listOf(
|
||||||
innerSerial,
|
innerSerial,
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
val f =
|
val f =
|
||||||
encoderClass.referenceMethod("${CallingConventions.encode}${it.elementMethodPrefix}")
|
encoderClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}")
|
||||||
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
||||||
f to args
|
f to args
|
||||||
})
|
})
|
||||||
@@ -67,7 +67,7 @@ class SerializerForInlineClassGenerator(
|
|||||||
|
|
||||||
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
val decoderClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.DECODER_CLASS)
|
||||||
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
val descriptorGetterSymbol = irAnySerialDescProperty?.owner?.getter!!.symbol
|
||||||
val decodeInline = decoderClass.referenceMethod(CallingConventions.decodeInline)
|
val decodeInline = decoderClass.referenceFunctionSymbol(CallingConventions.decodeInline)
|
||||||
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
|
||||||
|
|
||||||
// val inlineDecoder = decoder.decodeInline()
|
// val inlineDecoder = decoder.decodeInline()
|
||||||
@@ -76,9 +76,9 @@ class SerializerForInlineClassGenerator(
|
|||||||
val property = serializableProperties.first()
|
val property = serializableProperties.first()
|
||||||
val inlinedType = property.type.toIrType()
|
val inlinedType = property.type.toIrType()
|
||||||
val actualCall = formEncodeDecodePropertyCall(inlineDecoder, loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
val actualCall = formEncodeDecodePropertyCall(inlineDecoder, loadFunc.dispatchReceiverParameter!!, property, { innerSerial, sti ->
|
||||||
decoderClass.referenceMethod( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
decoderClass.referenceFunctionSymbol( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
||||||
}, {
|
}, {
|
||||||
decoderClass.referenceMethod("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
decoderClass.referenceFunctionSymbol("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
||||||
}, returnTypeHint = inlinedType)
|
}, returnTypeHint = inlinedType)
|
||||||
val value = coerceToBox(actualCall, loadFunc.returnType)
|
val value = coerceToBox(actualCall, loadFunc.returnType)
|
||||||
+irReturn(value)
|
+irReturn(value)
|
||||||
@@ -111,4 +111,4 @@ class SerializerForInlineClassGenerator(
|
|||||||
|
|
||||||
private fun IrBlockBodyBuilder.getFromBox(expression: IrExpression, serializableProperty: SerializableProperty): IrExpression =
|
private fun IrBlockBodyBuilder.getFromBox(expression: IrExpression, serializableProperty: SerializableProperty): IrExpression =
|
||||||
getProperty(expression, serializableProperty.getIrPropertyFrom(serializableIrClass))
|
getProperty(expression, serializableProperty.getIrPropertyFrom(serializableIrClass))
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-20
@@ -58,7 +58,7 @@ open class SerializerIrGenerator(
|
|||||||
|
|
||||||
override fun generateSerialDesc() {
|
override fun generateSerialDesc() {
|
||||||
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
|
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
|
||||||
val addFuncS = serialDescImplClass.referenceMethod(CallingConventions.addElement)
|
val addFuncS = serialDescImplClass.referenceFunctionSymbol(CallingConventions.addElement)
|
||||||
|
|
||||||
val thisAsReceiverParameter = irClass.thisReceiver!!
|
val thisAsReceiverParameter = irClass.thisReceiver!!
|
||||||
lateinit var prop: IrProperty
|
lateinit var prop: IrProperty
|
||||||
@@ -95,7 +95,7 @@ open class SerializerIrGenerator(
|
|||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
serializableIrClass.annotations,
|
serializableIrClass.annotations,
|
||||||
localDesc,
|
localDesc,
|
||||||
serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation)
|
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addClassAnnotation)
|
||||||
)
|
)
|
||||||
|
|
||||||
// save local descriptor to field
|
// save local descriptor to field
|
||||||
@@ -145,7 +145,7 @@ open class SerializerIrGenerator(
|
|||||||
copySerialInfoAnnotationsToDescriptor(
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
property.annotations,
|
property.annotations,
|
||||||
localDescriptor,
|
localDescriptor,
|
||||||
serialDescImplClass.referenceMethod(CallingConventions.addAnnotation)
|
serialDescImplClass.referenceFunctionSymbol(CallingConventions.addAnnotation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,12 +233,6 @@ open class SerializerIrGenerator(
|
|||||||
/* Already implemented in .generateSerialClassDesc ? */
|
/* Already implemented in .generateSerialClassDesc ? */
|
||||||
}
|
}
|
||||||
|
|
||||||
protected inline fun ClassDescriptor.referenceMethod(methodName: String, predicate: (IrSimpleFunction) -> Boolean = { true }): IrFunctionSymbol {
|
|
||||||
val irClass = compilerContext.referenceClass(fqNameSafe)?.owner ?: error("Couldn't load class $this")
|
|
||||||
val simpleFunctions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
|
||||||
return simpleFunctions.filter { it.name.asString() == methodName }.single { predicate(it) }.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
|
||||||
|
|
||||||
fun irThis(): IrExpression =
|
fun irThis(): IrExpression =
|
||||||
@@ -252,7 +246,7 @@ open class SerializerIrGenerator(
|
|||||||
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
|
||||||
|
|
||||||
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
|
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
|
||||||
val beginFunc = encoderClass.referenceMethod(CallingConventions.begin) { it.valueParameters.size == 1 }
|
val beginFunc = encoderClass.referenceFunctionSymbol(CallingConventions.begin) { it.valueParameters.size == 1 }
|
||||||
|
|
||||||
val call = irCall(beginFunc, type = kOutputClass.defaultType.toIrType()).mapValueParametersIndexed { _, _ ->
|
val call = irCall(beginFunc, type = kOutputClass.defaultType.toIrType()).mapValueParametersIndexed { _, _ ->
|
||||||
irGet(localSerialDesc)
|
irGet(localSerialDesc)
|
||||||
@@ -294,7 +288,7 @@ open class SerializerIrGenerator(
|
|||||||
// output.writeXxxElementValue(classDesc, index, value)
|
// output.writeXxxElementValue(classDesc, index, value)
|
||||||
val elementCall = formEncodeDecodePropertyCall(irGet(localOutput), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
val elementCall = formEncodeDecodePropertyCall(irGet(localOutput), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||||
val f =
|
val f =
|
||||||
kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
|
kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
|
||||||
f to listOf(
|
f to listOf(
|
||||||
irGet(localSerialDesc),
|
irGet(localSerialDesc),
|
||||||
irInt(index),
|
irInt(index),
|
||||||
@@ -303,7 +297,7 @@ open class SerializerIrGenerator(
|
|||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
val f =
|
val f =
|
||||||
kOutputClass.referenceMethod("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}")
|
||||||
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
val args: MutableList<IrExpression> = mutableListOf(irGet(localSerialDesc), irInt(index))
|
||||||
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
||||||
f to args
|
f to args
|
||||||
@@ -318,7 +312,7 @@ open class SerializerIrGenerator(
|
|||||||
// if ( if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
// if ( if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) {
|
||||||
// output.encodeIntElement(this.descriptor, i, obj.prop)
|
// output.encodeIntElement(this.descriptor, i, obj.prop)
|
||||||
// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
// block {obj.prop != DEFAULT_VALUE} may contain several statements
|
||||||
val shouldEncodeFunc = kOutputClass.referenceMethod(CallingConventions.shouldEncodeDefault)
|
val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault)
|
||||||
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index))
|
||||||
val partB = irNotEquals(property.irGet(), initializerAdapter(property.irField.initializer!!))
|
val partB = irNotEquals(property.irGet(), initializerAdapter(property.irField.initializer!!))
|
||||||
// Ir infrastructure does not have dedicated symbol for ||, so
|
// Ir infrastructure does not have dedicated symbol for ||, so
|
||||||
@@ -329,7 +323,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// output.writeEnd(serialClassDesc)
|
// output.writeEnd(serialClassDesc)
|
||||||
val wEndFunc = kOutputClass.referenceMethod(CallingConventions.end)
|
val wEndFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.end)
|
||||||
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
|
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +418,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//input = input.beginStructure(...)
|
//input = input.beginStructure(...)
|
||||||
val beginFunc = decoderClass.referenceMethod(CallingConventions.begin) { it.valueParameters.size == 1 }
|
val beginFunc = decoderClass.referenceFunctionSymbol(CallingConventions.begin) { it.valueParameters.size == 1 }
|
||||||
val call = irInvoke(
|
val call = irInvoke(
|
||||||
irGet(loadFunc.valueParameters[0]),
|
irGet(loadFunc.valueParameters[0]),
|
||||||
beginFunc,
|
beginFunc,
|
||||||
@@ -438,13 +432,13 @@ open class SerializerIrGenerator(
|
|||||||
serializableProperties.mapIndexed { index, property ->
|
serializableProperties.mapIndexed { index, property ->
|
||||||
val body = irBlock {
|
val body = irBlock {
|
||||||
val decodeFuncToCall = formEncodeDecodePropertyCall(localInput.get(), loadFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
val decodeFuncToCall = formEncodeDecodePropertyCall(localInput.get(), loadFunc.dispatchReceiverParameter!!, property, {innerSerial, sti ->
|
||||||
inputClass.referenceMethod(
|
inputClass.referenceFunctionSymbol(
|
||||||
"${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}", {it.valueParameters.size == 4}
|
"${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}", {it.valueParameters.size == 4}
|
||||||
) to listOf(
|
) to listOf(
|
||||||
localSerialDesc.get(), irInt(index), innerSerial, serialPropertiesMap.getValue(property.descriptor).get()
|
localSerialDesc.get(), irInt(index), innerSerial, serialPropertiesMap.getValue(property.descriptor).get()
|
||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
inputClass.referenceMethod(
|
inputClass.referenceFunctionSymbol(
|
||||||
"${CallingConventions.decode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}", {it.valueParameters.size == 2}
|
"${CallingConventions.decode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}", {it.valueParameters.size == 2}
|
||||||
) to listOf(
|
) to listOf(
|
||||||
localSerialDesc.get(), irInt(index)
|
localSerialDesc.get(), irInt(index)
|
||||||
@@ -464,7 +458,7 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if (decoder.decodeSequentially())
|
// if (decoder.decodeSequentially())
|
||||||
val decodeSequentiallyCall = irInvoke(localInput.get(), inputClass.referenceMethod(CallingConventions.decodeSequentially))
|
val decodeSequentiallyCall = irInvoke(localInput.get(), inputClass.referenceFunctionSymbol(CallingConventions.decodeSequentially))
|
||||||
|
|
||||||
val sequentialPart = irBlock {
|
val sequentialPart = irBlock {
|
||||||
decoderCalls.forEach { (_, expr) -> +expr.deepCopyWithVariables() }
|
decoderCalls.forEach { (_, expr) -> +expr.deepCopyWithVariables() }
|
||||||
@@ -473,7 +467,7 @@ open class SerializerIrGenerator(
|
|||||||
val byIndexPart: IrExpression = irWhile().also { loop ->
|
val byIndexPart: IrExpression = irWhile().also { loop ->
|
||||||
loop.condition = flagVar.get()
|
loop.condition = flagVar.get()
|
||||||
loop.body = irBlock {
|
loop.body = irBlock {
|
||||||
val readElementF = inputClass.referenceMethod(CallingConventions.decodeElementIndex)
|
val readElementF = inputClass.referenceFunctionSymbol(CallingConventions.decodeElementIndex)
|
||||||
+irSet(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
|
+irSet(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
|
||||||
+irWhen {
|
+irWhen {
|
||||||
// if index == -1 (READ_DONE) break loop
|
// if index == -1 (READ_DONE) break loop
|
||||||
@@ -502,7 +496,7 @@ open class SerializerIrGenerator(
|
|||||||
+irIfThenElse(compilerContext.irBuiltIns.unitType, decodeSequentiallyCall, sequentialPart, byIndexPart)
|
+irIfThenElse(compilerContext.irBuiltIns.unitType, decodeSequentiallyCall, sequentialPart, byIndexPart)
|
||||||
|
|
||||||
//input.endStructure(...)
|
//input.endStructure(...)
|
||||||
val endFunc = inputClass.referenceMethod(CallingConventions.end)
|
val endFunc = inputClass.referenceFunctionSymbol(CallingConventions.end)
|
||||||
+irInvoke(
|
+irInvoke(
|
||||||
localInput.get(),
|
localInput.get(),
|
||||||
endFunc,
|
endFunc,
|
||||||
|
|||||||
+1
-1
@@ -67,4 +67,4 @@ class SerializableCompanionJsTranslator(
|
|||||||
SerializableCompanionJsTranslator(descriptor, translator, context).generate()
|
SerializableCompanionJsTranslator(descriptor, translator, context).generate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+179
-1
@@ -7,17 +7,31 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
|
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.ClassDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.internalName
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
@@ -41,6 +55,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UN
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
@@ -55,6 +70,11 @@ internal val decoderType = Type.getObjectType("kotlinx/serialization/encoding/$D
|
|||||||
internal val kInputType = Type.getObjectType("kotlinx/serialization/encoding/$STRUCTURE_DECODER_CLASS")
|
internal val kInputType = Type.getObjectType("kotlinx/serialization/encoding/$STRUCTURE_DECODER_CLASS")
|
||||||
internal val pluginUtilsType = Type.getObjectType("kotlinx/serialization/internal/${PLUGIN_EXCEPTIONS_FILE}Kt")
|
internal val pluginUtilsType = Type.getObjectType("kotlinx/serialization/internal/${PLUGIN_EXCEPTIONS_FILE}Kt")
|
||||||
|
|
||||||
|
internal val jvmLambdaType = Type.getObjectType("kotlin/jvm/internal/Lambda")
|
||||||
|
internal val kotlinLazyType = Type.getObjectType("kotlin/Lazy")
|
||||||
|
internal val function0Type = Type.getObjectType("kotlin/jvm/functions/Function0")
|
||||||
|
internal val threadSafeModeType = Type.getObjectType("kotlin/LazyThreadSafetyMode")
|
||||||
|
|
||||||
internal val kSerialSaverType = Type.getObjectType("kotlinx/serialization/$SERIAL_SAVER_CLASS")
|
internal val kSerialSaverType = Type.getObjectType("kotlinx/serialization/$SERIAL_SAVER_CLASS")
|
||||||
internal val kSerialLoaderType = Type.getObjectType("kotlinx/serialization/$SERIAL_LOADER_CLASS")
|
internal val kSerialLoaderType = Type.getObjectType("kotlinx/serialization/$SERIAL_LOADER_CLASS")
|
||||||
internal val kSerializerType = Type.getObjectType("kotlinx/serialization/$KSERIALIZER_CLASS")
|
internal val kSerializerType = Type.getObjectType("kotlinx/serialization/$KSERIALIZER_CLASS")
|
||||||
@@ -65,7 +85,7 @@ internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MI
|
|||||||
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
|
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
|
||||||
|
|
||||||
internal val descriptorGetterName = JvmAbi.getterName(SERIAL_DESC_FIELD)
|
internal val descriptorGetterName = JvmAbi.getterName(SERIAL_DESC_FIELD)
|
||||||
|
internal val getLazyValueName = JvmAbi.getterName("value")
|
||||||
|
|
||||||
val OPT_MASK_TYPE: Type = Type.INT_TYPE
|
val OPT_MASK_TYPE: Type = Type.INT_TYPE
|
||||||
val OPT_MASK_BITS = 32
|
val OPT_MASK_BITS = 32
|
||||||
@@ -485,3 +505,161 @@ fun InstructionAdapter.stackValueDefault(type: Type) {
|
|||||||
else -> aconst(null)
|
else -> aconst(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun createSingletonLambda(
|
||||||
|
lambdaName: String,
|
||||||
|
outerClassCodegen: ImplementationBodyCodegen,
|
||||||
|
resultSimpleType: SimpleType,
|
||||||
|
block: InstructionAdapter.(ImplementationBodyCodegen) -> Unit
|
||||||
|
): Type {
|
||||||
|
val lambdaType = Type.getObjectType("${outerClassCodegen.className}\$$lambdaName")
|
||||||
|
|
||||||
|
val lambdaClass = ClassDescriptorImpl(
|
||||||
|
outerClassCodegen.descriptor,
|
||||||
|
Name.identifier(lambdaName),
|
||||||
|
Modality.FINAL,
|
||||||
|
ClassKind.CLASS,
|
||||||
|
listOf(outerClassCodegen.descriptor.module.builtIns.anyType),
|
||||||
|
SourceElement.NO_SOURCE,
|
||||||
|
false,
|
||||||
|
LockBasedStorageManager.NO_LOCKS
|
||||||
|
)
|
||||||
|
lambdaClass.initialize(
|
||||||
|
MemberScope.Empty, emptySet(),
|
||||||
|
DescriptorFactory.createPrimaryConstructorForObject(lambdaClass, lambdaClass.source)
|
||||||
|
)
|
||||||
|
val lambdaClassBuilder = outerClassCodegen.state.factory.newVisitor(
|
||||||
|
JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, null, lambdaClass),
|
||||||
|
Type.getObjectType(lambdaType.internalName),
|
||||||
|
outerClassCodegen.myClass.containingKtFile
|
||||||
|
)
|
||||||
|
val classContextForCreator = ClassContext(
|
||||||
|
outerClassCodegen.typeMapper, lambdaClass, OwnerKind.IMPLEMENTATION, outerClassCodegen.context.parentContext, null
|
||||||
|
)
|
||||||
|
val lambdaCodegen = ImplementationBodyCodegen(
|
||||||
|
outerClassCodegen.myClass,
|
||||||
|
classContextForCreator,
|
||||||
|
lambdaClassBuilder,
|
||||||
|
outerClassCodegen.state,
|
||||||
|
outerClassCodegen.parentCodegen,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
lambdaCodegen.v.defineClass(
|
||||||
|
null,
|
||||||
|
outerClassCodegen.state.classFileVersion,
|
||||||
|
Opcodes.ACC_FINAL or Opcodes.ACC_SUPER or Opcodes.ACC_SYNTHETIC,
|
||||||
|
lambdaType.internalName,
|
||||||
|
"L${jvmLambdaType.internalName};L${function0Type.internalName}<L${kSerializerType.internalName}<*>;>;",
|
||||||
|
jvmLambdaType.internalName,
|
||||||
|
arrayOf(function0Type.internalName)
|
||||||
|
)
|
||||||
|
|
||||||
|
outerClassCodegen.v.visitInnerClass(
|
||||||
|
lambdaType.internalName,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Opcodes.ACC_FINAL or Opcodes.ACC_SUPER or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_STATIC
|
||||||
|
)
|
||||||
|
lambdaCodegen.v.visitInnerClass(
|
||||||
|
lambdaType.internalName,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Opcodes.ACC_FINAL or Opcodes.ACC_SUPER or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_STATIC
|
||||||
|
)
|
||||||
|
lambdaCodegen.v.visitOuterClass(
|
||||||
|
outerClassCodegen.className,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
lambdaCodegen.v.visitSource(
|
||||||
|
outerClassCodegen.myClass.containingKtFile.name,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
val constr = ClassConstructorDescriptorImpl.createSynthesized(
|
||||||
|
lambdaClass,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
false,
|
||||||
|
lambdaClass.source
|
||||||
|
)
|
||||||
|
constr.initialize(
|
||||||
|
emptyList(),
|
||||||
|
DescriptorVisibilities.PUBLIC
|
||||||
|
)
|
||||||
|
constr.returnType = lambdaClass.defaultType
|
||||||
|
lambdaCodegen.generateMethod(constr) { _, _ ->
|
||||||
|
load(0, lambdaType)
|
||||||
|
iconst(0)
|
||||||
|
invokespecial(jvmLambdaType.internalName, "<init>", "(I)V", false)
|
||||||
|
areturn(Type.VOID_TYPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
lambdaCodegen.v.newField(
|
||||||
|
OtherOrigin(lambdaCodegen.myClass.psiOrParent),
|
||||||
|
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_STATIC or Opcodes.ACC_SYNTHETIC,
|
||||||
|
JvmAbi.INSTANCE_FIELD,
|
||||||
|
lambdaType.descriptor,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
val lambdaClInit = lambdaCodegen.createOrGetClInitCodegen()
|
||||||
|
with(lambdaClInit.v) {
|
||||||
|
anew(lambdaType)
|
||||||
|
dup()
|
||||||
|
invokespecial(lambdaType.internalName, "<init>", "()V", false)
|
||||||
|
putstatic(lambdaType.internalName, JvmAbi.INSTANCE_FIELD, lambdaType.descriptor)
|
||||||
|
areturn(Type.VOID_TYPE)
|
||||||
|
visitEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
val invokeFunction = SimpleFunctionDescriptorImpl.create(
|
||||||
|
lambdaCodegen.descriptor,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Name.identifier("invoke"),
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
lambdaCodegen.descriptor.source
|
||||||
|
)
|
||||||
|
|
||||||
|
invokeFunction.initialize(
|
||||||
|
null,
|
||||||
|
lambdaCodegen.descriptor.thisAsReceiverParameter,
|
||||||
|
emptyList(),
|
||||||
|
emptyList(),
|
||||||
|
resultSimpleType,
|
||||||
|
Modality.FINAL,
|
||||||
|
DescriptorVisibilities.PUBLIC
|
||||||
|
)
|
||||||
|
|
||||||
|
lambdaCodegen.generateMethod(invokeFunction) { _, _ ->
|
||||||
|
block(lambdaCodegen)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bridgeInvokeFunction = SimpleFunctionDescriptorImpl.create(
|
||||||
|
lambdaCodegen.descriptor,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Name.identifier("invoke"),
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
lambdaCodegen.descriptor.source
|
||||||
|
)
|
||||||
|
|
||||||
|
bridgeInvokeFunction.initialize(
|
||||||
|
null,
|
||||||
|
lambdaCodegen.descriptor.thisAsReceiverParameter,
|
||||||
|
emptyList(),
|
||||||
|
emptyList(),
|
||||||
|
lambdaCodegen.descriptor.builtIns.anyType,
|
||||||
|
Modality.FINAL,
|
||||||
|
DescriptorVisibilities.PUBLIC
|
||||||
|
)
|
||||||
|
|
||||||
|
lambdaCodegen.generateMethod(bridgeInvokeFunction) { _, _ ->
|
||||||
|
load(0, lambdaType)
|
||||||
|
invokevirtual(lambdaType.internalName, "invoke", "()L${resultSimpleType.toClassDescriptor.classId!!.internalName};", false)
|
||||||
|
areturn(kSerializerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSyntheticClassMetadata(lambdaClassBuilder, lambdaCodegen.state)
|
||||||
|
lambdaClassBuilder.done()
|
||||||
|
|
||||||
|
return lambdaType
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -35,8 +35,8 @@ import org.jetbrains.kotlinx.serialization.compiler.diagnostic.VersionReader
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
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.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.SINGLE_MASK_FIELD_MISSING_FUNC_NAME
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SINGLE_MASK_FIELD_MISSING_FUNC_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.initializedDescriptorFieldName
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -347,14 +347,14 @@ class SerializableCodegenImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InstructionAdapter.stackSerialDescriptor() {
|
private fun InstructionAdapter.stackSerialDescriptor() {
|
||||||
if (serializableDescriptor.shouldHaveGeneratedSerializer && staticDescriptor) {
|
if (serializableDescriptor.isStaticSerializable) {
|
||||||
val serializer = serializableDescriptor.classSerializer!!
|
val serializer = serializableDescriptor.classSerializer!!
|
||||||
StackValue.singleton(serializer, classCodegen.typeMapper).put(kSerializerType, this)
|
StackValue.singleton(serializer, classCodegen.typeMapper).put(kSerializerType, this)
|
||||||
invokeinterface(kSerializerType.internalName, descriptorGetterName, "()${descType.descriptor}")
|
invokeinterface(kSerializerType.internalName, descriptorGetterName, "()${descType.descriptor}")
|
||||||
} else {
|
} else {
|
||||||
generateStaticDescriptorField()
|
generateStaticDescriptorField()
|
||||||
|
|
||||||
getstatic(thisAsmType.internalName, initializedDescriptorFieldName, descType.descriptor)
|
getstatic(thisAsmType.internalName, INITIALIZED_DESCRIPTOR_FIELD_NAME, 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
|
val flags = Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_STATIC
|
||||||
classCodegen.v.newField(
|
classCodegen.v.newField(
|
||||||
OtherOrigin(classCodegen.myClass.psiOrParent), flags,
|
OtherOrigin(classCodegen.myClass.psiOrParent), flags,
|
||||||
initializedDescriptorFieldName, descType.descriptor, null, null
|
INITIALIZED_DESCRIPTOR_FIELD_NAME, descType.descriptor, null, null
|
||||||
)
|
)
|
||||||
|
|
||||||
val clInit = classCodegen.createOrGetClInitCodegen()
|
val clInit = classCodegen.createOrGetClInitCodegen()
|
||||||
@@ -380,7 +380,7 @@ class SerializableCodegenImpl(
|
|||||||
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false)
|
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
putstatic(thisAsmType.internalName, initializedDescriptorFieldName, descType.descriptor)
|
putstatic(thisAsmType.internalName, INITIALIZED_DESCRIPTOR_FIELD_NAME, descType.descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+61
-1
@@ -18,12 +18,17 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
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.SerializableCompanionCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
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.getKSerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.shouldHaveGeneratedMethodsInCompanion
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.shouldHaveGeneratedMethodsInCompanion
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.toSimpleType
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.toSimpleType
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationBodyCodegen) :
|
class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationBodyCodegen) :
|
||||||
SerializableCompanionCodegen(classCodegen.descriptor, classCodegen.bindingContext) {
|
SerializableCompanionCodegen(classCodegen.descriptor, classCodegen.bindingContext) {
|
||||||
@@ -36,6 +41,61 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
|
// 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,
|
||||||
|
kotlinLazyType.descriptor,
|
||||||
|
"L${kotlinLazyType.internalName}<L${kSerializerType.internalName}<*>;>;",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
// create singleton lambda class
|
||||||
|
val lambdaType =
|
||||||
|
createSingletonLambda("serializer\$1", classCodegen, companionDescriptor.getKSerializer().defaultType) { lambdaCodegen ->
|
||||||
|
val serializerDescriptor = requireNotNull(
|
||||||
|
findTypeSerializer(
|
||||||
|
serializableDescriptor.module,
|
||||||
|
serializableDescriptor.toSimpleType()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
stackValueSerializerInstance(
|
||||||
|
lambdaCodegen,
|
||||||
|
serializableDescriptor.module,
|
||||||
|
serializableDescriptor.defaultType,
|
||||||
|
serializerDescriptor,
|
||||||
|
this,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
areturn(kSerializerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize lazy delegate
|
||||||
|
val clInit = classCodegen.createOrGetClInitCodegen()
|
||||||
|
with(clInit.v) {
|
||||||
|
getstatic(threadSafeModeType.internalName, "PUBLICATION", threadSafeModeType.descriptor)
|
||||||
|
getstatic(lambdaType.internalName, JvmAbi.INSTANCE_FIELD, lambdaType.descriptor)
|
||||||
|
checkcast(function0Type)
|
||||||
|
invokestatic(
|
||||||
|
"kotlin/LazyKt",
|
||||||
|
"lazy",
|
||||||
|
"(${threadSafeModeType.descriptor}${function0Type.descriptor})${kotlinLazyType.descriptor}",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
putstatic(classCodegen.className, SERIALIZER_LAZY_DELEGATE_FIELD_NAME, kotlinLazyType.descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create serializer getter
|
||||||
|
classCodegen.generateMethod(methodDescriptor) { _, _ ->
|
||||||
|
getstatic(classCodegen.className, SERIALIZER_LAZY_DELEGATE_FIELD_NAME, kotlinLazyType.descriptor)
|
||||||
|
invokeinterface(kotlinLazyType.internalName, getLazyValueName, "()Ljava/lang/Object;")
|
||||||
|
checkcast(kSerializerType)
|
||||||
|
areturn(kSerializerType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||||
val serial = requireNotNull(
|
val serial = requireNotNull(
|
||||||
findTypeSerializer(
|
findTypeSerializer(
|
||||||
@@ -57,4 +117,4 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
areturn(kSerializerType)
|
areturn(kSerializerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -44,7 +44,8 @@ object SerialEntityNames {
|
|||||||
const val LOAD = "deserialize"
|
const val LOAD = "deserialize"
|
||||||
const val SERIALIZER_CLASS = "\$serializer"
|
const val SERIALIZER_CLASS = "\$serializer"
|
||||||
|
|
||||||
const val initializedDescriptorFieldName = "\$initializedDescriptor"
|
const val INITIALIZED_DESCRIPTOR_FIELD_NAME = "\$initializedDescriptor"
|
||||||
|
const val SERIALIZER_LAZY_DELEGATE_FIELD_NAME = "\$serializer\$delegate"
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
val KSERIALIZER_NAME = Name.identifier(KSERIALIZER_CLASS)
|
val KSERIALIZER_NAME = Name.identifier(KSERIALIZER_CLASS)
|
||||||
|
|||||||
+8
@@ -69,6 +69,14 @@ internal fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor
|
|||||||
)
|
)
|
||||||
)!!
|
)!!
|
||||||
|
|
||||||
|
internal fun ClassDescriptor.getKSerializer(): ClassDescriptor =
|
||||||
|
module.findClassAcrossModuleDependencies(
|
||||||
|
ClassId(
|
||||||
|
SerializationPackages.packageFqName,
|
||||||
|
SerialEntityNames.KSERIALIZER_NAME
|
||||||
|
)
|
||||||
|
)!!
|
||||||
|
|
||||||
internal fun getInternalPackageFqn(classSimpleName: String): FqName =
|
internal fun getInternalPackageFqn(classSimpleName: String): FqName =
|
||||||
SerializationPackages.internalPackageFqName.child(Name.identifier(classSimpleName))
|
SerializationPackages.internalPackageFqName.child(Name.identifier(classSimpleName))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user