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:
committed by
Space Team
parent
3e8f7b8ee4
commit
339b152390
+93
-25
@@ -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,
|
||||
|
||||
+103
-62
@@ -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()
|
||||
|
||||
+5
-5
@@ -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)
|
||||
}
|
||||
|
||||
+16
-3
@@ -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])
|
||||
}
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
|
||||
+54
-44
@@ -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,
|
||||
|
||||
+30
-1
@@ -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)
|
||||
|
||||
+2
@@ -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)
|
||||
|
||||
+42
-23
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user