diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 657f4e5e6d3..d24a8e9f0b4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -72,7 +72,7 @@ class ReifiedTypeInliner( fun applyPluginDefinedReifiedOperationMarker( insn: MethodInsnNode, instructions: InsnList, - type: KotlinType, + type: KT, asmType: Type ): Int = -1 } @@ -206,7 +206,7 @@ class ReifiedTypeInliner( val applyResult = intrinsicsSupport.applyPluginDefinedReifiedOperationMarker( insn, instructions, - intrinsicsSupport.toKotlinType(type), + type, asmType ) if (applyResult == -1) return false diff --git a/compiler/ir/backend.common/build.gradle.kts b/compiler/ir/backend.common/build.gradle.kts index 64b0a3f01d8..52dc7b458f2 100644 --- a/compiler/ir/backend.common/build.gradle.kts +++ b/compiler/ir/backend.common/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { api(project(":compiler:ir.tree")) api(project(":compiler:ir.interpreter")) compileOnly(intellijCore()) + compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all")) } sourceSets { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt index a95b2d93f8c..73b5605fddb 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt @@ -5,9 +5,15 @@ package org.jetbrains.kotlin.backend.common.extensions +import org.jetbrains.org.objectweb.asm.tree.InsnList +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode +import org.jetbrains.kotlin.backend.common.BackendContext +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.linkage.IrDeserializer +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType interface IrGenerationExtension : IrDeserializer.IrLinkerExtension { companion object : @@ -16,4 +22,15 @@ interface IrGenerationExtension : IrDeserializer.IrLinkerExtension { ) fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) + + // TODO: normal dependency & typing + fun retrieveIntrinsic(symbol: IrFunctionSymbol): Any? = null + + + fun applyPluginDefinedReifiedOperationMarker( + insn: MethodInsnNode, + instructions: InsnList, + type: IrType, + jvmBackendContext: BackendContext, + ): Int = -1 } diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt index 9ddfe72ed53..59d3a4b9472 100644 --- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt +++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineIntrinsicsSupport.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.backend.jvm.codegen +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.intrinsics.SignatureString import org.jetbrains.kotlin.backend.jvm.ir.getCallableReferenceOwnerKClassType import org.jetbrains.kotlin.backend.jvm.ir.getCallableReferenceTopLevelFlag @@ -12,12 +14,14 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.allParametersCount import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable @@ -31,6 +35,8 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type.INT_TYPE import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import org.jetbrains.org.objectweb.asm.tree.InsnList +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode class IrInlineIntrinsicsSupport( private val classCodegen: ClassCodegen, @@ -120,4 +126,22 @@ class IrInlineIntrinsicsSupport( classCodegen.context.ktDiagnosticReporter.at(reportErrorsOn, containingFile) .report(JvmBackendErrors.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND, typeParameterName.asString()) } + + override fun applyPluginDefinedReifiedOperationMarker( + insn: MethodInsnNode, + instructions: InsnList, + type: IrType, + asmType: Type + ): Int { + return IrGenerationExtension.getInstances(classCodegen.context.state.project) + .map { + it.applyPluginDefinedReifiedOperationMarker( + insn, + instructions, + type, + classCodegen.context + ) + } + .maxOrNull() ?: -1 + } } diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index fdcddca379b..7be155da8ad 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -286,8 +286,10 @@ open class JvmIrCodegenFactory( if (evaluatorFragmentInfoForPsi2Ir != null) { context.localDeclarationsLoweringData = mutableMapOf() } + // todo: pass it here + val generationExtensions = IrGenerationExtension.getInstances(state.project) val intrinsics by lazy { IrIntrinsicMethods(irModuleFragment.irBuiltins, context.ir.symbols) } - context.getIntrinsic = { symbol: IrFunctionSymbol -> intrinsics.getIntrinsic(symbol) } + context.getIntrinsic = { symbol: IrFunctionSymbol -> intrinsics.getIntrinsic(symbol) ?: generationExtensions.firstNotNullOfOrNull { it.retrieveIntrinsic(symbol) as? IntrinsicMarker } } /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index f7e30397a81..fa58f3b88f9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -157,7 +157,7 @@ class JvmBackendContext( } } - internal fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol = + fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol = symbolTable.lazyWrapper.referenceClass(descriptor) internal fun referenceTypeParameter(descriptor: TypeParameterDescriptor): IrTypeParameterSymbol = diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/build.gradle.kts b/plugins/kotlinx-serialization/kotlinx-serialization.backend/build.gradle.kts index 645bec12136..746bcb416c0 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/build.gradle.kts +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { compileOnly(project(":compiler:backend")) compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:backend.jvm")) + compileOnly(project(":compiler:backend.jvm.codegen")) compileOnly(project(":compiler:ir.tree")) compileOnly(project(":js:js.frontend")) compileOnly(project(":js:js.translator")) diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt index df915ec5aa5..e2367a8c888 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPredicates.kt @@ -63,7 +63,7 @@ internal fun IrClass.findPluginGeneratedMethod(name: String): IrSimpleFunction? } } -internal fun IrClass.isEnumWithLegacyGeneratedSerializer(context: SerializationPluginContext): Boolean = isInternallySerializableEnum() && !context.runtimeHasEnumSerializerFactoryFunctions +internal fun IrClass.isEnumWithLegacyGeneratedSerializer(context: SerializationBaseContext): Boolean = isInternallySerializableEnum() && !context.runtimeHasEnumSerializerFactoryFunctions internal val IrClass.isSealedSerializableInterface: Boolean get() = kind == ClassKind.INTERFACE && modality == Modality.SEALED && hasSerializableOrMetaAnnotation() @@ -102,7 +102,7 @@ internal val IrClass.isSerialInfoAnnotation: Boolean internal val IrClass.isInheritableSerialInfoAnnotation: Boolean get() = annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName) -internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationPluginContext): Boolean +internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationBaseContext): Boolean = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) || isEnumWithLegacyGeneratedSerializer(context) diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt index be8e497c810..1136aedbb25 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrSerializableProperties.kt @@ -30,7 +30,7 @@ class IrSerializableProperty( override val originalDescriptorName: Name = ir.name val type = ir.getter!!.returnType as IrSimpleType val genericIndex = type.genericIndex - fun serializableWith(ctx: SerializationPluginContext) = ir.annotations.serializableWith() ?: analyzeSpecialSerializers(ctx, ir.annotations) + fun serializableWith(ctx: SerializationBaseContext) = ir.annotations.serializableWith() ?: analyzeSpecialSerializers(ctx, ir.annotations) override val optional = !ir.annotations.hasAnnotation(SerializationAnnotations.requiredAnnotationFqName) && declaresDefaultValue override val transient = ir.annotations.hasAnnotation(SerializationAnnotations.serialTransientFqName) || !hasBackingField } diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index ff46b35f4ae..763dcc6dc28 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -33,30 +33,15 @@ class SerializableCompanionIrGenerator( compilerContext: SerializationPluginContext, ) : BaseIrGenerator(irClass, compilerContext) { - private fun getSerializerGetterFunction(): IrSimpleFunction { - return irClass.findDeclaration { - (it.valueParameters.size == serializableIrClass.typeParameters.size - && it.valueParameters.all { p -> p.type.isKSerializer() }) && it.returnType.isKSerializer() - } ?: throw IllegalStateException( - "Can't find synthesized 'Companion.serializer()' function to generate, " + - "probably clash with user-defined function has occurred" - ) - } - - fun generate() { - val serializerGetterFunction = getSerializerGetterFunction() - - if (serializableIrClass.isSerializableObject - || serializableIrClass.isAbstractOrSealedSerializableClass - || serializableIrClass.isSerializableEnum() - ) { - generateLazySerializerGetter(serializerGetterFunction) - } else { - generateSerializerGetter(serializerGetterFunction) - } - } - companion object { + fun getSerializerGetterFunction(serializableIrClass: IrClass): IrSimpleFunction? { + val irClass = if (serializableIrClass.isSerializableObject) serializableIrClass else serializableIrClass.companionObject() ?: return null + return irClass.findDeclaration { + (it.valueParameters.size == serializableIrClass.typeParameters.size + && it.valueParameters.all { p -> p.type.isKSerializer() }) && it.returnType.isKSerializer() + } + } + fun generate( irClass: IrClass, context: SerializationPluginContext, @@ -71,6 +56,22 @@ class SerializableCompanionIrGenerator( } } + fun generate() { + val serializerGetterFunction = getSerializerGetterFunction(serializableIrClass) ?: throw IllegalStateException( + "Can't find synthesized 'Companion.serializer()' function to generate, " + + "probably clash with user-defined function has occurred" + ) + + if (serializableIrClass.isSerializableObject + || serializableIrClass.isAbstractOrSealedSerializableClass + || serializableIrClass.isSerializableEnum() + ) { + generateLazySerializerGetter(serializerGetterFunction) + } else { + generateSerializerGetter(serializerGetterFunction) + } + } + private fun IrBuilderWithScope.patchSerializableClassWithMarkerAnnotation(serializer: IrClass) { if (serializer.kind != ClassKind.OBJECT) { return @@ -198,6 +199,5 @@ class SerializableCompanionIrGenerator( patchSerializableClassWithMarkerAnnotation(irClass) } } - } diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializationJvmIrIntrinsicSupport.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializationJvmIrIntrinsicSupport.kt new file mode 100644 index 00000000000..fe472511b79 --- /dev/null +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializationJvmIrIntrinsicSupport.kt @@ -0,0 +1,391 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.compiler.backend.ir + +import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo +import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen +import org.jetbrains.kotlin.backend.jvm.codegen.MaterialValue +import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue +import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod +import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound +import org.jetbrains.kotlin.backend.jvm.mapping.mapClass +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner +import org.jetbrains.kotlin.codegen.inline.newMethodNodeWithCorrectStackSize +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.* +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.annotationArrayType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.doubleAnnotationArrayType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumFactoriesType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.kSerializerArrayType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.kSerializerType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.stringArrayType +import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.stringType +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME +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 +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.polymorphicSerializerId +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.referenceArraySerializerId +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.sealedSerializerId +import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins +import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import org.jetbrains.org.objectweb.asm.tree.InsnList +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode + +class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContext) : SerializationBaseContext { + companion object { + fun isSerializerReifiedFunction(targetFunction: IrFunction): Boolean = + targetFunction.fqNameWhenAvailable?.asString() == "kotlinx.serialization.SerializersKt.serializer" + && targetFunction.valueParameters.isEmpty() + && targetFunction.typeParameters.size == 1 + && targetFunction.dispatchReceiverParameter == null + && targetFunction.extensionReceiverParameter == null + } + + object ReifiedSerializerMethod : IntrinsicMethod() { + override fun invoke( + expression: IrFunctionAccessExpression, + codegen: ExpressionCodegen, + data: BlockInfo + ): PromisedValue { + with(codegen) { + val argument = expression.getTypeArgument(0)!! + SerializationJvmIrIntrinsicSupport(codegen.context).generateSerializerForType( + argument, + mv + ) + return MaterialValue(codegen, kSerializerType, expression.type) + } + } + } + + + private val emptyGenerator: BaseIrGenerator? = null + private val module = jvmBackendContext.state.module + private val typeSystemContext = jvmBackendContext.typeSystem + private val typeMapper = jvmBackendContext.defaultTypeMapper + + /** + * This likely won't work in FIR because module is empty there and can't reference dependencies + * Proper referencing can be done via FirPluginContext, but it's not available in the intrinsics. + */ + @FirIncompatiblePluginAPI + override fun referenceClassId(classId: ClassId): IrClassSymbol? { + return module.findClassAcrossModuleDependencies(classId)?.let { jvmBackendContext.referenceClass(it) } + } + + override val runtimeHasEnumSerializerFactoryFunctions: Boolean + get() = false // TODO + + private fun findTypeSerializerOrContext(argType: IrType): IrClassSymbol? = + emptyGenerator.findTypeSerializerOrContextUnchecked(this, argType) + + private fun instantiateObject(iv: InstructionAdapter, objectSymbol: IrClassSymbol) { + val originalIrClass = objectSymbol.owner + require(originalIrClass.isObject) + val targetField = jvmBackendContext.cachedDeclarations.getFieldForObjectInstance(originalIrClass) + val ownerType = typeMapper.mapClass(targetField.parentAsClass) + val fieldType = typeMapper.mapType(targetField.type) + iv.visitFieldInsn(Opcodes.GETSTATIC, ownerType.internalName, targetField.name.asString(), fieldType.descriptor) + } + + fun applyPluginDefinedReifiedOperationMarker( + insn: MethodInsnNode, + instructions: InsnList, + type: IrType, + ): Int { + val newMethodNode = newMethodNodeWithCorrectStackSize { + generateSerializerForType(type, it) + } + + instructions.remove(insn.next) + instructions.insert(insn, newMethodNode.instructions) + + return newMethodNode.maxStack + } + + private fun InstructionAdapter.putReifyMarkerIfNeeded(type: KotlinTypeMarker): Boolean = + with(typeSystemContext) { + val typeDescriptor = type.typeConstructor().getTypeParameterClassifier() + if (typeDescriptor != null) { // need further reification + ReifiedTypeInliner.putReifiedOperationMarkerIfNeeded( + typeDescriptor, + false, + ReifiedTypeInliner.OperationKind.PLUGIN_DEFINED, + this@putReifyMarkerIfNeeded, + typeSystemContext + ) + invokestatic("kotlinx/serialization/SerializersKt", "serializer", "()Lkotlinx/serialization/KSerializer;", false) + return true + } + return false + } + + fun generateSerializerForType( + type: IrType, + adapter: InstructionAdapter + ) { + with(typeSystemContext) { + if (adapter.putReifyMarkerIfNeeded(type)) return + val typeDescriptor: IrClass = type.classOrNull!!.owner + + val support = this@SerializationJvmIrIntrinsicSupport + + val serializerMethod = SerializableCompanionIrGenerator.getSerializerGetterFunction(typeDescriptor) + if (serializerMethod != null) { + // fast path + val companionType = if (typeDescriptor.isSerializableObject) typeDescriptor else typeDescriptor.companionObject()!! + support.instantiateObject(adapter, companionType.symbol) + val args = type.getArguments().map { it.getType() } + args.forEach { generateSerializerForType(it, adapter) } + val signature = kSerializerType.descriptor.repeat(args.size) + adapter.invokevirtual( + typeMapper.mapClass(companionType).internalName, + "serializer", + "(${signature})${kSerializerType.descriptor}", + false + ) + } else { + // More general path, including special ol built-in serializers for e.g. List + val serializer = support.findTypeSerializerOrContext(type) + support.stackValueSerializerInstance( + type, + serializer, + adapter + ) { genericArg -> + assert(putReifyMarkerIfNeeded(genericArg)) + } + if (type.isMarkedNullable()) adapter.wrapStackValueIntoNullableSerializer() + } + } + } + + private fun stackValueSerializerInstance( + kType: IrType, maybeSerializer: IrClassSymbol?, + iv: InstructionAdapter?, + genericIndex: Int? = null, + genericSerializerFieldGetter: (InstructionAdapter.(IrType) -> Unit)? = null, + ): Boolean = with(typeSystemContext) { + if (maybeSerializer == null && genericIndex != null) { + // get field from serializer object + iv?.run { genericSerializerFieldGetter?.invoke(this, kType) } + return true + } + val serializer = maybeSerializer ?: run { + iv?.apply { + aconst(kType.classFqName!!.asString()) + invokestatic( + "kotlinx/serialization/SerializersKt", + "noCompiledSerializer", + "(Ljava/lang/String;)Lkotlinx/serialization/KSerializer;", + false + ) + } + return false + } + if (serializer.owner.isObject) { + // singleton serializer -- just get it + iv?.let { instantiateObject(it, serializer) } + return true + } + // serializer is not singleton object and shall be instantiated + val argSerializers = (kType as IrSimpleType).arguments.map { projection -> + // check if any type argument is not serializable + val argType = projection.typeOrNull!! + val argSerializer = + if (argType.isTypeParameter()) null else findTypeSerializerOrContext(argType) + // check if it can be properly serialized with its args recursively + Pair(argType, argSerializer) + } + // new serializer if needed + iv?.apply { + val serializerType = typeMapper.mapClass(serializer.owner) + if (serializer.owner.classId == enumSerializerId && runtimeHasEnumSerializerFactoryFunctions) { + val enumIrClass = kType.classOrNull!!.owner + // runtime contains enum serializer factory functions + val javaEnumArray = Type.getType("[Ljava/lang/Enum;") + val enumJavaType = typeMapper.mapType(kType, TypeMappingMode.GENERIC_ARGUMENT) + val serialName = enumIrClass.serialName() + + if (enumIrClass.isEnumWithSerialInfoAnnotation()) { + aconst(serialName) + invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false) + checkcast(javaEnumArray) + + val entries = enumIrClass.enumEntries() + fillArray(stringType, entries) { _, entry -> + entry.annotations.serialNameValue.let { + if (it == null) { + aconst(null) + } else { + aconst(it) + } + } + } + checkcast(stringArrayType) + + fillArray(annotationArrayType, entries) { _, _ -> + // FIXME: no org.jetbrains.kotlin.codegen.ExpressionCodegen available here to generate instances from descriptors + // val annotations = entry.descriptor.annotationsWithArguments() + aconst(null) + } + checkcast(doubleAnnotationArrayType) + + invokestatic( + enumFactoriesType.internalName, + MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(), + "(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor})${kSerializerType.descriptor}", + false + ) + } else { + aconst(serialName) + invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false) + checkcast(javaEnumArray) + + invokestatic( + enumFactoriesType.internalName, + ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(), + "(${stringType.descriptor}${javaEnumArray.descriptor})${kSerializerType.descriptor}", + false + ) + } + return true + } + + anew(serializerType) + dup() + // instantiate all arg serializers on stack + val signature = StringBuilder("(") + + fun instantiate(typeArgument: Pair, writeSignature: Boolean = true) { + val (argType, argSerializer) = typeArgument + stackValueSerializerInstance( + argType, + argSerializer, + this, + argType.genericIndex, + genericSerializerFieldGetter + ) + // wrap into nullable serializer if argType is nullable + if (argType.isMarkedNullable()) wrapStackValueIntoNullableSerializer() + if (writeSignature) signature.append(kSerializerType.descriptor) + } + + val serialName = kType.serialName() + when (serializer.owner.classId) { + enumSerializerId -> { + // support legacy serializer instantiation by constructor for old runtimes + aconst(serialName) + signature.append("Ljava/lang/String;") + val enumJavaType = typeMapper.mapTypeCommon(kType, TypeMappingMode.GENERIC_ARGUMENT) + val javaEnumArray = Type.getType("[Ljava/lang/Enum;") + invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false) + checkcast(javaEnumArray) + signature.append(javaEnumArray.descriptor) + } + contextSerializerId, polymorphicSerializerId -> { + // a special way to instantiate enum -- need a enum KClass reference + // GENERIC_ARGUMENT forces boxing in order to obtain KClass + aconst(typeMapper.mapTypeCommon(kType, TypeMappingMode.GENERIC_ARGUMENT)) + AsmUtil.wrapJavaClassIntoKClass(this) + signature.append(AsmTypes.K_CLASS_TYPE.descriptor) + if (serializer.owner.classId == contextSerializerId && serializer.constructors.any { it.owner.valueParameters.size == 3 }) { // TODO: this isn't working with LAZY IR CLASS + // append new additional arguments + val fallbackDefaultSerializer = findTypeSerializer(this@SerializationJvmIrIntrinsicSupport, kType) + if (fallbackDefaultSerializer != null && fallbackDefaultSerializer != serializer) { + instantiate(kType to fallbackDefaultSerializer, writeSignature = false) + } else { + aconst(null) + } + signature.append(kSerializerType.descriptor) + fillArray(kSerializerType, argSerializers) { _, serializer -> + instantiate(serializer, writeSignature = false) + } + signature.append(kSerializerArrayType.descriptor) + } + } + referenceArraySerializerId -> { + // a special way to instantiate reference array serializer -- need an element KClass reference + aconst(typeMapper.mapTypeCommon(kType.getArguments().first().getType(), TypeMappingMode.GENERIC_ARGUMENT)) + AsmUtil.wrapJavaClassIntoKClass(this) + signature.append(AsmTypes.K_CLASS_TYPE.descriptor) + // Reference array serializer still needs serializer for its argument type + instantiate(argSerializers[0]) + } + sealedSerializerId -> { + aconst(serialName) + signature.append("Ljava/lang/String;") + aconst(typeMapper.mapTypeCommon(kType, TypeMappingMode.GENERIC_ARGUMENT)) + AsmUtil.wrapJavaClassIntoKClass(this) + signature.append(AsmTypes.K_CLASS_TYPE.descriptor) + val (subClasses, subSerializers) = emptyGenerator.allSealedSerializableSubclassesFor( + kType.classOrUpperBound()?.owner!!, + this@SerializationJvmIrIntrinsicSupport + ) + // KClasses vararg + fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type -> + aconst(typeMapper.mapTypeCommon(type, TypeMappingMode.GENERIC_ARGUMENT)) + AsmUtil.wrapJavaClassIntoKClass(this) + } + signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor) + // Serializers vararg + fillArray(kSerializerType, subSerializers) { i, serializer -> + val (argType, argSerializer) = subClasses[i] to serializer + assert( + stackValueSerializerInstance( + argType, + argSerializer, + this, + argType.genericIndex + ) { genericType -> + // if we encountered generic type parameter in one of subclasses of sealed class, use polymorphism from upper bound + assert( + stackValueSerializerInstance( + (genericType.classifierOrNull as IrTypeParameterSymbol).owner.representativeUpperBound, + jvmBackendContext.referenceClass(module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer)), + this + ) + ) + } + ) + if (argType.isMarkedNullable()) wrapStackValueIntoNullableSerializer() + } + signature.append(kSerializerArrayType.descriptor) + } + objectSerializerId -> { + aconst(serialName) + signature.append("Ljava/lang/String;") + instantiateObject(iv, kType.classOrNull!!) + signature.append("Ljava/lang/Object;") + } + // all serializers get arguments with serializers of their generic types + else -> argSerializers.forEach { instantiate(it) } + } + signature.append(")V") + // invoke constructor + invokespecial(serializerType.internalName, "", signature.toString(), false) + } + return true + } +} \ No newline at end of file diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt index 49cbcaf7256..ea0012dc3d8 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerSearchUtil.kt @@ -16,7 +16,10 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages +import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.contextSerializerId import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.enumSerializerId @@ -30,7 +33,13 @@ class IrSerialTypeInfo( val serializer: IrClassSymbol? = null ) -fun BaseIrGenerator.getIrSerialTypeInfo(property: IrSerializableProperty, ctx: SerializationPluginContext): IrSerialTypeInfo { +interface SerializationBaseContext { + fun referenceClassId(classId: ClassId): IrClassSymbol? + + val runtimeHasEnumSerializerFactoryFunctions: Boolean +} + +fun BaseIrGenerator.getIrSerialTypeInfo(property: IrSerializableProperty, ctx: SerializationBaseContext): IrSerialTypeInfo { fun SerializableInfo(serializer: IrClassSymbol?) = IrSerialTypeInfo(property, if (property.type.isNullable()) "Nullable" else "", serializer) @@ -57,7 +66,7 @@ fun BaseIrGenerator.getIrSerialTypeInfo(property: IrSerializableProperty, ctx: S } } -fun BaseIrGenerator.findAddOnSerializer(propertyType: IrType, ctx: SerializationPluginContext): IrClassSymbol? { +fun BaseIrGenerator.findAddOnSerializer(propertyType: IrType, ctx: SerializationBaseContext): IrClassSymbol? { val classSymbol = propertyType.classOrNull ?: return null additionalSerializersInScopeOfCurrentFile[classSymbol to propertyType.isNullable()]?.let { return it } if (classSymbol in contextualKClassListInCurrentFile) @@ -68,61 +77,62 @@ fun BaseIrGenerator.findAddOnSerializer(propertyType: IrType, ctx: Serialization return null } -fun BaseIrGenerator.findTypeSerializerOrContext( - context: SerializationPluginContext, kType: IrType +fun BaseIrGenerator?.findTypeSerializerOrContext( + context: SerializationBaseContext, kType: IrType ): IrClassSymbol? { if (kType.isTypeParameter()) return null return findTypeSerializerOrContextUnchecked(context, kType) ?: error("Serializer for element of type ${kType.render()} has not been found") } -fun BaseIrGenerator.findTypeSerializerOrContextUnchecked( - context: SerializationPluginContext, kType: IrType +fun BaseIrGenerator?.findTypeSerializerOrContextUnchecked( + context: SerializationBaseContext, kType: IrType ): IrClassSymbol? { val annotations = kType.annotations if (kType.isTypeParameter()) return null annotations.serializableWith()?.let { return it } - additionalSerializersInScopeOfCurrentFile[kType.classOrNull!! to kType.isNullable()]?.let { + this?.additionalSerializersInScopeOfCurrentFile?.get(kType.classOrNull!! to kType.isNullable())?.let { return it } if (kType.isMarkedNullable()) return findTypeSerializerOrContextUnchecked(context, kType.makeNotNull()) - if (kType.classOrNull in contextualKClassListInCurrentFile) return context.referenceClass(contextSerializerId) + if (this?.contextualKClassListInCurrentFile?.contains(kType.classOrNull) == true) return context.referenceClassId(contextSerializerId) return analyzeSpecialSerializers(context, annotations) ?: findTypeSerializer(context, kType) } fun analyzeSpecialSerializers( - context: SerializationPluginContext, + context: SerializationBaseContext, annotations: List ): IrClassSymbol? = when { annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || annotations.hasAnnotation(SerializationAnnotations.contextualOnPropertyFqName) -> - context.referenceClass(contextSerializerId) + context.referenceClassId(contextSerializerId) // can be annotation on type usage, e.g. List<@Polymorphic Any> annotations.hasAnnotation(SerializationAnnotations.polymorphicFqName) -> - context.referenceClass(polymorphicSerializerId) + context.referenceClassId(polymorphicSerializerId) else -> null } -fun findTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? { +fun findTypeSerializer(context: SerializationBaseContext, type: IrType): IrClassSymbol? { type.overridenSerializer?.let { return it } if (type.isTypeParameter()) return null - if (type.isArray()) return context.referenceClass(referenceArraySerializerId) - if (type.isGeneratedSerializableObject()) return context.referenceClass(objectSerializerId) + if (type.isArray()) return context.referenceClassId(referenceArraySerializerId) + if (type.isGeneratedSerializableObject()) return context.referenceClassId(objectSerializerId) val stdSer = findStandardKotlinTypeSerializer(context, type) // see if there is a standard serializer ?: findEnumTypeSerializer(context, type) if (stdSer != null) return stdSer - if (type.isInterface() && type.classOrNull?.owner?.isSealedSerializableInterface == false) return context.referenceClass( + if (type.isInterface() && type.classOrNull?.owner?.isSealedSerializableInterface == false) return context.referenceClassId( polymorphicSerializerId ) return type.classOrNull?.owner.classSerializer(context) // check for serializer defined on the type } -fun findEnumTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? { + +fun findEnumTypeSerializer(context: SerializationBaseContext, type: IrType): IrClassSymbol? { val classSymbol = type.classOrNull?.owner ?: return null return if (classSymbol.kind == ClassKind.ENUM_CLASS && !classSymbol.isEnumWithLegacyGeneratedSerializer(context)) - context.referenceClass(enumSerializerId) + context.referenceClassId(enumSerializerId) else null } -internal fun IrClass?.classSerializer(context: SerializationPluginContext): IrClassSymbol? = this?.let { +internal fun IrClass?.classSerializer(context: SerializationBaseContext): IrClassSymbol? = this?.let { // serializer annotation on class? serializableWith?.let { return it } // companion object serializer? @@ -139,7 +149,7 @@ internal fun IrClass?.classSerializer(context: SerializationPluginContext): IrCl return null } -internal fun IrClass.polymorphicSerializerIfApplicableAutomatically(context: SerializationPluginContext): IrClassSymbol? { +internal fun IrClass.polymorphicSerializerIfApplicableAutomatically(context: SerializationBaseContext): IrClassSymbol? { val serializer = when { kind == ClassKind.INTERFACE && modality == Modality.SEALED -> SpecialBuiltins.sealedSerializer kind == ClassKind.INTERFACE -> SpecialBuiltins.polymorphicSerializer @@ -170,7 +180,7 @@ internal val IrClass.serializerForClass: IrClassSymbol? get() = (annotations.findAnnotation(SerializationAnnotations.serializerAnnotationFqName) ?.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol -fun findStandardKotlinTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? { +fun findStandardKotlinTypeSerializer(context: SerializationBaseContext, type: IrType): IrClassSymbol? { val typeName = type.classFqName?.toString() val name = when (typeName) { "Z" -> if (type.isBoolean()) "BooleanSerializer" else null @@ -202,9 +212,9 @@ internal fun getSerializableClassByCompanion(companionClass: IrClass): IrClass? return classDescriptor } -fun BaseIrGenerator.allSealedSerializableSubclassesFor( +fun BaseIrGenerator?.allSealedSerializableSubclassesFor( irClass: IrClass, - context: SerializationPluginContext + context: SerializationBaseContext ): Pair, List> { assert(irClass.modality == Modality.SEALED) fun recursiveSealed(klass: IrClass): Collection { @@ -217,7 +227,7 @@ fun BaseIrGenerator.allSealedSerializableSubclassesFor( }.unzip() } -internal fun SerializationPluginContext.getSerializableClassDescriptorBySerializer(serializer: IrClass): IrClass? { +internal fun SerializationBaseContext.getSerializableClassDescriptorBySerializer(serializer: IrClass): IrClass? { val serializerForClass = serializer.serializerForClass if (serializerForClass != null) return serializerForClass.owner if (serializer.name !in setOf( @@ -230,22 +240,22 @@ internal fun SerializationPluginContext.getSerializableClassDescriptorBySerializ return classDescriptor } -fun SerializationPluginContext.getClassFromRuntimeOrNull(className: String, vararg packages: FqName): IrClassSymbol? { +fun SerializationBaseContext.getClassFromRuntimeOrNull(className: String, vararg packages: FqName): IrClassSymbol? { val listToSearch = if (packages.isEmpty()) SerializationPackages.allPublicPackages else packages.toList() for (pkg in listToSearch) { - referenceClass(ClassId(pkg, Name.identifier(className)))?.let { return it } + referenceClassId(ClassId(pkg, Name.identifier(className)))?.let { return it } } return null } -fun SerializationPluginContext.getClassFromRuntime(className: String, vararg packages: FqName): IrClassSymbol { +fun SerializationBaseContext.getClassFromRuntime(className: String, vararg packages: FqName): IrClassSymbol { return getClassFromRuntimeOrNull(className, *packages) ?: error( "Class $className wasn't found in ${packages.toList().ifEmpty { SerializationPackages.allPublicPackages }}. " + "Check that you have correct version of serialization runtime in classpath." ) } -fun SerializationPluginContext.getClassFromInternalSerializationPackage(className: String): IrClassSymbol = +fun SerializationBaseContext.getClassFromInternalSerializationPackage(className: String): IrClassSymbol = getClassFromRuntimeOrNull(className, SerializationPackages.internalPackageFqName) ?: error("Class $className wasn't found in ${SerializationPackages.internalPackageFqName}. Check that you have correct version of serialization runtime in classpath.") diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt index b04b10b395a..dbad1f2a8f4 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.context.ClassContext import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -34,6 +35,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import org.jetbrains.kotlinx.serialization.compiler.backend.common.* @@ -95,11 +97,11 @@ internal val serializationExceptionName = "kotlinx/serialization/$SERIAL_EXC" internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MISSING_FIELD_EXC" internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC" -private val annotationType = Type.getObjectType("java/lang/annotation/Annotation") -private val annotationArrayType = Type.getObjectType("[${annotationType.descriptor}") -private val doubleAnnotationArrayType = Type.getObjectType("[${annotationArrayType.descriptor}") -private val stringType = AsmTypes.JAVA_STRING_TYPE -private val stringArrayType = Type.getObjectType("[${stringType.descriptor}") +internal val annotationType = Type.getObjectType("java/lang/annotation/Annotation") +internal val annotationArrayType = Type.getObjectType("[${annotationType.descriptor}") +internal val doubleAnnotationArrayType = Type.getObjectType("[${annotationArrayType.descriptor}") +internal val stringType = AsmTypes.JAVA_STRING_TYPE +internal val stringArrayType = Type.getObjectType("[${stringType.descriptor}") internal val descriptorGetterName = JvmAbi.getterName(SERIAL_DESC_FIELD) internal val getLazyValueName = JvmAbi.getterName("value") @@ -256,7 +258,8 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance( genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null ): Boolean { return stackValueSerializerInstance( - expressionCodegen,codegen.typeMapper, + expressionCodegen, + codegen.typeMapper, module, kType, maybeSerializer, @@ -357,7 +360,7 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance( } else { fillArray(annotationType, annotations) { _, annotation -> val (annotationClass, args, consParams) = annotation - expressionCodegen?.generateSyntheticAnnotationOnStack(annotationClass, args, consParams) + expressionCodegen?.generateSyntheticAnnotationOnStack(annotationClass, args, consParams) ?: nop() } } } diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JvmSerializerIntrinsic.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JvmSerializerIntrinsic.kt deleted file mode 100644 index dc3e020158c..00000000000 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JvmSerializerIntrinsic.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlinx.serialization.compiler.backend.jvm - -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension -import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner -import org.jetbrains.kotlin.codegen.inline.newMethodNodeWithCorrectStackSize -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.ir.expressions.typeParametersCount -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext -import org.jetbrains.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator -import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen -import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContextUnchecked -import org.jetbrains.kotlinx.serialization.compiler.resolve.isSerializableObject -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter -import org.jetbrains.org.objectweb.asm.tree.InsnList -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode - -object JvmSerializerIntrinsic { - fun applyFunction(resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? { - val targetFunction = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return null - val isSerializerReifiedFunction = - targetFunction.fqNameSafe.asString() == "kotlinx.serialization.serializer" - && targetFunction.valueParameters.isEmpty() - && targetFunction.typeParametersCount == 1 - && targetFunction.dispatchReceiverParameter == null - && targetFunction.extensionReceiverParameter == null - if (!isSerializerReifiedFunction) return null - val typeArgument = - resolvedCall.typeArguments.entries.singleOrNull()?.value ?: error("serializer() function has exactly one type parameter") - return StackValue.functionCall(kSerializerType, targetFunction.returnType) { iv -> - generateSerializerForType(typeArgument, iv, c.typeMapper, c.codegen.typeSystem, module = c.codegen.state.module) - } - } - - fun applyPluginDefinedReifiedOperationMarker( - insn: MethodInsnNode, - instructions: InsnList, - type: KotlinType, - typeMapper: KotlinTypeMapper, - typeSystem: TypeSystemCommonBackendContext, - module: ModuleDescriptor - ): Int { - val newMethodNode = newMethodNodeWithCorrectStackSize { - generateSerializerForType(type, it, typeMapper, typeSystem, module) - } - - instructions.remove(insn.next) - instructions.insert(insn, newMethodNode.instructions) - - return newMethodNode.maxStack - } - - private fun InstructionAdapter.putReifyMarkerIfNeeded(type: KotlinType, typeSystem: TypeSystemCommonBackendContext): Boolean { - val typeDescriptor = (type as SimpleType).constructor.declarationDescriptor!! - if (typeDescriptor is TypeParameterDescriptor) { // need further reification - ReifiedTypeInliner.putReifiedOperationMarkerIfNeeded( - typeDescriptor, - false, - ReifiedTypeInliner.OperationKind.PLUGIN_DEFINED, - this, - typeSystem - ) - invokestatic("kotlinx/serialization/SerializersKt", "serializer", "()Lkotlinx/serialization/KSerializer;", false) - return true - } - return false - } - - private fun generateSerializerForType( - type: KotlinType, - adapter: InstructionAdapter, - typeMapper: KotlinTypeMapper, - typeSystem: TypeSystemCommonBackendContext, - module: ModuleDescriptor - ): Unit = with(adapter) { - if (putReifyMarkerIfNeeded(type, typeSystem)) return - val typeDescriptor = (type as SimpleType).constructor.declarationDescriptor!! as ClassDescriptor - - val serializerMethod = SerializableCompanionCodegen.findSerializerGetterOnCompanion(typeDescriptor) - if (serializerMethod != null) { - // fast path - val companionType = if (typeDescriptor.isSerializableObject) typeDescriptor else typeDescriptor.companionObjectDescriptor!! - StackValue.singleton(companionType, typeMapper).put(this) - val args = type.arguments.map { it.type } - args.forEach { generateSerializerForType(it, this, typeMapper, typeSystem, module) } - val signature = kSerializerType.descriptor.repeat(args.size) - invokevirtual( - typeMapper.mapType(companionType).internalName, - "serializer", - "(${signature})${kSerializerType.descriptor}", - false - ) - } else { - // More general path, including special ol built-in serializers for e.g. List - val emptyGenerator: AbstractSerialGenerator? = null // stub indicating we do not look into @UseSerializers to avoid confusion - val serializer = emptyGenerator.findTypeSerializerOrContextUnchecked(module, type) - emptyGenerator.stackValueSerializerInstance( - null, - typeMapper, - module, - type, - serializer, - this, - insertExceptionOnNoSerializer = true - ) { _, genericArg -> - assert(putReifyMarkerIfNeeded(genericArg, typeSystem)) - } - if (type.isMarkedNullable) wrapStackValueIntoNullableSerializer() - } - } -} \ No newline at end of file diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt index c969f103a14..8b9f8dd7839 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt @@ -8,11 +8,11 @@ package org.jetbrains.kotlinx.serialization.compiler.extensions import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.* import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.InsnList @@ -26,22 +26,6 @@ open class SerializationCodegenExtension @JvmOverloads constructor(val metadataP SerializableCompanionCodegenImpl.generateSerializableExtensions(codegen) } - override fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? { - return JvmSerializerIntrinsic.applyFunction(resolvedCall, c) - } - - override fun applyPluginDefinedReifiedOperationMarker( - insn: MethodInsnNode, - instructions: InsnList, - type: KotlinType, - asmType: Type, - typeMapper: KotlinTypeMapper, - typeSystem: TypeSystemCommonBackendContext, - module: ModuleDescriptor - ): Int { - return JvmSerializerIntrinsic.applyPluginDefinedReifiedOperationMarker(insn, instructions, type, typeMapper, typeSystem, module) - } - override val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean get() = false } \ No newline at end of file diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt index eabee0f3291..c5220b142ec 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt @@ -5,25 +5,34 @@ package org.jetbrains.kotlinx.serialization.compiler.extensions +import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.CompilationException import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 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.ir.IrElement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType 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.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.KSerializerDescriptorResolver import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages +import org.jetbrains.org.objectweb.asm.tree.InsnList +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode import java.util.concurrent.ConcurrentHashMap /** @@ -44,7 +53,7 @@ fun ClassLoweringPass.runOnFileInOrder(irFile: IrFile) { class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugin: SerializationDescriptorSerializerPlugin?) : - IrPluginContext by baseContext { + IrPluginContext by baseContext, SerializationBaseContext { lateinit var serialInfoImplJvmIrGenerator: SerialInfoImplJvmIrGenerator internal val copiedStaticWriteSelf: MutableMap = ConcurrentHashMap() @@ -63,7 +72,9 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi ) ).singleOrNull() - val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null + override val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null + + override fun referenceClassId(classId: ClassId): IrClassSymbol? = referenceClass(classId) } private inline fun IrClass.runPluginSafe(block: () -> Unit) { @@ -126,4 +137,25 @@ open class SerializationLoweringExtension @JvmOverloads constructor( moduleFragment.files.forEach(pass1::runOnFileInOrder) moduleFragment.files.forEach(pass2::runOnFileInOrder) } + + override fun retrieveIntrinsic(symbol: IrFunctionSymbol): Any? { + if (!SerializationJvmIrIntrinsicSupport.isSerializerReifiedFunction(symbol.owner)) return null + return SerializationJvmIrIntrinsicSupport.ReifiedSerializerMethod + } + + override fun applyPluginDefinedReifiedOperationMarker( + insn: MethodInsnNode, + instructions: InsnList, + type: IrType, + jvmBackendContext: BackendContext, + ): Int { + val ctx = jvmBackendContext as? JvmBackendContext ?: return -1 + return SerializationJvmIrIntrinsicSupport(ctx).applyPluginDefinedReifiedOperationMarker( + insn, + instructions, + type, + ) + } } + + diff --git a/plugins/kotlinx-serialization/testData/boxIr/intrinsicsBox.kt b/plugins/kotlinx-serialization/testData/boxIr/intrinsicsBox.kt new file mode 100644 index 00000000000..c0fdf0e1f73 --- /dev/null +++ b/plugins/kotlinx-serialization/testData/boxIr/intrinsicsBox.kt @@ -0,0 +1,62 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_STDLIB + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.internal.* +import kotlinx.serialization.descriptors.* + +@Serializable +class Simple(val firstName: String, val lastName: String) + +@Serializable +data class Box(val boxed: T) + +@Serializable +object SerializableObject {} + +inline fun getSer(): KSerializer { + return serializer() +} + +inline fun getBoxSer(): KSerializer> { + return serializer>() +} + +inline fun listSer(): KSerializer> { + return serializer>() +} + +fun SerialDescriptor.recursiveToString(): String { + return (0 until elementsCount).joinToString(", ", "$serialName(", ")") { i -> + getElementName(i) + ": " + getElementDescriptor(i).recursiveToString() + } +} + +fun assertHasSerializers(kSerializer: KSerializer<*>, list: List) { + var str = kSerializer.descriptor.recursiveToString() + for (name in list) { + if (name !in str) error("Not found $name in $str") + str = str.replaceBefore(name, "") + str = str.removePrefix(name) + } +} + +fun box(): String { + assertHasSerializers(serializer(), listOf("Simple")) + assertHasSerializers(getSer(), listOf("Simple")) + + assertHasSerializers(getSer>(), listOf("Box", "Simple")) + assertHasSerializers(getBoxSer(), listOf("Box", "Simple")) + + assertHasSerializers(listSer(), listOf("ArrayList", "Simple")) + assertHasSerializers(serializer>>(), listOf("Box", "ArrayList", "Simple")) + assertHasSerializers(listSer>>(), listOf("ArrayList", "Box", "ArrayList", "Simple")) + + assertHasSerializers(serializer(), listOf("Int")) + assertHasSerializers(serializer(), listOf("SerializableObject")) + assertHasSerializers(listSer>>(), listOf("ArrayList", "ArrayList", "Box", "Int")) + return "OK" +} \ No newline at end of file diff --git a/plugins/kotlinx-serialization/testData/codegen/Intrinsics.ir.txt b/plugins/kotlinx-serialization/testData/codegen/Intrinsics.ir.txt index 37bf68045ff..e86af1744f2 100644 --- a/plugins/kotlinx-serialization/testData/codegen/Intrinsics.ir.txt +++ b/plugins/kotlinx-serialization/testData/codegen/Intrinsics.ir.txt @@ -74,313 +74,116 @@ public final class IntrinsicsKt : java/lang/Object { public final static kotlinx.serialization.KSerializer listSer() public final static void test() { + GETSTATIC (Simple, Companion, LSimple$Companion;) + INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) + POP LABEL (L0) - LINENUMBER (28) - ICONST_0 - ISTORE (0) - LABEL (L1) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - LABEL (L2) - LINENUMBER (50) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (1) - LABEL (L3) - ICONST_0 - ISTORE (2) - LABEL (L4) - LINENUMBER (51) - ALOAD (1) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L5) - LINENUMBER (50) - NOP - LABEL (L6) LINENUMBER (29) ICONST_0 ISTORE (0) - LABEL (L7) - LINENUMBER (52) - ICONST_0 - ISTORE (1) - LABEL (L8) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - LABEL (L9) - LINENUMBER (53) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L10) - ICONST_0 - ISTORE (3) - LABEL (L11) - LINENUMBER (54) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L12) - LINENUMBER (53) + LABEL (L1) + GETSTATIC (Simple, Companion, LSimple$Companion;) + INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) + LABEL (L2) + LINENUMBER (44) NOP - LABEL (L13) - LINENUMBER (52) - NOP - LABEL (L14) + LABEL (L3) + POP + LABEL (L4) LINENUMBER (30) ICONST_0 ISTORE (0) - LABEL (L15) - LINENUMBER (55) - ICONST_0 - ISTORE (1) - LABEL (L16) - LDC (LBox;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L17) - LINENUMBER (56) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L18) - ICONST_0 - ISTORE (3) - LABEL (L19) - LINENUMBER (57) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L20) - LINENUMBER (56) + LABEL (L5) + GETSTATIC (Box, Companion, LBox$Companion;) + GETSTATIC (Simple, Companion, LSimple$Companion;) + INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) + INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) + LABEL (L6) + LINENUMBER (45) NOP - LABEL (L21) - LINENUMBER (55) - NOP - LABEL (L22) + LABEL (L7) + POP + LABEL (L8) LINENUMBER (31) ICONST_0 ISTORE (0) - LABEL (L23) - LINENUMBER (58) - ICONST_0 - ISTORE (1) - LABEL (L24) - LDC (LBox;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L25) - LINENUMBER (59) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L26) - ICONST_0 - ISTORE (3) - LABEL (L27) - LINENUMBER (60) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L28) - LINENUMBER (59) + LABEL (L9) + GETSTATIC (Box, Companion, LBox$Companion;) + GETSTATIC (Simple, Companion, LSimple$Companion;) + INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) + INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) + LABEL (L10) + LINENUMBER (46) NOP - LABEL (L29) - LINENUMBER (58) - NOP - LABEL (L30) + LABEL (L11) + POP + LABEL (L12) LINENUMBER (32) ICONST_0 ISTORE (0) - LABEL (L31) - LINENUMBER (61) - ICONST_0 - ISTORE (1) - LABEL (L32) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L33) - LINENUMBER (62) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L34) - ICONST_0 - ISTORE (3) - LABEL (L35) - LINENUMBER (63) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L36) - LINENUMBER (62) + LABEL (L13) + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + GETSTATIC (Simple, Companion, LSimple$Companion;) + INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + LABEL (L14) + LINENUMBER (47) NOP - LABEL (L37) - LINENUMBER (61) - NOP - LABEL (L38) - LINENUMBER (34) - ICONST_0 - ISTORE (0) - LABEL (L39) - LDC (LBox;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L40) - LINENUMBER (64) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (1) - LABEL (L41) - ICONST_0 - ISTORE (2) - LABEL (L42) - LINENUMBER (65) - ALOAD (1) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L43) - LINENUMBER (64) - NOP - LABEL (L44) + LABEL (L15) + POP + GETSTATIC (Box, Companion, LBox$Companion;) + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) + POP + LABEL (L16) LINENUMBER (36) ICONST_0 ISTORE (0) - LABEL (L45) - LINENUMBER (66) - ICONST_0 - ISTORE (1) - LABEL (L46) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LBox;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LSimple;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L47) - LINENUMBER (67) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L48) - ICONST_0 - ISTORE (3) - LABEL (L49) - LINENUMBER (68) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L50) - LINENUMBER (67) + LABEL (L17) + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + GETSTATIC (Box, Companion, LBox$Companion;) + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + LABEL (L18) + LINENUMBER (48) NOP - LABEL (L51) - LINENUMBER (66) - NOP - LABEL (L52) - LINENUMBER (38) - ICONST_0 - ISTORE (0) - LABEL (L53) - GETSTATIC (java/lang/Integer, TYPE, Ljava/lang/Class;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - LABEL (L54) - LINENUMBER (69) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (1) - LABEL (L55) - ICONST_0 - ISTORE (2) - LABEL (L56) - LINENUMBER (70) - ALOAD (1) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L57) - LINENUMBER (69) - NOP - LABEL (L58) - LINENUMBER (40) - ICONST_0 - ISTORE (0) - LABEL (L59) - LDC (LSerializableObject;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - LABEL (L60) - LINENUMBER (71) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (1) - LABEL (L61) - ICONST_0 - ISTORE (2) - LABEL (L62) - LINENUMBER (72) - ALOAD (1) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L63) - LINENUMBER (71) - NOP - LABEL (L64) + LABEL (L19) + POP + GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;) + POP + GETSTATIC (SerializableObject, INSTANCE, LSerializableObject;) + INVOKEVIRTUAL (SerializableObject, serializer, ()Lkotlinx/serialization/KSerializer;) + POP + LABEL (L20) LINENUMBER (42) ICONST_0 ISTORE (0) - LABEL (L65) - LINENUMBER (73) - ICONST_0 - ISTORE (1) - LABEL (L66) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (Ljava/util/List;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - LDC (LBox;) - GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) - GETSTATIC (java/lang/Integer, TYPE, Ljava/lang/Class;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) - INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) - LABEL (L67) - LINENUMBER (74) - INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) - ASTORE (2) - LABEL (L68) - ICONST_0 - ISTORE (3) - LABEL (L69) - LINENUMBER (75) - ALOAD (2) - LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) - LABEL (L70) - LINENUMBER (74) + LABEL (L21) + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + NEW (kotlinx/serialization/internal/ArrayListSerializer) + DUP + NEW (Box$$serializer) + DUP + GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;) + INVOKESPECIAL (Box$$serializer, , (Lkotlinx/serialization/KSerializer;)V) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + LABEL (L22) + LINENUMBER (49) NOP - LABEL (L71) - LINENUMBER (73) - NOP - LABEL (L72) + LABEL (L23) + POP + LABEL (L24) LINENUMBER (43) RETURN } @@ -462,4 +265,4 @@ public final class Simple : java/lang/Object { public final java.lang.String getLastName() public final static void write$Self(Simple self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) -} +} \ No newline at end of file diff --git a/plugins/kotlinx-serialization/testData/codegen/Intrinsics.txt b/plugins/kotlinx-serialization/testData/codegen/Intrinsics.txt index f6e7083bbfe..6ea07e8a4f9 100644 --- a/plugins/kotlinx-serialization/testData/codegen/Intrinsics.txt +++ b/plugins/kotlinx-serialization/testData/codegen/Intrinsics.txt @@ -70,114 +70,311 @@ public final class IntrinsicsKt : java/lang/Object { public final static void test() { LABEL (L0) LINENUMBER (28) - GETSTATIC (Simple, Companion, LSimple$Companion;) - INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) - POP + ICONST_0 + ISTORE (0) LABEL (L1) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + LABEL (L2) + LINENUMBER (50) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (1) + LABEL (L3) + ICONST_0 + ISTORE (2) + LABEL (L4) + LINENUMBER (51) + ALOAD (1) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L5) + LINENUMBER (50) + NOP + LABEL (L6) LINENUMBER (29) ICONST_0 ISTORE (0) - LABEL (L2) - LINENUMBER (44) - GETSTATIC (Simple, Companion, LSimple$Companion;) - INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) - LABEL (L3) - POP - LABEL (L4) + LABEL (L7) + LINENUMBER (52) + ICONST_0 + ISTORE (1) + LABEL (L8) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + LABEL (L9) + LINENUMBER (53) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L10) + ICONST_0 + ISTORE (3) + LABEL (L11) + LINENUMBER (54) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L12) + LINENUMBER (53) + NOP + LABEL (L13) + LINENUMBER (52) + NOP + LABEL (L14) LINENUMBER (30) ICONST_0 ISTORE (0) - LABEL (L5) - LINENUMBER (45) - GETSTATIC (Box, Companion, LBox$Companion;) - GETSTATIC (Simple, Companion, LSimple$Companion;) - INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) - INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) - LABEL (L6) - POP - LABEL (L7) + LABEL (L15) + LINENUMBER (55) + ICONST_0 + ISTORE (1) + LABEL (L16) + LDC (LBox;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L17) + LINENUMBER (56) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L18) + ICONST_0 + ISTORE (3) + LABEL (L19) + LINENUMBER (57) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L20) + LINENUMBER (56) + NOP + LABEL (L21) + LINENUMBER (55) + NOP + LABEL (L22) LINENUMBER (31) ICONST_0 ISTORE (0) - LABEL (L8) - LINENUMBER (46) - GETSTATIC (Box, Companion, LBox$Companion;) - GETSTATIC (Simple, Companion, LSimple$Companion;) - INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) - INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) - LABEL (L9) - POP - LABEL (L10) + LABEL (L23) + LINENUMBER (58) + ICONST_0 + ISTORE (1) + LABEL (L24) + LDC (LBox;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L25) + LINENUMBER (59) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L26) + ICONST_0 + ISTORE (3) + LABEL (L27) + LINENUMBER (60) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L28) + LINENUMBER (59) + NOP + LABEL (L29) + LINENUMBER (58) + NOP + LABEL (L30) LINENUMBER (32) ICONST_0 ISTORE (0) - LABEL (L11) - LINENUMBER (47) - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - GETSTATIC (Simple, Companion, LSimple$Companion;) - INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - LABEL (L12) - POP - LABEL (L13) + LABEL (L31) + LINENUMBER (61) + ICONST_0 + ISTORE (1) + LABEL (L32) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L33) + LINENUMBER (62) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L34) + ICONST_0 + ISTORE (3) + LABEL (L35) + LINENUMBER (63) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L36) + LINENUMBER (62) + NOP + LABEL (L37) + LINENUMBER (61) + NOP + LABEL (L38) LINENUMBER (34) - GETSTATIC (Box, Companion, LBox$Companion;) - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;) - CHECKCAST (kotlinx/serialization/KSerializer) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) - POP - LABEL (L14) + ICONST_0 + ISTORE (0) + LABEL (L39) + LDC (LBox;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L40) + LINENUMBER (64) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (1) + LABEL (L41) + ICONST_0 + ISTORE (2) + LABEL (L42) + LINENUMBER (65) + ALOAD (1) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L43) + LINENUMBER (64) + NOP + LABEL (L44) LINENUMBER (36) ICONST_0 ISTORE (0) - LABEL (L15) - LINENUMBER (48) - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - GETSTATIC (Box, Companion, LBox$Companion;) - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;) - CHECKCAST (kotlinx/serialization/KSerializer) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - LABEL (L16) - POP - LABEL (L17) + LABEL (L45) + LINENUMBER (66) + ICONST_0 + ISTORE (1) + LABEL (L46) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LBox;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LSimple;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L47) + LINENUMBER (67) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L48) + ICONST_0 + ISTORE (3) + LABEL (L49) + LINENUMBER (68) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L50) + LINENUMBER (67) + NOP + LABEL (L51) + LINENUMBER (66) + NOP + LABEL (L52) LINENUMBER (38) - GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;) - CHECKCAST (kotlinx/serialization/KSerializer) - POP - LABEL (L18) + ICONST_0 + ISTORE (0) + LABEL (L53) + GETSTATIC (java/lang/Integer, TYPE, Ljava/lang/Class;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + LABEL (L54) + LINENUMBER (69) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (1) + LABEL (L55) + ICONST_0 + ISTORE (2) + LABEL (L56) + LINENUMBER (70) + ALOAD (1) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L57) + LINENUMBER (69) + NOP + LABEL (L58) LINENUMBER (40) - GETSTATIC (SerializableObject, INSTANCE, LSerializableObject;) - INVOKEVIRTUAL (SerializableObject, serializer, ()Lkotlinx/serialization/KSerializer;) - POP - LABEL (L19) + ICONST_0 + ISTORE (0) + LABEL (L59) + LDC (LSerializableObject;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + LABEL (L60) + LINENUMBER (71) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (1) + LABEL (L61) + ICONST_0 + ISTORE (2) + LABEL (L62) + LINENUMBER (72) + ALOAD (1) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L63) + LINENUMBER (71) + NOP + LABEL (L64) LINENUMBER (42) ICONST_0 ISTORE (0) - LABEL (L20) - LINENUMBER (49) - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - NEW (kotlinx/serialization/internal/ArrayListSerializer) - DUP - NEW (Box$$serializer) - DUP - GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;) - CHECKCAST (kotlinx/serialization/KSerializer) - INVOKESPECIAL (Box$$serializer, , (Lkotlinx/serialization/KSerializer;)V) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - LABEL (L21) - POP - LABEL (L22) + LABEL (L65) + LINENUMBER (73) + ICONST_0 + ISTORE (1) + LABEL (L66) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (Ljava/util/List;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + LDC (LBox;) + GETSTATIC (kotlin/reflect/KTypeProjection, Companion, Lkotlin/reflect/KTypeProjection$Companion;) + GETSTATIC (java/lang/Integer, TYPE, Ljava/lang/Class;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + INVOKEVIRTUAL (kotlin/reflect/KTypeProjection$Companion, invariant, (Lkotlin/reflect/KType;)Lkotlin/reflect/KTypeProjection;) + INVOKESTATIC (kotlin/jvm/internal/Reflection, typeOf, (Ljava/lang/Class;Lkotlin/reflect/KTypeProjection;)Lkotlin/reflect/KType;) + LABEL (L67) + LINENUMBER (74) + INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;) + ASTORE (2) + LABEL (L68) + ICONST_0 + ISTORE (3) + LABEL (L69) + LINENUMBER (75) + ALOAD (2) + LDC (null cannot be cast to non-null type kotlinx.serialization.KSerializer) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNull, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L70) + LINENUMBER (74) + NOP + LABEL (L71) + LINENUMBER (73) + NOP + LABEL (L72) LINENUMBER (43) RETURN } @@ -257,4 +454,4 @@ public final class Simple : java/lang/Object { public final java.lang.String getLastName() public final static void write$Self(Simple self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) -} \ No newline at end of file +} diff --git a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java index 0ffe0a60dc9..b054f5e735a 100644 --- a/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java +++ b/plugins/kotlinx-serialization/tests-gen/org/jetbrains/kotlinx/serialization/runners/SerializationIrBoxTestGenerated.java @@ -55,6 +55,12 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT runTest("plugins/kotlinx-serialization/testData/boxIr/inlineClasses.kt"); } + @Test + @TestMetadata("intrinsicsBox.kt") + public void testIntrinsicsBox() throws Exception { + runTest("plugins/kotlinx-serialization/testData/boxIr/intrinsicsBox.kt"); + } + @Test @TestMetadata("metaSerializable.kt") public void testMetaSerializable() throws Exception {