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
|
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.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.jvm.functionByName
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
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.deepCopyWithVariables
|
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_NAME_FQ
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.contextSerializerId
|
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.enumSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.objectSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.objectSerializerId
|
||||||
@@ -178,6 +174,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
|||||||
kOutputClass: IrClassSymbol,
|
kOutputClass: IrClassSymbol,
|
||||||
ignoreIndexTo: Int,
|
ignoreIndexTo: Int,
|
||||||
initializerAdapter: (IrExpressionBody) -> IrExpression,
|
initializerAdapter: (IrExpressionBody) -> IrExpression,
|
||||||
|
cachedChildSerializerByIndex: (Int) -> IrExpression?,
|
||||||
genericGetter: ((Int, IrType) -> 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())
|
if (it.elementMethodPrefix != "Unit") args.add(property.irGet())
|
||||||
f to args
|
f to args
|
||||||
},
|
},
|
||||||
|
cachedChildSerializerByIndex(index),
|
||||||
genericGetter
|
genericGetter
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -249,11 +247,12 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
|||||||
property: IrSerializableProperty,
|
property: IrSerializableProperty,
|
||||||
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
|
cachedSerializer: IrExpression?,
|
||||||
genericGetter: ((Int, IrType) -> IrExpression)? = null,
|
genericGetter: ((Int, IrType) -> IrExpression)? = null,
|
||||||
returnTypeHint: IrType? = null
|
returnTypeHint: IrType? = null
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
val sti = getIrSerialTypeInfo(property, compilerContext)
|
val sti = getIrSerialTypeInfo(property, compilerContext)
|
||||||
val innerSerial = serializerInstance(
|
val innerSerial = cachedSerializer ?: serializerInstance(
|
||||||
sti.serializer,
|
sti.serializer,
|
||||||
compilerContext,
|
compilerContext,
|
||||||
property.type,
|
property.type,
|
||||||
@@ -305,24 +304,33 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
|||||||
fun IrBuilderWithScope.serializerTower(
|
fun IrBuilderWithScope.serializerTower(
|
||||||
generator: SerializerIrGenerator,
|
generator: SerializerIrGenerator,
|
||||||
dispatchReceiverParameter: IrValueParameter,
|
dispatchReceiverParameter: IrValueParameter,
|
||||||
property: IrSerializableProperty
|
property: IrSerializableProperty,
|
||||||
|
cachedSerializer: IrExpression?
|
||||||
): IrExpression? {
|
): IrExpression? {
|
||||||
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableCallableId).single()
|
val nullableSerClass = compilerContext.referenceProperties(SerialEntityNames.wrapIntoNullableCallableId).single()
|
||||||
val serializer =
|
|
||||||
property.serializableWith(compilerContext)
|
val serializerExpression = if (cachedSerializer != null) {
|
||||||
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
|
cachedSerializer
|
||||||
compilerContext,
|
} else {
|
||||||
property.type
|
val serializerClassSymbol =
|
||||||
) else null
|
property.serializableWith(compilerContext)
|
||||||
return serializerInstance(
|
?: if (!property.type.isTypeParameter()) generator.findTypeSerializerOrContext(
|
||||||
serializer,
|
compilerContext,
|
||||||
compilerContext,
|
property.type
|
||||||
property.type,
|
) else null
|
||||||
genericIndex = property.genericIndex
|
|
||||||
) { it, _ ->
|
serializerInstance(
|
||||||
val ir = generator.localSerializersFieldsDescriptors[it]
|
serializerClassSymbol,
|
||||||
irGetField(irGet(dispatchReceiverParameter), ir.backingField!!)
|
compilerContext,
|
||||||
}?.let { expr -> wrapWithNullableSerializerIfNeeded(property.type, expr, nullableSerClass) }
|
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(
|
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(
|
fun IrBuilderWithScope.serializerInstance(
|
||||||
serializerClassOriginal: IrClassSymbol?,
|
serializerClassOriginal: IrClassSymbol?,
|
||||||
pluginContext: SerializationPluginContext,
|
pluginContext: SerializationPluginContext,
|
||||||
|
|||||||
+103
-62
@@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
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.DeclarationIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
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.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
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.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 {
|
interface IrBuilderWithPluginContext {
|
||||||
@@ -61,8 +53,10 @@ interface IrBuilderWithPluginContext {
|
|||||||
visibility = DescriptorVisibilities.LOCAL
|
visibility = DescriptorVisibilities.LOCAL
|
||||||
origin = SERIALIZATION_PLUGIN_ORIGIN
|
origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||||
}
|
}
|
||||||
function.body =
|
function.body = DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset) {
|
||||||
DeclarationIrBuilder(compilerContext, function.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
val expr = addAndGetLastExpression(bodyGen)
|
||||||
|
+irReturn(expr)
|
||||||
|
}
|
||||||
function.parent = this
|
function.parent = this
|
||||||
|
|
||||||
val f0Type = compilerContext.irBuiltIns.functionN(0)
|
val f0Type = compilerContext.irBuiltIns.functionN(0)
|
||||||
@@ -78,78 +72,105 @@ interface IrBuilderWithPluginContext {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createLazyProperty(
|
fun addLazyValProperty(
|
||||||
containingClass: IrClass,
|
containingClass: IrClass,
|
||||||
targetIrType: IrType,
|
targetIrType: IrType,
|
||||||
name: Name,
|
propertyName: Name,
|
||||||
|
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE,
|
||||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||||
): IrProperty {
|
): IrProperty {
|
||||||
val lazySafeModeClassDescriptor = compilerContext.referenceClass(ClassId.topLevel(LAZY_MODE_FQ))!!.owner
|
val lazyIrType =
|
||||||
val lazyFunctionSymbol = compilerContext.referenceFunctions(CallableId(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, Name.identifier("lazy"))).single {
|
compilerContext.lazyClass.defaultType.substitute(mapOf(compilerContext.lazyClass.typeParameters[0].symbol to targetIrType))
|
||||||
it.owner.valueParameters.size == 2 && it.owner.valueParameters[0].type == lazySafeModeClassDescriptor.defaultType
|
|
||||||
|
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 prop = containingClass.addProperty {
|
||||||
val builder = DeclarationIrBuilder(compilerContext, containingClass.symbol, startOffset, endOffset)
|
startOffset = containingClass.startOffset
|
||||||
val initializerBody = builder.run {
|
endOffset = containingClass.endOffset
|
||||||
val enumElement = IrGetEnumValueImpl(
|
name = propertyName
|
||||||
startOffset,
|
this.visibility = visibility
|
||||||
endOffset,
|
this.isVar = false
|
||||||
lazySafeModeClassDescriptor.defaultType,
|
origin = SERIALIZATION_PLUGIN_ORIGIN
|
||||||
publicationEntryDescriptor.symbol
|
}.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(
|
getter.apply {
|
||||||
irInvoke(null, lazyFunctionSymbol, listOf(targetIrType), listOf(enumElement, lambdaExpression), lazyIrType)
|
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(
|
fun IrClass.addValPropertyWithJvmField(
|
||||||
companionClass: IrClass,
|
|
||||||
type: IrType,
|
type: IrType,
|
||||||
name: Name,
|
name: Name,
|
||||||
|
visibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE,
|
||||||
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
initializerBuilder: IrBlockBodyBuilder.() -> Unit
|
||||||
): IrProperty {
|
): IrProperty {
|
||||||
return generateSimplePropertyWithBackingField(name, type, companionClass).apply {
|
return generateSimplePropertyWithBackingField(name, type, this, visibility).apply {
|
||||||
companionClass.contributeAnonymousInitializer {
|
val field = backingField!!
|
||||||
val irBlockBody = irBlockBody(startOffset, endOffset, initializerBuilder)
|
addAnonymousInit {
|
||||||
irBlockBody.statements.dropLast(1).forEach { +it }
|
val resultExpression = addAndGetLastExpression(initializerBuilder)
|
||||||
val expression = irBlockBody.statements.last() as? IrExpression
|
+irSetField(irGet(thisReceiver!!), field, resultExpression)
|
||||||
?: throw AssertionError("Last statement in property initializer builder is not an a expression")
|
|
||||||
+irSetField(irGetObject(companionClass), backingField!!, expression)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
* Add all statements to the builder, except the last one.
|
||||||
factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
* The last statement should be an expression, it will return as a result
|
||||||
it.parent = this
|
*/
|
||||||
declarations.add(it)
|
private fun IrStatementsBuilder<*>.addAndGetLastExpression(blockBuilder: IrBlockBodyBuilder.() -> Unit): IrExpression {
|
||||||
it.body = DeclarationIrBuilder(compilerContext, symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, bodyGen)
|
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 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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.irInvoke(
|
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 {
|
fun IrBuilderWithScope.irBinOp(name: Name, lhs: IrExpression, rhs: IrExpression): IrExpression {
|
||||||
val classFqName = (lhs.type as IrSimpleType).classOrNull!!.owner.fqNameWhenAvailable!!
|
val classFqName = (lhs.type as IrSimpleType).classOrNull!!.owner.fqNameWhenAvailable!!
|
||||||
val symbol = compilerContext.referenceFunctions(CallableId(ClassId.topLevel(classFqName), name)).single()
|
val symbol = compilerContext.referenceFunctions(CallableId(ClassId.topLevel(classFqName), name)).single()
|
||||||
|
|||||||
+5
-5
@@ -119,16 +119,16 @@ class SerializableCompanionIrGenerator(
|
|||||||
val targetIrType =
|
val targetIrType =
|
||||||
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
|
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
|
||||||
|
|
||||||
val property = createLazyProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
|
val property = addLazyValProperty(irClass, targetIrType, SerialEntityNames.CACHED_SERIALIZER_PROPERTY_NAME) {
|
||||||
val expr = serializerInstance(
|
val expr = requireNotNull(
|
||||||
serializer, compilerContext, serializableIrClass.defaultType
|
serializerInstance(serializer, compilerContext, serializableIrClass.defaultType)
|
||||||
)
|
)
|
||||||
patchSerializableClassWithMarkerAnnotation(kSerializerIrClass)
|
patchSerializableClassWithMarkerAnnotation(kSerializerIrClass)
|
||||||
+irReturn(requireNotNull(expr))
|
+expr
|
||||||
}
|
}
|
||||||
|
|
||||||
addFunctionBody(methodDescriptor) {
|
addFunctionBody(methodDescriptor) {
|
||||||
+irReturn(getLazyValueExpression(it.dispatchReceiverParameter!!, property, targetIrType))
|
+irReturn(irInvoke(irGet(it.dispatchReceiverParameter!!), property.getter!!.symbol))
|
||||||
}
|
}
|
||||||
generateSerializerFactoryIfNeeded(methodDescriptor)
|
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.backend.common.lower.irThrow
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
@@ -56,6 +57,13 @@ class SerializableIrGenerator(
|
|||||||
|
|
||||||
private val IrClass.isInternalSerializable: Boolean get() = kind == ClassKind.CLASS && hasSerializableOrMetaAnnotationWithoutArgs()
|
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) =
|
fun generateInternalConstructor(constructorDescriptor: IrConstructor) =
|
||||||
addFunctionBody(constructorDescriptor) { ctor ->
|
addFunctionBody(constructorDescriptor) { ctor ->
|
||||||
val thiz = irClass.thisReceiver!!
|
val thiz = irClass.thisReceiver!!
|
||||||
@@ -200,10 +208,10 @@ class SerializableIrGenerator(
|
|||||||
return irGetField(irGetObject(companionObject), property.backingField!!)
|
return irGetField(irGetObject(companionObject), property.backingField!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBlockBodyBuilder.createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
|
private fun createCachedDescriptorProperty(companionObject: IrClass): IrProperty {
|
||||||
val serialDescIrType = serialDescriptorClass.defaultType
|
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(
|
val serialDescVar = irTemporary(
|
||||||
getInstantiateDescriptorExpr(),
|
getInstantiateDescriptorExpr(),
|
||||||
nameHint = "serialDesc"
|
nameHint = "serialDesc"
|
||||||
@@ -342,10 +350,15 @@ class SerializableIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val cachedChildSerializerByIndex = createCacheableChildSerializersFactory(
|
||||||
|
cachedChildSerializersProperty,
|
||||||
|
cachedChildSerializers.map { it != null }
|
||||||
|
) { irClass.companionObject()!! }
|
||||||
|
|
||||||
serializeAllProperties(
|
serializeAllProperties(
|
||||||
serializableProperties, objectToSerialize,
|
serializableProperties, objectToSerialize,
|
||||||
localOutput, localSerialDesc, kOutputClass,
|
localOutput, localSerialDesc, kOutputClass,
|
||||||
ignoreIndexTo, initializerAdapter
|
ignoreIndexTo, initializerAdapter, cachedChildSerializerByIndex,
|
||||||
) { it, _ ->
|
) { it, _ ->
|
||||||
irGet(writeSelfFunction.valueParameters[3 + it])
|
irGet(writeSelfFunction.valueParameters[3 + it])
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -53,7 +53,7 @@ class SerializerForInlineClassGenerator(
|
|||||||
encoderClass.functionByName("${CallingConventions.encode}${it.elementMethodPrefix}")
|
encoderClass.functionByName("${CallingConventions.encode}${it.elementMethodPrefix}")
|
||||||
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
val args = if (it.elementMethodPrefix != "Unit") listOf(value) else emptyList()
|
||||||
f to args
|
f to args
|
||||||
})
|
}, null)
|
||||||
|
|
||||||
val actualEncodeCall = irIfNull(compilerContext.irBuiltIns.unitType, irGet(inlineEncoder), irNull(), elementCall)
|
val actualEncodeCall = irIfNull(compilerContext.irBuiltIns.unitType, irGet(inlineEncoder), irNull(), elementCall)
|
||||||
+actualEncodeCall
|
+actualEncodeCall
|
||||||
@@ -77,7 +77,7 @@ class SerializerForInlineClassGenerator(
|
|||||||
decoderClass.functionByName( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
decoderClass.functionByName( "${CallingConventions.decode}${sti.elementMethodPrefix}SerializableValue") to listOf(innerSerial)
|
||||||
}, {
|
}, {
|
||||||
decoderClass.functionByName("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
decoderClass.functionByName("${CallingConventions.decode}${it.elementMethodPrefix}") to listOf()
|
||||||
}, returnTypeHint = inlinedType)
|
}, null, returnTypeHint = inlinedType)
|
||||||
val value = coerceToBox(actualCall, loadFunc.returnType)
|
val value = coerceToBox(actualCall, loadFunc.returnType)
|
||||||
+irReturn(value)
|
+irReturn(value)
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-44
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
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.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||||
import org.jetbrains.kotlin.backend.jvm.functionByName
|
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.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
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.SerializationDescriptorSerializerPlugin
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.CACHED_CHILD_SERIALIZERS_PROPERTY_NAME
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
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.ENCODER_CLASS
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_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 isGeneratedSerializer = irClass.superTypes.any(IrType::isGeneratedKSerializer)
|
||||||
|
|
||||||
protected val generatedSerialDescPropertyDescriptor = getProperty(
|
protected val generatedSerialDescPropertyDescriptor = getProperty(
|
||||||
SerialEntityNames.SERIAL_DESC_FIELD,
|
SerialEntityNames.SERIAL_DESC_FIELD
|
||||||
{ true }
|
) { true }?.takeIf { it.isFromPlugin(compilerContext.afterK2) }
|
||||||
)?.takeIf { it.isFromPlugin(compilerContext.afterK2) }
|
|
||||||
|
|
||||||
protected val anySerialDescProperty = getProperty(
|
protected val anySerialDescProperty = getProperty(
|
||||||
SerialEntityNames.SERIAL_DESC_FIELD,
|
SerialEntityNames.SERIAL_DESC_FIELD,
|
||||||
@@ -80,6 +78,14 @@ open class SerializerIrGenerator(
|
|||||||
var localSerializersFieldsDescriptors: List<IrProperty> = emptyList()
|
var localSerializersFieldsDescriptors: List<IrProperty> = emptyList()
|
||||||
private set
|
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
|
// null if was not found — we're in FIR
|
||||||
private fun findLocalSerializersFieldDescriptors(): List<IrProperty?> {
|
private fun findLocalSerializersFieldDescriptors(): List<IrProperty?> {
|
||||||
val count = serializableIrClass.typeParameters.size
|
val count = serializableIrClass.typeParameters.size
|
||||||
@@ -112,42 +118,29 @@ open class SerializerIrGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val anonymousInit = irClass.run {
|
irClass.addAnonymousInit {
|
||||||
val symbol = IrAnonymousInitializerSymbolImpl(symbol)
|
val localDesc = irTemporary(
|
||||||
irClass.factory.createAnonymousInitializer(startOffset, endOffset, SERIALIZATION_PLUGIN_ORIGIN, symbol).also {
|
instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)),
|
||||||
it.parent = this
|
nameHint = "serialDesc"
|
||||||
declarations.add(it)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
anonymousInit.buildWithScope { initIrBody ->
|
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
|
||||||
compilerContext.symbolTable.withReferenceScope(initIrBody) {
|
// add class annotations
|
||||||
initIrBody.body =
|
copySerialInfoAnnotationsToDescriptor(
|
||||||
DeclarationIrBuilder(compilerContext, initIrBody.symbol, initIrBody.startOffset, initIrBody.endOffset).irBlockBody {
|
collectSerialInfoAnnotations(serializableIrClass),
|
||||||
val localDesc = irTemporary(
|
localDesc,
|
||||||
instantiateNewDescriptor(serialDescImplClass, irGet(thisAsReceiverParameter)),
|
serialDescImplClass.functionByName(CallingConventions.addClassAnnotation)
|
||||||
nameHint = "serialDesc"
|
)
|
||||||
)
|
|
||||||
|
|
||||||
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
|
// save local descriptor to field
|
||||||
// add class annotations
|
+irSetField(
|
||||||
copySerialInfoAnnotationsToDescriptor(
|
IrGetValueImpl(
|
||||||
collectSerialInfoAnnotations(serializableIrClass),
|
startOffset, endOffset,
|
||||||
localDesc,
|
thisAsReceiverParameter.symbol
|
||||||
serialDescImplClass.functionByName(CallingConventions.addClassAnnotation)
|
),
|
||||||
)
|
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 ->
|
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(
|
requireNotNull(
|
||||||
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, it)
|
serializerTower(this@SerializerIrGenerator, irFun.dispatchReceiverParameter!!, property, cachedChildSerializerByIndex(index))
|
||||||
) { "Property ${it.name} must have a serializer" }
|
) { "Property ${property.name} must have a serializer" }
|
||||||
}
|
}
|
||||||
|
|
||||||
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
|
val kSerType = ((irFun.returnType as IrSimpleType).arguments.first() as IrTypeProjection).type
|
||||||
@@ -294,9 +292,14 @@ open class SerializerIrGenerator(
|
|||||||
val initializerAdapter: (IrExpressionBody) -> IrExpression =
|
val initializerAdapter: (IrExpressionBody) -> IrExpression =
|
||||||
createInitializerAdapter(serializableIrClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) })
|
createInitializerAdapter(serializableIrClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) })
|
||||||
|
|
||||||
|
val cachedChildSerializerByIndex =
|
||||||
|
createCacheableChildSerializersFactory(cachedChildSerializersProperty, cacheableChildSerializers) {
|
||||||
|
serializableIrClass.companionObject()!!
|
||||||
|
}
|
||||||
|
|
||||||
serializeAllProperties(
|
serializeAllProperties(
|
||||||
serializableProperties, objectToSerialize, localOutput,
|
serializableProperties, objectToSerialize, localOutput,
|
||||||
localSerialDesc, kOutputClass, ignoreIndexTo = -1, initializerAdapter
|
localSerialDesc, kOutputClass, ignoreIndexTo = -1, initializerAdapter, cachedChildSerializerByIndex
|
||||||
) { it, _ ->
|
) { it, _ ->
|
||||||
val ir = localSerializersFieldsDescriptors[it]
|
val ir = localSerializersFieldsDescriptors[it]
|
||||||
irGetField(irGet(saveFunc.dispatchReceiverParameter!!), ir.backingField!!)
|
irGetField(irGet(saveFunc.dispatchReceiverParameter!!), ir.backingField!!)
|
||||||
@@ -314,12 +317,14 @@ open class SerializerIrGenerator(
|
|||||||
property: IrSerializableProperty,
|
property: IrSerializableProperty,
|
||||||
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
whenHaveSerializer: (serializer: IrExpression, sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
whenDoNot: (sti: IrSerialTypeInfo) -> FunctionWithArgs,
|
||||||
|
cachedSerializer: IrExpression?,
|
||||||
returnTypeHint: IrType? = null
|
returnTypeHint: IrType? = null
|
||||||
): IrExpression = formEncodeDecodePropertyCall(
|
): IrExpression = formEncodeDecodePropertyCall(
|
||||||
encoder,
|
encoder,
|
||||||
property,
|
property,
|
||||||
whenHaveSerializer,
|
whenHaveSerializer,
|
||||||
whenDoNot,
|
whenDoNot,
|
||||||
|
cachedSerializer,
|
||||||
{ it, _ ->
|
{ it, _ ->
|
||||||
val ir = localSerializersFieldsDescriptors[it]
|
val ir = localSerializersFieldsDescriptors[it]
|
||||||
irGetField(irGet(dispatchReceiver), ir.backingField!!)
|
irGetField(irGet(dispatchReceiver), ir.backingField!!)
|
||||||
@@ -405,6 +410,11 @@ open class SerializerIrGenerator(
|
|||||||
)
|
)
|
||||||
val localInput = irTemporary(call, "input")
|
val localInput = irTemporary(call, "input")
|
||||||
|
|
||||||
|
val cachedChildSerializerByIndex = createCacheableChildSerializersFactory(
|
||||||
|
cachedChildSerializersProperty,
|
||||||
|
cacheableChildSerializers
|
||||||
|
) { serializableIrClass.companionObject()!! }
|
||||||
|
|
||||||
// prepare all .decodeXxxElement calls
|
// prepare all .decodeXxxElement calls
|
||||||
val decoderCalls: List<Pair<Int, IrExpression>> =
|
val decoderCalls: List<Pair<Int, IrExpression>> =
|
||||||
serializableProperties.mapIndexed { index, property ->
|
serializableProperties.mapIndexed { index, property ->
|
||||||
@@ -422,7 +432,7 @@ open class SerializerIrGenerator(
|
|||||||
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}" &&
|
it.owner.name.asString() == "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}" &&
|
||||||
it.owner.valueParameters.size == 2
|
it.owner.valueParameters.size == 2
|
||||||
} to listOf(localSerialDesc.get(), irInt(index))
|
} to listOf(localSerialDesc.get(), irInt(index))
|
||||||
}, returnTypeHint = property.type)
|
}, cachedChildSerializerByIndex(index), returnTypeHint = property.type)
|
||||||
// local$i = localInput.decode...(...)
|
// local$i = localInput.decode...(...)
|
||||||
+irSet(
|
+irSet(
|
||||||
serialPropertiesMap.getValue(property.ir).symbol,
|
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.IrGenerationExtension
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
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.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
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.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializationJvmIrIntrinsicSupport
|
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializationJvmIrIntrinsicSupport
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
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 org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@@ -55,6 +60,24 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
|
|||||||
|
|
||||||
internal val copiedStaticWriteSelf: MutableMap<IrSimpleFunction, IrSimpleFunction> = ConcurrentHashMap()
|
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(
|
internal val enumSerializerFactoryFunc = baseContext.referenceFunctions(
|
||||||
CallableId(
|
CallableId(
|
||||||
SerializationPackages.internalPackageFqName,
|
SerializationPackages.internalPackageFqName,
|
||||||
@@ -69,6 +92,12 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
|
|||||||
)
|
)
|
||||||
).singleOrNull()
|
).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 val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null
|
||||||
|
|
||||||
override fun referenceClassId(classId: ClassId): IrClassSymbol? = referenceClass(classId)
|
override fun referenceClassId(classId: ClassId): IrClassSymbol? = referenceClass(classId)
|
||||||
|
|||||||
+2
@@ -68,6 +68,7 @@ object SerialEntityNames {
|
|||||||
|
|
||||||
const val CACHED_DESCRIPTOR_FIELD = "\$cachedDescriptor"
|
const val CACHED_DESCRIPTOR_FIELD = "\$cachedDescriptor"
|
||||||
const val CACHED_SERIALIZER_PROPERTY = "\$cachedSerializer"
|
const val CACHED_SERIALIZER_PROPERTY = "\$cachedSerializer"
|
||||||
|
const val CACHED_CHILD_SERIALIZERS_PROPERTY = "\$childSerializers"
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
val KCLASS_NAME_FQ = FqName("kotlin.reflect.KClass")
|
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 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 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_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 CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
|
||||||
|
|
||||||
val ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
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() {
|
public kotlinx.serialization.KSerializer[] childSerializers() {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (12)
|
LINENUMBER (12)
|
||||||
|
INVOKESTATIC (ListOfUsers, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (1)
|
||||||
ICONST_1
|
ICONST_1
|
||||||
ANEWARRAY (kotlinx/serialization/KSerializer)
|
ANEWARRAY (kotlinx/serialization/KSerializer)
|
||||||
ASTORE (1)
|
ASTORE (2)
|
||||||
|
ALOAD (2)
|
||||||
|
ICONST_0
|
||||||
ALOAD (1)
|
ALOAD (1)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
AALOAD
|
||||||
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
|
AASTORE
|
||||||
ALOAD (1)
|
ALOAD (2)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
@@ -78,17 +77,17 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
|||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
|
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
|
||||||
ASTORE (7)
|
ASTORE (7)
|
||||||
|
INVOKESTATIC (ListOfUsers, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (8)
|
||||||
ALOAD (7)
|
ALOAD (7)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
|
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
|
||||||
IFEQ (L2)
|
IFEQ (L2)
|
||||||
ALOAD (7)
|
ALOAD (7)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
ALOAD (8)
|
||||||
DUP
|
ICONST_0
|
||||||
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/KSerializer)
|
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
|
||||||
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
||||||
ALOAD (6)
|
ALOAD (6)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
|
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 (7)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
ALOAD (8)
|
||||||
DUP
|
ICONST_0
|
||||||
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/KSerializer)
|
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
|
||||||
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
||||||
ALOAD (6)
|
ALOAD (6)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
|
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 {
|
public final class ListOfUsers : java/lang/Object {
|
||||||
|
private final static kotlinx.serialization.KSerializer[] $childSerializers
|
||||||
|
|
||||||
public final static ListOfUsers$Companion Companion
|
public final static ListOfUsers$Companion Companion
|
||||||
|
|
||||||
private final java.util.List list
|
private final java.util.List list
|
||||||
@@ -247,6 +246,24 @@ public final class ListOfUsers : java/lang/Object {
|
|||||||
ACONST_NULL
|
ACONST_NULL
|
||||||
INVOKESPECIAL (ListOfUsers$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
|
INVOKESPECIAL (ListOfUsers$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
|
||||||
PUTSTATIC (ListOfUsers, Companion, LListOfUsers$Companion;)
|
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
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,19 +308,21 @@ public final class ListOfUsers : java/lang/Object {
|
|||||||
LABEL (L2)
|
LABEL (L2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final static kotlinx.serialization.KSerializer[] access$get$childSerializers$cp()
|
||||||
|
|
||||||
public final java.util.List getList()
|
public final java.util.List getList()
|
||||||
|
|
||||||
public final static void write$Self(ListOfUsers self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
|
public final static void write$Self(ListOfUsers self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (12)
|
LINENUMBER (12)
|
||||||
|
GETSTATIC (ListOfUsers, $childSerializers, [Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (3)
|
||||||
ALOAD (1)
|
ALOAD (1)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
ALOAD (3)
|
||||||
DUP
|
ICONST_0
|
||||||
GETSTATIC (User$$serializer, INSTANCE, LUser$$serializer;)
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/KSerializer)
|
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
|
||||||
CHECKCAST (kotlinx/serialization/SerializationStrategy)
|
CHECKCAST (kotlinx/serialization/SerializationStrategy)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
GETFIELD (ListOfUsers, list, Ljava/util/List;)
|
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)
|
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)
|
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 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 java.lang.Object component1()
|
||||||
|
|
||||||
public final Box copy(java.lang.Object boxed)
|
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 {
|
final class SerializableObject$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||||
public final static SerializableObject$$cachedSerializer$delegate$1 INSTANCE
|
public final static SerializableObject$1 INSTANCE
|
||||||
|
|
||||||
static void <clinit>()
|
static void <clinit>()
|
||||||
|
|
||||||
@@ -212,7 +208,7 @@ public final class SerializableObject : java/lang/Object {
|
|||||||
|
|
||||||
private void <init>()
|
private void <init>()
|
||||||
|
|
||||||
private final kotlin.Lazy get$cachedSerializer$delegate()
|
private final kotlinx.serialization.KSerializer get$cachedSerializer()
|
||||||
|
|
||||||
public final kotlinx.serialization.KSerializer serializer()
|
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() {
|
public kotlinx.serialization.KSerializer[] childSerializers() {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (18)
|
LINENUMBER (18)
|
||||||
|
INVOKESTATIC (Container, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (1)
|
||||||
ICONST_1
|
ICONST_1
|
||||||
ANEWARRAY (kotlinx/serialization/KSerializer)
|
ANEWARRAY (kotlinx/serialization/KSerializer)
|
||||||
ASTORE (1)
|
ASTORE (2)
|
||||||
|
ALOAD (2)
|
||||||
|
ICONST_0
|
||||||
ALOAD (1)
|
ALOAD (1)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
GETSTATIC (Result, Companion, LResult$Companion;)
|
AALOAD
|
||||||
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
|
||||||
AASTORE
|
AASTORE
|
||||||
ALOAD (1)
|
ALOAD (2)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
@@ -74,14 +77,17 @@ public final class Container$$serializer : java/lang/Object, kotlinx/serializati
|
|||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
|
INVOKEINTERFACE (kotlinx/serialization/encoding/Decoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder;)
|
||||||
ASTORE (7)
|
ASTORE (7)
|
||||||
|
INVOKESTATIC (Container, access$get$childSerializers$cp, ()[Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (8)
|
||||||
ALOAD (7)
|
ALOAD (7)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
|
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSequentially, ()Z)
|
||||||
IFEQ (L2)
|
IFEQ (L2)
|
||||||
ALOAD (7)
|
ALOAD (7)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
GETSTATIC (Result, Companion, LResult$Companion;)
|
ALOAD (8)
|
||||||
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
ICONST_0
|
||||||
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
||||||
ALOAD (6)
|
ALOAD (6)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
|
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 (7)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
GETSTATIC (Result, Companion, LResult$Companion;)
|
ALOAD (8)
|
||||||
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
ICONST_0
|
||||||
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
CHECKCAST (kotlinx/serialization/DeserializationStrategy)
|
||||||
ALOAD (6)
|
ALOAD (6)
|
||||||
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeDecoder, decodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object;)
|
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 {
|
public final class Container : java/lang/Object {
|
||||||
|
private final static kotlinx.serialization.KSerializer[] $childSerializers
|
||||||
|
|
||||||
public final static Container$Companion Companion
|
public final static Container$Companion Companion
|
||||||
|
|
||||||
private final Result r
|
private final Result r
|
||||||
@@ -201,6 +210,20 @@ public final class Container : java/lang/Object {
|
|||||||
ACONST_NULL
|
ACONST_NULL
|
||||||
INVOKESPECIAL (Container$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
|
INVOKESPECIAL (Container$Companion, <init>, (Lkotlin/jvm/internal/DefaultConstructorMarker;)V)
|
||||||
PUTSTATIC (Container, Companion, LContainer$Companion;)
|
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
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,16 +268,21 @@ public final class Container : java/lang/Object {
|
|||||||
LABEL (L2)
|
LABEL (L2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final static kotlinx.serialization.KSerializer[] access$get$childSerializers$cp()
|
||||||
|
|
||||||
public final Result getR()
|
public final Result getR()
|
||||||
|
|
||||||
public final static void write$Self(Container self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
|
public final static void write$Self(Container self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (18)
|
LINENUMBER (18)
|
||||||
|
GETSTATIC (Container, $childSerializers, [Lkotlinx/serialization/KSerializer;)
|
||||||
|
ASTORE (3)
|
||||||
ALOAD (1)
|
ALOAD (1)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
ICONST_0
|
ICONST_0
|
||||||
GETSTATIC (Result, Companion, LResult$Companion;)
|
ALOAD (3)
|
||||||
INVOKEVIRTUAL (Result$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
ICONST_0
|
||||||
|
AALOAD
|
||||||
CHECKCAST (kotlinx/serialization/SerializationStrategy)
|
CHECKCAST (kotlinx/serialization/SerializationStrategy)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
GETFIELD (Container, r, LResult;)
|
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 {
|
final class Result$Companion$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||||
public final static Result$Companion$$cachedSerializer$delegate$1 INSTANCE
|
public final static Result$Companion$1 INSTANCE
|
||||||
|
|
||||||
static void <clinit>() {
|
static void <clinit>() {
|
||||||
NEW (Result$Companion$$cachedSerializer$delegate$1)
|
NEW (Result$Companion$1)
|
||||||
DUP
|
DUP
|
||||||
INVOKESPECIAL (Result$Companion$$cachedSerializer$delegate$1, <init>, ()V)
|
INVOKESPECIAL (Result$Companion$1, <init>, ()V)
|
||||||
PUTSTATIC (Result$Companion$$cachedSerializer$delegate$1, INSTANCE, LResult$Companion$$cachedSerializer$delegate$1;)
|
PUTSTATIC (Result$Companion$1, INSTANCE, LResult$Companion$1;)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +366,7 @@ final class Result$Companion$$cachedSerializer$delegate$1 : kotlin/jvm/internal/
|
|||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (12)
|
LINENUMBER (12)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
INVOKEVIRTUAL (Result$Companion$$cachedSerializer$delegate$1, invoke, ()Lkotlinx/serialization/KSerializer;)
|
INVOKEVIRTUAL (Result$Companion$1, invoke, ()Lkotlinx/serialization/KSerializer;)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
@@ -362,28 +390,26 @@ public final class Result$Companion : java/lang/Object {
|
|||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private final kotlin.Lazy get$cachedSerializer$delegate()
|
private final kotlinx.serialization.KSerializer get$cachedSerializer()
|
||||||
|
|
||||||
public final kotlinx.serialization.KSerializer serializer() {
|
public final kotlinx.serialization.KSerializer serializer() {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (12)
|
LINENUMBER (12)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
INVOKESPECIAL (Result$Companion, get$cachedSerializer$delegate, ()Lkotlin/Lazy;)
|
INVOKESPECIAL (Result$Companion, get$cachedSerializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKEINTERFACE (kotlin/Lazy, getValue, ()Ljava/lang/Object;)
|
|
||||||
CHECKCAST (kotlinx/serialization/KSerializer)
|
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class Result$Err$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
final class Result$Err$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||||
public final static Result$Err$$cachedSerializer$delegate$1 INSTANCE
|
public final static Result$Err$1 INSTANCE
|
||||||
|
|
||||||
static void <clinit>() {
|
static void <clinit>() {
|
||||||
NEW (Result$Err$$cachedSerializer$delegate$1)
|
NEW (Result$Err$1)
|
||||||
DUP
|
DUP
|
||||||
INVOKESPECIAL (Result$Err$$cachedSerializer$delegate$1, <init>, ()V)
|
INVOKESPECIAL (Result$Err$1, <init>, ()V)
|
||||||
PUTSTATIC (Result$Err$$cachedSerializer$delegate$1, INSTANCE, LResult$Err$$cachedSerializer$delegate$1;)
|
PUTSTATIC (Result$Err$1, INSTANCE, LResult$Err$1;)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +441,7 @@ final class Result$Err$$cachedSerializer$delegate$1 : kotlin/jvm/internal/Lambda
|
|||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (15)
|
LINENUMBER (15)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
INVOKEVIRTUAL (Result$Err$$cachedSerializer$delegate$1, invoke, ()Lkotlinx/serialization/KSerializer;)
|
INVOKEVIRTUAL (Result$Err$1, invoke, ()Lkotlinx/serialization/KSerializer;)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
@@ -434,7 +460,7 @@ public final class Result$Err : Result {
|
|||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (15)
|
LINENUMBER (15)
|
||||||
GETSTATIC (kotlin/LazyThreadSafetyMode, PUBLICATION, Lkotlin/LazyThreadSafetyMode;)
|
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)
|
CHECKCAST (kotlin/jvm/functions/Function0)
|
||||||
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
|
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
|
||||||
PUTSTATIC (Result$Err, $cachedSerializer$delegate, Lkotlin/Lazy;)
|
PUTSTATIC (Result$Err, $cachedSerializer$delegate, Lkotlin/Lazy;)
|
||||||
@@ -451,15 +477,13 @@ public final class Result$Err : Result {
|
|||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
|
|
||||||
private final kotlin.Lazy get$cachedSerializer$delegate()
|
private final kotlinx.serialization.KSerializer get$cachedSerializer()
|
||||||
|
|
||||||
public final kotlinx.serialization.KSerializer serializer() {
|
public final kotlinx.serialization.KSerializer serializer() {
|
||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (15)
|
LINENUMBER (15)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
INVOKESPECIAL (Result$Err, get$cachedSerializer$delegate, ()Lkotlin/Lazy;)
|
INVOKESPECIAL (Result$Err, get$cachedSerializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKEINTERFACE (kotlin/Lazy, getValue, ()Ljava/lang/Object;)
|
|
||||||
CHECKCAST (kotlinx/serialization/KSerializer)
|
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
}
|
}
|
||||||
@@ -737,10 +761,12 @@ public abstract class Result : java/lang/Object, X {
|
|||||||
LABEL (L0)
|
LABEL (L0)
|
||||||
LINENUMBER (12)
|
LINENUMBER (12)
|
||||||
GETSTATIC (kotlin/LazyThreadSafetyMode, PUBLICATION, Lkotlin/LazyThreadSafetyMode;)
|
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)
|
CHECKCAST (kotlin/jvm/functions/Function0)
|
||||||
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
|
INVOKESTATIC (kotlin/LazyKt, lazy, (Lkotlin/LazyThreadSafetyMode;Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;)
|
||||||
PUTSTATIC (Result, $cachedSerializer$delegate, Lkotlin/Lazy;)
|
PUTSTATIC (Result, $cachedSerializer$delegate, Lkotlin/Lazy;)
|
||||||
|
LABEL (L1)
|
||||||
|
LINENUMBER (16)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user