Introduce support for plugin-defined intrinsics in old JVM backend:
(Old is created first because all intrinsics emit bytecode anyway) Provide intrinsic for serializer<T>() function so it won't invoke typeOf() construction and KType->KSerializer conversion making it fast and truly reflectionless Add support for recalculating stack size in plugin-defined intrinsics since it is needed for correct work: Unify method for recalculating stack size with existing typeOf intrinsic Add testdata for IR for future intrinsic in IR
This commit is contained in:
+19
-9
@@ -12,6 +12,9 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isSerializableObject
|
||||
|
||||
abstract class SerializableCompanionCodegen(
|
||||
protected val companionDescriptor: ClassDescriptor,
|
||||
@@ -20,15 +23,7 @@ abstract class SerializableCompanionCodegen(
|
||||
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
|
||||
|
||||
open fun getSerializerGetterDescriptor(): FunctionDescriptor {
|
||||
return companionDescriptor.unsubstitutedMemberScope.getContributedFunctions(
|
||||
SERIALIZER_PROVIDER_NAME,
|
||||
NoLookupLocation.FROM_BACKEND
|
||||
).firstOrNull {
|
||||
it.valueParameters.size == serializableDescriptor.declaredTypeParameters.size
|
||||
&& it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
&& it.valueParameters.all { p -> isKSerializer(p.type) }
|
||||
&& it.returnType != null && isKSerializer(it.returnType)
|
||||
} ?: throw IllegalStateException(
|
||||
return findSerializerGetterOnCompanion(serializableDescriptor) ?: throw IllegalStateException(
|
||||
"Can't find synthesized 'Companion.serializer()' function to generate, " +
|
||||
"probably clash with user-defined function has occurred"
|
||||
)
|
||||
@@ -52,4 +47,19 @@ abstract class SerializableCompanionCodegen(
|
||||
protected open fun generateLazySerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||
generateSerializerGetter(methodDescriptor)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun findSerializerGetterOnCompanion(serializableDescriptor: ClassDescriptor): FunctionDescriptor? {
|
||||
val companionObjectDesc = if (serializableDescriptor.isSerializableObject) serializableDescriptor else serializableDescriptor.companionObjectDescriptor
|
||||
return companionObjectDesc?.unsubstitutedMemberScope?.getContributedFunctions(
|
||||
SERIALIZER_PROVIDER_NAME,
|
||||
NoLookupLocation.FROM_BACKEND
|
||||
)?.firstOrNull {
|
||||
it.valueParameters.size == serializableDescriptor.declaredTypeParameters.size
|
||||
&& it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
&& it.valueParameters.all { p -> isKSerializer(p.type) }
|
||||
&& it.returnType != null && isKSerializer(it.returnType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
-29
@@ -8,7 +8,9 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
||||
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.descriptors.*
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
@@ -247,56 +249,88 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
||||
expressionCodegen: ExpressionCodegen, codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||
iv: InstructionAdapter?,
|
||||
genericIndex: Int? = null,
|
||||
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
||||
): Boolean {
|
||||
return stackValueSerializerInstance(
|
||||
expressionCodegen,codegen.typeMapper,
|
||||
module,
|
||||
kType,
|
||||
maybeSerializer,
|
||||
iv,
|
||||
genericIndex,
|
||||
false,
|
||||
genericSerializerFieldGetter
|
||||
)
|
||||
}
|
||||
|
||||
// returns false is cannot not use serializer
|
||||
// use iv == null to check only (do not emit serializer onto stack)
|
||||
internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCodegen: ExpressionCodegen, classCodegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||
iv: InstructionAdapter?,
|
||||
genericIndex: Int? = null,
|
||||
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
||||
internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
||||
expressionCodegen: ExpressionCodegen?, typeMapper: KotlinTypeMapper, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||
iv: InstructionAdapter?,
|
||||
genericIndex: Int? = null,
|
||||
insertExceptionOnNoSerializer: Boolean = false,
|
||||
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null,
|
||||
): Boolean {
|
||||
if (maybeSerializer == null && genericIndex != null) {
|
||||
// get field from serializer object
|
||||
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex, kType) }
|
||||
return true
|
||||
}
|
||||
val serializer = maybeSerializer ?: return false
|
||||
val serializer = maybeSerializer ?: run {
|
||||
if (insertExceptionOnNoSerializer) iv?.apply {
|
||||
aconst(kType.getJetTypeFqName(false))
|
||||
invokestatic(
|
||||
"kotlinx/serialization/SerializersKt",
|
||||
"noCompiledSerializer",
|
||||
"(Ljava/lang/String;)Lkotlinx/serialization/KSerializer;",
|
||||
false
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (serializer.kind == ClassKind.OBJECT) {
|
||||
// singleton serializer -- just get it
|
||||
if (iv != null)
|
||||
StackValue.singleton(serializer, classCodegen.typeMapper).put(kSerializerType, iv)
|
||||
StackValue.singleton(serializer, typeMapper).put(kSerializerType, iv)
|
||||
return true
|
||||
}
|
||||
// serializer is not singleton object and shall be instantiated
|
||||
val argSerializers = kType.arguments.map { projection ->
|
||||
// bail out from stackValueSerializerInstance if any type argument is not serializable
|
||||
// check if any type argument is not serializable
|
||||
val argType = projection.type
|
||||
val argSerializer = if (argType.isTypeParameter()) null else {
|
||||
findTypeSerializerOrContext(module, argType, sourceElement = classCodegen.descriptor.findPsi())
|
||||
?: return false
|
||||
}
|
||||
val argSerializer =
|
||||
if (argType.isTypeParameter()) null else findTypeSerializerOrContextUnchecked(module, argType)
|
||||
// check if it can be properly serialized with its args recursively
|
||||
if (!stackValueSerializerInstance(
|
||||
expressionCodegen,
|
||||
classCodegen,
|
||||
typeMapper,
|
||||
module,
|
||||
argType,
|
||||
argSerializer,
|
||||
null,
|
||||
argType.genericIndex,
|
||||
insertExceptionOnNoSerializer = false,
|
||||
genericSerializerFieldGetter
|
||||
)
|
||||
)
|
||||
return false
|
||||
) {
|
||||
// bail out only if we do not need to insert exception
|
||||
if (!insertExceptionOnNoSerializer) return false
|
||||
}
|
||||
Pair(argType, argSerializer)
|
||||
}
|
||||
// new serializer if needed
|
||||
iv?.apply {
|
||||
val serializerType = classCodegen.typeMapper.mapClass(serializer)
|
||||
val serializerType = typeMapper.mapClass(serializer)
|
||||
val classDescriptor = kType.toClassDescriptor!!
|
||||
if (serializer.classId == enumSerializerId && !classDescriptor.useGeneratedEnumSerializer) {
|
||||
// runtime contains enum serializer factory functions
|
||||
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||
val enumJavaType = typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||
val serialName = classDescriptor.serialName()
|
||||
|
||||
if (classDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||
@@ -323,7 +357,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
} else {
|
||||
fillArray(annotationType, annotations) { _, annotation ->
|
||||
val (annotationClass, args, consParams) = annotation
|
||||
expressionCodegen.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||
expressionCodegen?.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,14 +395,15 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
assert(
|
||||
stackValueSerializerInstance(
|
||||
expressionCodegen,
|
||||
classCodegen,
|
||||
typeMapper,
|
||||
module,
|
||||
argType,
|
||||
argSerializer,
|
||||
this,
|
||||
argType.genericIndex,
|
||||
insertExceptionOnNoSerializer,
|
||||
genericSerializerFieldGetter
|
||||
)
|
||||
) || insertExceptionOnNoSerializer
|
||||
)
|
||||
// wrap into nullable serializer if argType is nullable
|
||||
if (argType.isMarkedNullable) wrapStackValueIntoNullableSerializer()
|
||||
@@ -381,16 +416,16 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
// support legacy serializer instantiation by constructor for old runtimes
|
||||
aconst(serialName)
|
||||
signature.append("Ljava/lang/String;")
|
||||
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||
val enumJavaType = typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||
invokestatic(enumJavaType.internalName, "values","()[${enumJavaType.descriptor}", false)
|
||||
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(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
aconst(typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||
if (serializer.classId == contextSerializerId && serializer.constructors.any { it.valueParameters.size == 3 }) {
|
||||
@@ -410,7 +445,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
}
|
||||
referenceArraySerializerId -> {
|
||||
// a special way to instantiate reference array serializer -- need an element KClass reference
|
||||
aconst(classCodegen.typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
aconst(typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||
// Reference array serializer still needs serializer for its argument type
|
||||
@@ -419,13 +454,13 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
sealedSerializerId -> {
|
||||
aconst(serialName)
|
||||
signature.append("Ljava/lang/String;")
|
||||
aconst(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
aconst(typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
||||
// KClasses vararg
|
||||
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
||||
aconst(classCodegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
aconst(typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||
}
|
||||
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
||||
@@ -435,7 +470,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
assert(
|
||||
stackValueSerializerInstance(
|
||||
expressionCodegen,
|
||||
classCodegen,
|
||||
typeMapper,
|
||||
module,
|
||||
argType,
|
||||
argSerializer,
|
||||
@@ -446,11 +481,12 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
assert(
|
||||
stackValueSerializerInstance(
|
||||
expressionCodegen,
|
||||
classCodegen,
|
||||
typeMapper,
|
||||
module,
|
||||
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
||||
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
||||
this
|
||||
this,
|
||||
insertExceptionOnNoSerializer = insertExceptionOnNoSerializer
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -462,7 +498,7 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
objectSerializerId -> {
|
||||
aconst(serialName)
|
||||
signature.append("Ljava/lang/String;")
|
||||
StackValue.singleton(kType.toClassDescriptor!!, classCodegen.typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
||||
StackValue.singleton(kType.toClassDescriptor!!, typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
||||
signature.append("Ljava/lang/Object;")
|
||||
}
|
||||
// all serializers get arguments with serializers of their generic types
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-17
@@ -1,27 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2021 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.extensions
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerialInfoCodegenImpl
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCodegenImpl
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCompanionCodegenImpl
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
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.kotlinx.serialization.compiler.backend.jvm.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||
|
||||
open class SerializationCodegenExtension @JvmOverloads constructor(val metadataPlugin: SerializationDescriptorSerializerPlugin? = null) : ExpressionCodegenExtension {
|
||||
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
|
||||
@@ -31,6 +26,22 @@ 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
|
||||
}
|
||||
Reference in New Issue
Block a user