Implemented caching of child serializers

Resolves Kotlin/kotlinx.serialization#1918

Merge-request: KT-MR-7578
Merged-by: Sergey Shanshin <Sergey.Shanshin@jetbrains.com>
This commit is contained in:
Sergey.Shanshin
2022-11-23 19:53:44 +00:00
committed by Space Team
parent 3e8f7b8ee4
commit 339b152390
11 changed files with 408 additions and 204 deletions
@@ -5,17 +5,14 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.jvm.functionByName
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.deepCopyWithVariables
import org.jetbrains.kotlin.ir.expressions.IrClassReference
import org.jetbrains.kotlin.ir.expressions.IrExpression
@@ -29,13 +26,12 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_NAME_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.contextSerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.objectSerializerId
@@ -178,6 +174,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
kOutputClass: IrClassSymbol,
ignoreIndexTo: Int,
initializerAdapter: (IrExpressionBody) -> IrExpression,
cachedChildSerializerByIndex: (Int) -> IrExpression?,
genericGetter: ((Int, IrType) -> IrExpression)?
) {
@@ -212,6 +209,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
f to args
},
cachedChildSerializerByIndex(index),
genericGetter
)
@@ -249,11 +247,12 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
property: IrSerializableProperty,
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
cachedSerializer: IrExpression?,
genericGetter: ((Int, IrType) -> IrExpression)? = null,
returnTypeHint: IrType? = null
): IrExpression {
val sti = getIrSerialTypeInfo(property, compilerContext)
val innerSerial = serializerInstance(
val innerSerial = cachedSerializer ?: serializerInstance(
sti.serializer,
compilerContext,
property.type,
@@ -305,24 +304,33 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
fun IrBuilderWithScope.serializerTower(
generator: SerializerIrGenerator,
dispatchReceiverParameter: IrValueParameter,
property: IrSerializableProperty
property: IrSerializableProperty,
cachedSerializer: IrExpression?
): IrExpression? {
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableCallableId).single()
val serializer =
property.serializableWith(compilerContext)
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
compilerContext,
property.type
) else null
return serializerInstance(
serializer,
compilerContext,
property.type,
genericIndex = property.genericIndex
) { it, _ ->
val ir = generator.localSerializersFieldsDescriptors[it]
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
}?.let { expr -> wrapWithNullableSerializerIfNeeded(property.type, expr, nullableSerClass) }
val serializerExpression = if (cachedSerializer != null) {
cachedSerializer
} else {
val serializerClassSymbol =
property.serializableWith(compilerContext)
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
compilerContext,
property.type
) else null
serializerInstance(
serializerClassSymbol,
compilerContext,
property.type,
genericIndex = property.genericIndex
) { it, _ ->
val ir = generator.localSerializersFieldsDescriptors[it]
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
}
}
return serializerExpression?.let { expr -> wrapWithNullableSerializerIfNeeded(property.type, expr, nullableSerClass) }
}
private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(
@@ -359,6 +367,66 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
)
}
internal fun IrClass.addCachedChildSerializersProperty(cacheableSerializers: List<IrExpression?>): IrProperty? {
// if all child serializers are null (non-cacheable) we don't need to create a property
cacheableSerializers.firstOrNull { it != null } ?: return null
val kSerializerClass = compilerContext.kSerializerClass
?: throw AssertionError("Serializer class '$KSERIALIZER_NAME_FQ' not found. Check that the kotlinx.serialization runtime is connected correctly")
val kSerializerType = kSerializerClass.typeWith(compilerContext.irBuiltIns.anyType)
val arrayType = compilerContext.irBuiltIns.arrayClass.typeWith(kSerializerType)
return addValPropertyWithJvmField(arrayType, SerialEntityNames.CACHED_CHILD_SERIALIZERS_PROPERTY_NAME) {
+createArrayOfExpression(kSerializerType, cacheableSerializers.map { it ?: irNull() })
}
}
/**
* Factory to getting cached serializers via variable.
* Must be used only in one place because for each factory creates one variable.
*
* Class from [containingClassProducer] used only if [cacheProperty] is not null.
*/
internal fun IrStatementsBuilder<*>.createCacheableChildSerializersFactory(
cacheProperty: IrProperty?,
cacheableSerializers: List<Boolean>,
containingClassProducer: () -> IrClass
): (Int) -> IrExpression? {
cacheProperty ?: return { null }
val variable =
irTemporary(irInvoke(irGetObject(containingClassProducer()), cacheProperty.getter!!.symbol), "cached")
return { index: Int ->
if (cacheableSerializers[index]) {
irInvoke(irGet(variable), compilerContext.arrayValueGetter.symbol, irInt(index))
} else {
null
}
}
}
fun IrClass.createCachedChildSerializers(
serializableProperties: List<IrSerializableProperty>
): List<IrExpression?> {
return DeclarationIrBuilder(compilerContext, symbol).run {
serializableProperties.map { cacheableChildSerializerInstance(it) }
}
}
private fun IrBuilderWithScope.cacheableChildSerializerInstance(property: IrSerializableProperty): IrExpression? {
val serializer = getIrSerialTypeInfo(property, compilerContext).serializer ?: return null
if (serializer.owner.kind == ClassKind.OBJECT) return null
return serializerInstance(
serializer,
compilerContext,
property.type,
null,
null
)
}
fun IrBuilderWithScope.serializerInstance(
serializerClassOriginal: IrClassSymbol?,
pluginContext: SerializationPluginContext,
@@ -5,11 +5,9 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.*
@@ -23,17 +21,11 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.synthetic.syntheticVisibility
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_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 IrBuilderWithPluginContext {
@@ -61,8 +53,10 @@ interface IrBuilderWithPluginContext {
visibility = DescriptorVisibilities.LOCAL
origin = SERIALIZATION_PLUGIN_ORIGIN
}
function.body =
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
function.body = DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset) {
val expr = addAndGetLastExpression(bodyGen)
+irReturn(expr)
}
function.parent = this
val f0Type = compilerContext.irBuiltIns.functionN(0)
@@ -78,78 +72,105 @@ interface IrBuilderWithPluginContext {
)
}
fun createLazyProperty(
fun addLazyValProperty(
containingClass: IrClass,
targetIrType: IrType,
name: Name,
propertyName: Name,
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE,
initializerBuilder: IrBlockBodyBuilder.() -> Unit
): IrProperty {
val lazySafeModeClassDescriptor = compilerContext.referenceClass(ClassId.topLevel(LAZY_MODE_FQ))!!.owner
val lazyFunctionSymbol = compilerContext.referenceFunctions(CallableId(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, Name.identifier("lazy"))).single {
it.owner.valueParameters.size == 2 && it.owner.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
val lazyIrType =
compilerContext.lazyClass.defaultType.substitute(mapOf(compilerContext.lazyClass.typeParameters[0].symbol to targetIrType))
val field = containingClass.factory.buildField {
startOffset = containingClass.startOffset
endOffset = containingClass.endOffset
name = Name.identifier(propertyName.asString() + "\$delegate")
type = lazyIrType
origin = SERIALIZATION_PLUGIN_ORIGIN
isFinal = true
this.visibility = DescriptorVisibilities.PRIVATE
}.also { it.parent = containingClass }
containingClass.addAnonymousInit {
val enumElement = IrGetEnumValueImpl(
startOffset,
endOffset,
compilerContext.lazyModeClass.defaultType,
compilerContext.lazyModePublicationEnumEntry.symbol
)
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
val invokeLazyExpr =
irInvoke(null, compilerContext.lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), lazyIrType)
+irSetField(irGet(containingClass.thisReceiver!!), field, invokeLazyExpr)
}
val publicationEntryDescriptor = lazySafeModeClassDescriptor.enumEntries().single { it.name == LAZY_PUBLICATION_MODE_NAME }
val lazyIrClass = compilerContext.referenceClass(ClassId.topLevel(LAZY_FQ))!!.owner
val lazyIrType = lazyIrClass.defaultType.substitute(mapOf(lazyIrClass.typeParameters[0].symbol to targetIrType))
return generateSimplePropertyWithBackingField(Name.identifier(name.asString() + "\$delegate"), lazyIrType, containingClass).apply {
val builder = DeclarationIrBuilder(compilerContext, containingClass.symbol, startOffset, endOffset)
val initializerBody = builder.run {
val enumElement = IrGetEnumValueImpl(
startOffset,
endOffset,
lazySafeModeClassDescriptor.defaultType,
publicationEntryDescriptor.symbol
)
val prop = containingClass.addProperty {
startOffset = containingClass.startOffset
endOffset = containingClass.endOffset
name = propertyName
this.visibility = visibility
this.isVar = false
origin = SERIALIZATION_PLUGIN_ORIGIN
}.apply {
field.correspondingPropertySymbol = this.symbol
backingField = field
}
val lambdaExpression = containingClass.createLambdaExpression(targetIrType, initializerBuilder)
val getter = prop.addGetter {
startOffset = containingClass.startOffset
endOffset = containingClass.endOffset
returnType = targetIrType
origin = SERIALIZATION_PLUGIN_ORIGIN
this.visibility = visibility
modality = Modality.FINAL
}
irExprBody(
irInvoke(null, lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), lazyIrType)
getter.apply {
dispatchReceiverParameter = containingClass.thisReceiver!!.copyTo(this, type = containingClass.defaultType)
body = compilerContext.irBuiltIns.createIrBuilder(symbol, containingClass.startOffset, containingClass.endOffset).irBlockBody {
+irReturn(
irInvoke(
irGetField(irGet(dispatchReceiverParameter!!), field),
compilerContext.lazyValueGetter,
typeHint = targetIrType
)
)
}
backingField!!.initializer = initializerBody
}
return prop
}
fun createCompanionValProperty(
companionClass: IrClass,
fun IrClass.addValPropertyWithJvmField(
type: IrType,
name: Name,
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE,
initializerBuilder: IrBlockBodyBuilder.() -> Unit
): IrProperty {
return generateSimplePropertyWithBackingField(name, type, companionClass).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)
return generateSimplePropertyWithBackingField(name, type, this, visibility).apply {
val field = backingField!!
addAnonymousInit {
val resultExpression = addAndGetLastExpression(initializerBuilder)
+irSetField(irGet(thisReceiver!!), field, resultExpression)
}
val annotationCtor = compilerContext.jvmFieldClassSymbol.constructors.single { it.owner.isPrimary }
val annotationType = compilerContext.jvmFieldClassSymbol.defaultType
field.annotations += IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, annotationType, annotationCtor)
}
}
fun IrClass.contributeAnonymousInitializer(bodyGen: IrBlockBodyBuilder.() -> Unit) {
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
it.parent = this
declarations.add(it)
it.body = DeclarationIrBuilder(compilerContext, symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
}
}
fun IrBlockBodyBuilder.getLazyValueExpression(thisParam: IrValueParameter, property: IrProperty, type: IrType): IrExpression {
val lazyIrClass = compilerContext.referenceClass(ClassId.topLevel(LAZY_FQ))!!.owner
val valueGetter = lazyIrClass.getPropertyGetter("value")!!
val propertyGetter = property.getter!!
return irInvoke(
irGet(propertyGetter.returnType, irGet(thisParam), propertyGetter.symbol),
valueGetter,
typeHint = type
)
/**
* Add all statements to the builder, except the last one.
* The last statement should be an expression, it will return as a result
*/
private fun IrStatementsBuilder<*>.addAndGetLastExpression(blockBuilder: IrBlockBodyBuilder.() -> Unit): IrExpression {
val irBlockBody = irBlockBody(startOffset, endOffset, blockBuilder)
irBlockBody.statements.dropLast(1).forEach { +it }
return irBlockBody.statements.last() as? IrExpression
?: throw AssertionError("Last statement in property initializer builder is not an a expression")
}
fun IrBuilderWithScope.irInvoke(
@@ -207,6 +228,26 @@ interface IrBuilderWithPluginContext {
}
}
fun IrClass.addAnonymousInit(body: IrBlockBodyBuilder.() -> Unit) {
val anonymousInit = this.run {
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
this.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
it.parent = this
declarations.add(it)
}
}
anonymousInit.buildWithScope { initIrBody ->
initIrBody.body =
DeclarationIrBuilder(
compilerContext,
initIrBody.symbol,
initIrBody.startOffset,
initIrBody.endOffset
).irBlockBody(body = body)
}
}
fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression {
val classFqName = (lhs.type as IrSimpleType).classOrNull!!.owner.fqNameWhenAvailable!!
val symbol = compilerContext.referenceFunctions(CallableId(ClassId.topLevel(classFqName), name)).single()
@@ -119,16 +119,16 @@ class SerializableCompanionIrGenerator(
val targetIrType =
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
val property = createLazyProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
val expr = serializerInstance(
serializer, compilerContext, serializableIrClass.defaultType
val property = addLazyValProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
val expr = requireNotNull(
serializerInstance(serializer, compilerContext, serializableIrClass.defaultType)
)
patchSerializableClassWithMarkerAnnotation(kSerializerIrClass)
+irReturn(requireNotNull(expr))
+expr
}
addFunctionBody(methodDescriptor) {
+irReturn(getLazyValueExpression(it.dispatchReceiverParameter!!, property, targetIrType))
+irReturn(irInvoke(irGet(it.dispatchReceiverParameter!!), property.getter!!.symbol))
}
generateSerializerFactoryIfNeeded(methodDescriptor)
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
@@ -56,6 +57,13 @@ class SerializableIrGenerator(
private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableOrMetaAnnotationWithoutArgs()
private val cachedChildSerializers: List<IrExpression?> =
irClass.companionObject()!!.createCachedChildSerializers(properties.serializableProperties)
private val cachedChildSerializersProperty: IrProperty? =
irClass.companionObject()!!.addCachedChildSerializersProperty(cachedChildSerializers)
fun generateInternalConstructor(constructorDescriptor: IrConstructor) =
addFunctionBody(constructorDescriptor) { ctor ->
val thiz = irClass.thisReceiver!!
@@ -200,10 +208,10 @@ class SerializableIrGenerator(
return irGetField(irGetObject(companionObject), property.backingField!!)
}
private fun IrBlockBodyBuilder.createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
private fun createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
val serialDescIrType = serialDescriptorClass.defaultType
return createCompanionValProperty(companionObject, serialDescIrType, CACHED_DESCRIPTOR_FIELD_NAME) {
return companionObject.addValPropertyWithJvmField(serialDescIrType, CACHED_DESCRIPTOR_FIELD_NAME, DescriptorVisibilities.PUBLIC) {
val serialDescVar = irTemporary(
getInstantiateDescriptorExpr(),
nameHint = "serialDesc"
@@ -342,10 +350,15 @@ class SerializableIrGenerator(
}
}
val cachedChildSerializerByIndex = createCacheableChildSerializersFactory(
cachedChildSerializersProperty,
cachedChildSerializers.map { it != null }
) { irClass.companionObject()!! }
serializeAllProperties(
serializableProperties, objectToSerialize,
localOutput, localSerialDesc, kOutputClass,
ignoreIndexTo, initializerAdapter
ignoreIndexTo, initializerAdapter, cachedChildSerializerByIndex,
) { it, _ ->
irGet(writeSelfFunction.valueParameters[3 + it])
}
@@ -53,7 +53,7 @@ class SerializerForInlineClassGenerator(
encoderClass.functionByName("${CallingConventions.encode}${it.elementMethodPrefix}")
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
f to args
})
}, null)
val actualEncodeCall = irIfNull(compilerContext.irBuiltIns.unitType, irGet(inlineEncoder), irNull(), elementCall)
+actualEncodeCall
@@ -77,7 +77,7 @@ class SerializerForInlineClassGenerator(
decoderClass.functionByName( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
}, {
decoderClass.functionByName("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
}, returnTypeHint = inlinedType)
}, null, returnTypeHint = inlinedType)
val value = coerceToBox(actualCall, loadFunc.returnType)
+irReturn(value)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.backend.jvm.functionByName
@@ -24,7 +23,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.ClassId
@@ -34,6 +32,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_CHILD_SERIALIZERS_PROPERTY_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
@@ -60,9 +59,8 @@ open class SerializerIrGenerator(
protected val isGeneratedSerializer = irClass.superTypes.any(IrType::isGeneratedKSerializer)
protected val generatedSerialDescPropertyDescriptor = getProperty(
SerialEntityNames.SERIAL_DESC_FIELD,
{ true }
)?.takeIf { it.isFromPlugin(compilerContext.afterK2) }
SerialEntityNames.SERIAL_DESC_FIELD
) { true }?.takeIf { it.isFromPlugin(compilerContext.afterK2) }
protected val anySerialDescProperty = getProperty(
SerialEntityNames.SERIAL_DESC_FIELD,
@@ -80,6 +78,14 @@ open class SerializerIrGenerator(
var localSerializersFieldsDescriptors: List<IrProperty> = emptyList()
private set
// child serializers cached if serializable class is internal
private val cachedChildSerializersProperty =
serializableIrClass.companionObject()?.properties?.singleOrNull { it.name == CACHED_CHILD_SERIALIZERS_PROPERTY_NAME }
// non-object serializers which can be cached
private val cacheableChildSerializers =
serializableIrClass.createCachedChildSerializers(properties.serializableProperties).map { it != null }
// null if was not found — we're in FIR
private fun findLocalSerializersFieldDescriptors(): List<IrProperty?> {
val count = serializableIrClass.typeParameters.size
@@ -112,42 +118,29 @@ open class SerializerIrGenerator(
}
}
val anonymousInit = irClass.run {
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
irClass.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
it.parent = this
declarations.add(it)
}
}
irClass.addAnonymousInit {
val localDesc = irTemporary(
instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)),
nameHint = "serialDesc"
)
anonymousInit.buildWithScope { initIrBody ->
compilerContext.symbolTable.withReferenceScope(initIrBody) {
initIrBody.body =
DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody {
val localDesc = irTemporary(
instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)),
nameHint = "serialDesc"
)
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
// add class annotations
copySerialInfoAnnotationsToDescriptor(
collectSerialInfoAnnotations(serializableIrClass),
localDesc,
serialDescImplClass.functionByName(CallingConventions.addClassAnnotation)
)
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
// add class annotations
copySerialInfoAnnotationsToDescriptor(
collectSerialInfoAnnotations(serializableIrClass),
localDesc,
serialDescImplClass.functionByName(CallingConventions.addClassAnnotation)
)
// save local descriptor to field
+irSetField(
IrGetValueImpl(
startOffset, endOffset,
thisAsReceiverParameter.symbol
),
prop.backingField!!,
irGet(localDesc)
)
}
}
// save local descriptor to field
+irSetField(
IrGetValueImpl(
startOffset, endOffset,
thisAsReceiverParameter.symbol
),
prop.backingField!!,
irGet(localDesc)
)
}
}
@@ -225,10 +218,15 @@ open class SerializerIrGenerator(
}
open fun generateChildSerializersGetter(function: IrSimpleFunction) = addFunctionBody(function) { irFun ->
val allSerializers = serializableProperties.map {
val cachedChildSerializerByIndex = createCacheableChildSerializersFactory(
cachedChildSerializersProperty,
cacheableChildSerializers
) { serializableIrClass.companionObject()!! }
val allSerializers = serializableProperties.mapIndexed { index, property ->
requireNotNull(
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)
) { "Property ${it.name} must have a serializer" }
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, property, cachedChildSerializerByIndex(index))
) { "Property ${property.name} must have a serializer" }
}
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
@@ -294,9 +292,14 @@ open class SerializerIrGenerator(
val initializerAdapter: (IrExpressionBody) -> IrExpression =
createInitializerAdapter(serializableIrClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) })
val cachedChildSerializerByIndex =
createCacheableChildSerializersFactory(cachedChildSerializersProperty, cacheableChildSerializers) {
serializableIrClass.companionObject()!!
}
serializeAllProperties(
serializableProperties, objectToSerialize, localOutput,
localSerialDesc, kOutputClass, ignoreIndexTo = -1, initializerAdapter
localSerialDesc, kOutputClass, ignoreIndexTo = -1, initializerAdapter, cachedChildSerializerByIndex
) { it, _ ->
val ir = localSerializersFieldsDescriptors[it]
irGetField(irGet(saveFunc.dispatchReceiverParameter!!), ir.backingField!!)
@@ -314,12 +317,14 @@ open class SerializerIrGenerator(
property: IrSerializableProperty,
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
cachedSerializer: IrExpression?,
returnTypeHint: IrType? = null
): IrExpression = formEncodeDecodePropertyCall(
encoder,
property,
whenHaveSerializer,
whenDoNot,
cachedSerializer,
{ it, _ ->
val ir = localSerializersFieldsDescriptors[it]
irGetField(irGet(dispatchReceiver), ir.backingField!!)
@@ -405,6 +410,11 @@ open class SerializerIrGenerator(
)
val localInput = irTemporary(call, "input")
val cachedChildSerializerByIndex = createCacheableChildSerializersFactory(
cachedChildSerializersProperty,
cacheableChildSerializers
) { serializableIrClass.companionObject()!! }
// prepare all .decodeXxxElement calls
val decoderCalls: List<Pair<Int, IrExpression>> =
serializableProperties.mapIndexed { index, property ->
@@ -422,7 +432,7 @@ open class SerializerIrGenerator(
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}" &&
it.owner.valueParameters.size == 2
} to listOf(localSerialDesc.get(), irInt(index))
}, returnTypeHint = property.type)
}, cachedChildSerializerByIndex(index), returnTypeHint = property.type)
// local$i = localInput.decode...(...)
+irSet(
serialPropertiesMap.getValue(property.ir).symbol,
@@ -11,25 +11,30 @@ import org.jetbrains.kotlin.backend.common.CompilationException
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.*
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializationJvmIrIntrinsicSupport
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
import java.util.concurrent.ConcurrentHashMap
@@ -55,6 +60,24 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
internal val copiedStaticWriteSelf: MutableMap<IrSimpleFunction, IrSimpleFunction> = ConcurrentHashMap()
// Kotlin built-in declarations
internal val arrayValueGetter = irBuiltIns.arrayClass.owner.declarations.filterIsInstance<IrSimpleFunction>()
.single { it.name.asString() == "get" }
// Kotlin stdlib declarations
internal val jvmFieldClassSymbol = referenceClass(StandardClassIds.Annotations.JvmField)!!
internal val lazyModeClass = referenceClass(ClassId.topLevel(SerializationDependencies.LAZY_MODE_FQ))!!.owner
internal val lazyModePublicationEnumEntry =
lazyModeClass.enumEntries().single { it.name == SerializationDependencies.LAZY_PUBLICATION_MODE_NAME }
internal val lazyFunctionSymbol =
referenceFunctions(CallableId(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, Name.identifier("lazy"))).single {
it.owner.valueParameters.size == 2 && it.owner.valueParameters[0].type == lazyModeClass.defaultType
}
internal val lazyClass = referenceClass(ClassId.topLevel(SerializationDependencies.LAZY_FQ))!!.owner
internal val lazyValueGetter = lazyClass.getPropertyGetter("value")!!
// serialization runtime declarations
internal val enumSerializerFactoryFunc = baseContext.referenceFunctions(
CallableId(
SerializationPackages.internalPackageFqName,
@@ -69,6 +92,12 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
)
).singleOrNull()
/**
* @return `null` if there is no serialization runtime in the classpath
*/
internal val kSerializerClass = referenceClass(SerialEntityNames.KSERIALIZER_CLASS_ID)?.owner
// evaluated properties
override val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null
override fun referenceClassId(classId: ClassId): IrClassSymbol? = referenceClass(classId)
@@ -68,6 +68,7 @@ object SerialEntityNames {
const val CACHED_DESCRIPTOR_FIELD = "\$cachedDescriptor"
const val CACHED_SERIALIZER_PROPERTY = "\$cachedSerializer"
const val CACHED_CHILD_SERIALIZERS_PROPERTY = "\$childSerializers"
// classes
val KCLASS_NAME_FQ = FqName("kotlin.reflect.KClass")
@@ -123,6 +124,7 @@ object SerialEntityNames {
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_CHILD_SERIALIZERS_PROPERTY_NAME = Name.identifier(CACHED_CHILD_SERIALIZERS_PROPERTY)
val CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
val ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ENUM_SERIALIZER_FACTORY_FUNC_NAME)
@@ -41,19 +41,18 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
public kotlinx.serialization.KSerializer[] childSerializers() {
LABEL (L0)
LINENUMBER (12)
INVOKESTATIC (ListOfUsers, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
ASTORE (1)
ICONST_1
ANEWARRAY (kotlinx/serialization/KSerializer)
ASTORE (1)
ASTORE (2)
ALOAD (2)
ICONST_0
ALOAD (1)
ICONST_0
NEW (kotlinx/serialization/internal/ArrayListSerializer)
DUP
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
CHECKCAST (kotlinx/serialization/KSerializer)
AALOAD
AASTORE
ALOAD (1)
ALOAD (2)
ARETURN
LABEL (L1)
}
@@ -78,17 +77,17 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
ALOAD (2)
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
ASTORE (7)
INVOKESTATIC (ListOfUsers, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
ASTORE (8)
ALOAD (7)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
IFEQ (L2)
ALOAD (7)
ALOAD (2)
ICONST_0
NEW (kotlinx/serialization/internal/ArrayListSerializer)
DUP
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
ALOAD (8)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
ALOAD (6)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
@@ -118,11 +117,9 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
ALOAD (7)
ALOAD (2)
ICONST_0
NEW (kotlinx/serialization/internal/ArrayListSerializer)
DUP
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
ALOAD (8)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
ALOAD (6)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
@@ -237,6 +234,8 @@ public final class ListOfUsers$Companion : java/lang/Object {
}
public final class ListOfUsers : java/lang/Object {
private final static kotlinx.serialization.KSerializer[] $childSerializers
public final static ListOfUsers$Companion Companion
private final java.util.List list
@@ -247,6 +246,24 @@ public final class ListOfUsers : java/lang/Object {
ACONST_NULL
INVOKESPECIAL (ListOfUsers$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
PUTSTATIC (ListOfUsers, Companion, LListOfUsers$Companion;)
LABEL (L0)
LINENUMBER (12)
ICONST_1
ANEWARRAY (kotlinx/serialization/KSerializer)
ASTORE (0)
ALOAD (0)
ICONST_0
NEW (kotlinx/serialization/internal/ArrayListSerializer)
DUP
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
CHECKCAST (kotlinx/serialization/KSerializer)
AASTORE
ALOAD (0)
PUTSTATIC (ListOfUsers, $childSerializers, [Lkotlinx/serialization/KSerializer;)
LABEL (L1)
LINENUMBER (13)
RETURN
}
@@ -291,19 +308,21 @@ public final class ListOfUsers : java/lang/Object {
LABEL (L2)
}
public final static kotlinx.serialization.KSerializer[] access$get$childSerializers$cp()
public final java.util.List getList()
public final static void write$Self(ListOfUsers self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
LABEL (L0)
LINENUMBER (12)
GETSTATIC (ListOfUsers, $childSerializers, [Lkotlinx/serialization/KSerializer;)
ASTORE (3)
ALOAD (1)
ALOAD (2)
ICONST_0
NEW (kotlinx/serialization/internal/ArrayListSerializer)
DUP
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
ALOAD (3)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/SerializationStrategy)
ALOAD (0)
GETFIELD (ListOfUsers, list, Ljava/util/List;)
@@ -29,8 +29,6 @@ public final class Box$Companion : java/lang/Object {
public void <init>(kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker)
private final kotlinx.serialization.descriptors.SerialDescriptor get$cachedDescriptor()
public final kotlinx.serialization.KSerializer serializer(kotlinx.serialization.KSerializer typeSerial0)
}
@@ -47,8 +45,6 @@ public final class Box : java/lang/Object {
public void <init>(int seen1, java.lang.Object boxed, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker)
public final static kotlinx.serialization.descriptors.SerialDescriptor access$get$cachedDescriptor$cp()
public final java.lang.Object component1()
public final Box copy(java.lang.Object boxed)
@@ -191,8 +187,8 @@ public final class IntrinsicsKt : java/lang/Object {
}
}
final class SerializableObject$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static SerializableObject$$cachedSerializer$delegate$1 INSTANCE
final class SerializableObject$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static SerializableObject$1 INSTANCE
static void <clinit>()
@@ -212,7 +208,7 @@ public final class SerializableObject : java/lang/Object {
private void <init>()
private final kotlin.Lazy get$cachedSerializer$delegate()
private final kotlinx.serialization.KSerializer get$cachedSerializer()
public final kotlinx.serialization.KSerializer serializer()
}
@@ -41,15 +41,18 @@ public final class Container$$serializer : java/lang/Object, kotlinx/serializati
public kotlinx.serialization.KSerializer[] childSerializers() {
LABEL (L0)
LINENUMBER (18)
INVOKESTATIC (Container, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
ASTORE (1)
ICONST_1
ANEWARRAY (kotlinx/serialization/KSerializer)
ASTORE (1)
ASTORE (2)
ALOAD (2)
ICONST_0
ALOAD (1)
ICONST_0
GETSTATIC (Result, Companion, LResult$Companion;)
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
AALOAD
AASTORE
ALOAD (1)
ALOAD (2)
ARETURN
LABEL (L1)
}
@@ -74,14 +77,17 @@ public final class Container$$serializer : java/lang/Object, kotlinx/serializati
ALOAD (2)
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
ASTORE (7)
INVOKESTATIC (Container, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
ASTORE (8)
ALOAD (7)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
IFEQ (L2)
ALOAD (7)
ALOAD (2)
ICONST_0
GETSTATIC (Result, Companion, LResult$Companion;)
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
ALOAD (8)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
ALOAD (6)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
@@ -111,8 +117,9 @@ public final class Container$$serializer : java/lang/Object, kotlinx/serializati
ALOAD (7)
ALOAD (2)
ICONST_0
GETSTATIC (Result, Companion, LResult$Companion;)
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
ALOAD (8)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
ALOAD (6)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
@@ -191,6 +198,8 @@ public final class Container$Companion : java/lang/Object {
}
public final class Container : java/lang/Object {
private final static kotlinx.serialization.KSerializer[] $childSerializers
public final static Container$Companion Companion
private final Result r
@@ -201,6 +210,20 @@ public final class Container : java/lang/Object {
ACONST_NULL
INVOKESPECIAL (Container$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
PUTSTATIC (Container, Companion, LContainer$Companion;)
LABEL (L0)
LINENUMBER (18)
ICONST_1
ANEWARRAY (kotlinx/serialization/KSerializer)
ASTORE (0)
ALOAD (0)
ICONST_0
GETSTATIC (Result, Companion, LResult$Companion;)
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
AASTORE
ALOAD (0)
PUTSTATIC (Container, $childSerializers, [Lkotlinx/serialization/KSerializer;)
LABEL (L1)
LINENUMBER (19)
RETURN
}
@@ -245,16 +268,21 @@ public final class Container : java/lang/Object {
LABEL (L2)
}
public final static kotlinx.serialization.KSerializer[] access$get$childSerializers$cp()
public final Result getR()
public final static void write$Self(Container self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
LABEL (L0)
LINENUMBER (18)
GETSTATIC (Container, $childSerializers, [Lkotlinx/serialization/KSerializer;)
ASTORE (3)
ALOAD (1)
ALOAD (2)
ICONST_0
GETSTATIC (Result, Companion, LResult$Companion;)
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
ALOAD (3)
ICONST_0
AALOAD
CHECKCAST (kotlinx/serialization/SerializationStrategy)
ALOAD (0)
GETFIELD (Container, r, LResult;)
@@ -264,14 +292,14 @@ public final class Container : java/lang/Object {
}
}
final class Result$Companion$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static Result$Companion$$cachedSerializer$delegate$1 INSTANCE
final class Result$Companion$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static Result$Companion$1 INSTANCE
static void <clinit>() {
NEW (Result$Companion$$cachedSerializer$delegate$1)
NEW (Result$Companion$1)
DUP
INVOKESPECIAL (Result$Companion$$cachedSerializer$delegate$1, <init>, ()V)
PUTSTATIC (Result$Companion$$cachedSerializer$delegate$1, INSTANCE, LResult$Companion$$cachedSerializer$delegate$1;)
INVOKESPECIAL (Result$Companion$1, <init>, ()V)
PUTSTATIC (Result$Companion$1, INSTANCE, LResult$Companion$1;)
RETURN
}
@@ -338,7 +366,7 @@ final class Result$Companion$$cachedSerializer$delegate$1 : kotlin/jvm/internal/
LABEL (L0)
LINENUMBER (12)
ALOAD (0)
INVOKEVIRTUAL (Result$Companion$$cachedSerializer$delegate$1, invoke, ()Lkotlinx/serialization/KSerializer;)
INVOKEVIRTUAL (Result$Companion$1, invoke, ()Lkotlinx/serialization/KSerializer;)
ARETURN
LABEL (L1)
}
@@ -362,28 +390,26 @@ public final class Result$Companion : java/lang/Object {
LABEL (L1)
}
private final kotlin.Lazy get$cachedSerializer$delegate()
private final kotlinx.serialization.KSerializer get$cachedSerializer()
public final kotlinx.serialization.KSerializer serializer() {
LABEL (L0)
LINENUMBER (12)
ALOAD (0)
INVOKESPECIAL (Result$Companion, get$cachedSerializer$delegate, ()Lkotlin/Lazy;)
INVOKEINTERFACE (kotlin/Lazy, getValue, ()Ljava/lang/Object;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (Result$Companion, get$cachedSerializer, ()Lkotlinx/serialization/KSerializer;)
ARETURN
LABEL (L1)
}
}
final class Result$Err$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static Result$Err$$cachedSerializer$delegate$1 INSTANCE
final class Result$Err$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
public final static Result$Err$1 INSTANCE
static void <clinit>() {
NEW (Result$Err$$cachedSerializer$delegate$1)
NEW (Result$Err$1)
DUP
INVOKESPECIAL (Result$Err$$cachedSerializer$delegate$1, <init>, ()V)
PUTSTATIC (Result$Err$$cachedSerializer$delegate$1, INSTANCE, LResult$Err$$cachedSerializer$delegate$1;)
INVOKESPECIAL (Result$Err$1, <init>, ()V)
PUTSTATIC (Result$Err$1, INSTANCE, LResult$Err$1;)
RETURN
}
@@ -415,7 +441,7 @@ final class Result$Err$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda
LABEL (L0)
LINENUMBER (15)
ALOAD (0)
INVOKEVIRTUAL (Result$Err$$cachedSerializer$delegate$1, invoke, ()Lkotlinx/serialization/KSerializer;)
INVOKEVIRTUAL (Result$Err$1, invoke, ()Lkotlinx/serialization/KSerializer;)
ARETURN
LABEL (L1)
}
@@ -434,7 +460,7 @@ public final class Result$Err : Result {
LABEL (L0)
LINENUMBER (15)
GETSTATIC (kotlin/LazyThreadSafetyMode, PUBLICATION, Lkotlin/LazyThreadSafetyMode;)
GETSTATIC (Result$Err$$cachedSerializer$delegate$1, INSTANCE, LResult$Err$$cachedSerializer$delegate$1;)
GETSTATIC (Result$Err$1, INSTANCE, LResult$Err$1;)
CHECKCAST (kotlin/jvm/functions/Function0)
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
PUTSTATIC (Result$Err, $cachedSerializer$delegate, Lkotlin/Lazy;)
@@ -451,15 +477,13 @@ public final class Result$Err : Result {
LABEL (L1)
}
private final kotlin.Lazy get$cachedSerializer$delegate()
private final kotlinx.serialization.KSerializer get$cachedSerializer()
public final kotlinx.serialization.KSerializer serializer() {
LABEL (L0)
LINENUMBER (15)
ALOAD (0)
INVOKESPECIAL (Result$Err, get$cachedSerializer$delegate, ()Lkotlin/Lazy;)
INVOKEINTERFACE (kotlin/Lazy, getValue, ()Ljava/lang/Object;)
CHECKCAST (kotlinx/serialization/KSerializer)
INVOKESPECIAL (Result$Err, get$cachedSerializer, ()Lkotlinx/serialization/KSerializer;)
ARETURN
LABEL (L1)
}
@@ -737,10 +761,12 @@ public abstract class Result : java/lang/Object, X {
LABEL (L0)
LINENUMBER (12)
GETSTATIC (kotlin/LazyThreadSafetyMode, PUBLICATION, Lkotlin/LazyThreadSafetyMode;)
GETSTATIC (Result$Companion$$cachedSerializer$delegate$1, INSTANCE, LResult$Companion$$cachedSerializer$delegate$1;)
GETSTATIC (Result$Companion$1, INSTANCE, LResult$Companion$1;)
CHECKCAST (kotlin/jvm/functions/Function0)
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
PUTSTATIC (Result, $cachedSerializer$delegate, Lkotlin/Lazy;)
LABEL (L1)
LINENUMBER (16)
RETURN
}