Determine more precise conditions when to enable serialization intrinsic
Disable it if we do not have required `noCompiledSerializer` function in runtime. Leave it enabled in tests. Rollback some changes for old backend as it is unsupported now.
This commit is contained in:
-7
@@ -8,17 +8,10 @@ package org.jetbrains.kotlin.codegen.extensions
|
|||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
|
|
||||||
interface ExpressionCodegenExtension {
|
interface ExpressionCodegenExtension {
|
||||||
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
|
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class PsiInlineCodegen(
|
|||||||
) : InlineCodegen<ExpressionCodegen>(
|
) : InlineCodegen<ExpressionCodegen>(
|
||||||
codegen, state, signature, typeParameterMappings, sourceCompiler,
|
codegen, state, signature, typeParameterMappings, sourceCompiler,
|
||||||
ReifiedTypeInliner(
|
ReifiedTypeInliner(
|
||||||
typeParameterMappings, PsiInlineIntrinsicsSupport(state, reportErrorsOn, codegen.typeSystem), codegen.typeSystem,
|
typeParameterMappings, PsiInlineIntrinsicsSupport(state, reportErrorsOn), codegen.typeSystem,
|
||||||
state.languageVersionSettings, state.unifiedNullChecks
|
state.languageVersionSettings, state.unifiedNullChecks
|
||||||
),
|
),
|
||||||
), CallGenerator {
|
), CallGenerator {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
@@ -20,22 +19,16 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.TYPEOF_SUSPEND_TYPE
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
|
||||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.Type.INT_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.Type.VOID_TYPE
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
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 PsiInlineIntrinsicsSupport(
|
class PsiInlineIntrinsicsSupport(
|
||||||
override val state: GenerationState,
|
override val state: GenerationState,
|
||||||
private val reportErrorsOn: KtElement,
|
private val reportErrorsOn: KtElement,
|
||||||
private val typeSystem: TypeSystemCommonBackendContext
|
|
||||||
) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
|
) : ReifiedTypeInliner.IntrinsicsSupport<KotlinType> {
|
||||||
private val pluginExtensions = ExpressionCodegenExtension.getInstances(state.project)
|
|
||||||
|
|
||||||
override fun putClassInstance(v: InstructionAdapter, type: KotlinType) {
|
override fun putClassInstance(v: InstructionAdapter, type: KotlinType) {
|
||||||
DescriptorAsmUtil.putJavaLangClassInstance(v, state.typeMapper.mapType(type), type, state.typeMapper)
|
DescriptorAsmUtil.putJavaLangClassInstance(v, state.typeMapper.mapType(type), type, state.typeMapper)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
fun reportSuspendTypeUnsupported()
|
fun reportSuspendTypeUnsupported()
|
||||||
fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name)
|
fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name)
|
||||||
|
|
||||||
fun rewritePluginDefinedOperationMarker(v: InstructionAdapter, next: AbstractInsnNode, instructions: InsnList, type: KT): Boolean =
|
fun rewritePluginDefinedOperationMarker(v: InstructionAdapter, stubConstNull: AbstractInsnNode, instructions: InsnList, type: KT): Boolean =
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.extensions
|
package org.jetbrains.kotlin.backend.common.extensions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||||
@@ -17,7 +18,7 @@ interface IrGenerationExtension : IrDeserializer.IrLinkerExtension {
|
|||||||
|
|
||||||
fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext)
|
fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext)
|
||||||
|
|
||||||
fun getPlatformIntrinsicExtension(): IrIntrinsicExtension? = null
|
fun getPlatformIntrinsicExtension(backendContext: BackendContext): IrIntrinsicExtension? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-3
@@ -44,7 +44,7 @@ class IrInlineIntrinsicsSupport(
|
|||||||
get() = classCodegen.context.state
|
get() = classCodegen.context.state
|
||||||
|
|
||||||
private val pluginExtensions = IrGenerationExtension.getInstances(classCodegen.context.state.project)
|
private val pluginExtensions = IrGenerationExtension.getInstances(classCodegen.context.state.project)
|
||||||
.mapNotNull { it.getPlatformIntrinsicExtension() as? JvmIrIntrinsicExtension }
|
.mapNotNull { it.getPlatformIntrinsicExtension(classCodegen.context) as? JvmIrIntrinsicExtension }
|
||||||
|
|
||||||
override fun putClassInstance(v: InstructionAdapter, type: IrType) {
|
override fun putClassInstance(v: InstructionAdapter, type: IrType) {
|
||||||
ExpressionCodegen.generateClassInstance(v, type, classCodegen.typeMapper, wrapPrimitives = false)
|
ExpressionCodegen.generateClassInstance(v, type, classCodegen.typeMapper, wrapPrimitives = false)
|
||||||
@@ -127,7 +127,7 @@ class IrInlineIntrinsicsSupport(
|
|||||||
.report(JvmBackendErrors.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND, typeParameterName.asString())
|
.report(JvmBackendErrors.TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND, typeParameterName.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun rewritePluginDefinedOperationMarker(v: InstructionAdapter, next: AbstractInsnNode, instructions: InsnList, type: IrType): Boolean {
|
override fun rewritePluginDefinedOperationMarker(v: InstructionAdapter, stubConstNull: AbstractInsnNode, instructions: InsnList, type: IrType): Boolean {
|
||||||
return pluginExtensions.any { it.rewritePluginDefinedOperationMarker(v, next, instructions, type, classCodegen.context) }
|
return pluginExtensions.any { it.rewritePluginDefinedOperationMarker(v, stubConstNull, instructions, type) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
@@ -20,12 +19,13 @@ interface JvmIrIntrinsicExtension : IrIntrinsicExtension {
|
|||||||
/**
|
/**
|
||||||
* Should return `true` if marker was processed.
|
* Should return `true` if marker was processed.
|
||||||
* If this method returns `false`, a regular `TYPE_OF` intrinsic would be inserted.
|
* If this method returns `false`, a regular `TYPE_OF` intrinsic would be inserted.
|
||||||
|
*
|
||||||
|
* This is plugin's responsibility to remove any calls to MagicApiIntrinsics.voidMagicApiCall and its arguments.
|
||||||
*/
|
*/
|
||||||
fun rewritePluginDefinedOperationMarker(
|
fun rewritePluginDefinedOperationMarker(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
next: AbstractInsnNode,
|
stubConstNull: AbstractInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
type: IrType,
|
type: IrType
|
||||||
jvmBackendContext: JvmBackendContext
|
|
||||||
): Boolean
|
): Boolean
|
||||||
}
|
}
|
||||||
+1
-1
@@ -288,7 +288,7 @@ open class JvmIrCodegenFactory(
|
|||||||
context.localDeclarationsLoweringData = mutableMapOf()
|
context.localDeclarationsLoweringData = mutableMapOf()
|
||||||
}
|
}
|
||||||
val generationExtensions = IrGenerationExtension.getInstances(state.project)
|
val generationExtensions = IrGenerationExtension.getInstances(state.project)
|
||||||
.mapNotNull { it.getPlatformIntrinsicExtension() as? JvmIrIntrinsicExtension }
|
.mapNotNull { it.getPlatformIntrinsicExtension(context) as? JvmIrIntrinsicExtension }
|
||||||
val intrinsics by lazy { IrIntrinsicMethods(irModuleFragment.irBuiltins, context.ir.symbols) }
|
val intrinsics by lazy { IrIntrinsicMethods(irModuleFragment.irBuiltins, context.ir.symbols) }
|
||||||
context.getIntrinsic = { symbol: IrFunctionSymbol ->
|
context.getIntrinsic = { symbol: IrFunctionSymbol ->
|
||||||
intrinsics.getIntrinsic(symbol) ?: generationExtensions.firstNotNullOfOrNull { it.getIntrinsic(symbol) }
|
intrinsics.getIntrinsic(symbol) ?: generationExtensions.firstNotNullOfOrNull { it.getIntrinsic(symbol) }
|
||||||
|
|||||||
+40
-37
@@ -19,9 +19,9 @@ import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIn
|
|||||||
import org.jetbrains.kotlin.config.ApiVersion
|
import org.jetbrains.kotlin.config.ApiVersion
|
||||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
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.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
@@ -56,7 +56,7 @@ import org.jetbrains.org.objectweb.asm.tree.InsnList
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
||||||
|
|
||||||
class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContext) : SerializationBaseContext {
|
class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContext) : SerializationBaseContext, JvmIrIntrinsicExtension {
|
||||||
sealed class IntrinsicType(val methodDescriptor: String) {
|
sealed class IntrinsicType(val methodDescriptor: String) {
|
||||||
object Simple : IntrinsicType(stubCallDescriptor)
|
object Simple : IntrinsicType(stubCallDescriptor)
|
||||||
|
|
||||||
@@ -69,35 +69,7 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
inner class ReifiedSerializerMethod(private val withModule: Boolean) : IntrinsicMethod() {
|
||||||
fun intrinsicForMethod(method: IrFunction): IntrinsicMethod? {
|
|
||||||
if (method.fqNameWhenAvailable?.asString() != "kotlinx.serialization.SerializersKt.serializer"
|
|
||||||
|| method.dispatchReceiverParameter != null
|
|
||||||
|| method.typeParameters.size != 1
|
|
||||||
|| method.valueParameters.isNotEmpty()
|
|
||||||
) return null
|
|
||||||
val receiver = method.extensionReceiverParameter
|
|
||||||
return if (receiver == null)
|
|
||||||
ReifiedSerializerMethod(withModule = false)
|
|
||||||
else if (receiver.type.classFqName?.asString() == "kotlinx.serialization.modules.SerializersModule")
|
|
||||||
ReifiedSerializerMethod(withModule = true)
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
|
|
||||||
val serializersModuleType: Type = Type.getObjectType("kotlinx/serialization/modules/SerializersModule")
|
|
||||||
val kTypeType: Type = AsmTypes.K_TYPE
|
|
||||||
|
|
||||||
val stubCallDescriptorWithModule = "(${serializersModuleType.descriptor}${kTypeType.descriptor})${kSerializerType.descriptor}"
|
|
||||||
val stubCallDescriptor = "(${kTypeType.descriptor})${kSerializerType.descriptor}"
|
|
||||||
const val serializersKtInternalName = "kotlinx/serialization/SerializersKt"
|
|
||||||
const val callMethodName = "serializer"
|
|
||||||
const val noCompiledSerializerMethodName = "noCompiledSerializer"
|
|
||||||
|
|
||||||
const val magicMarkerStringPrefix = "kotlinx.serialization.serializer."
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReifiedSerializerMethod(private val withModule: Boolean) : IntrinsicMethod() {
|
|
||||||
override fun invoke(
|
override fun invoke(
|
||||||
expression: IrFunctionAccessExpression,
|
expression: IrFunctionAccessExpression,
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
@@ -115,7 +87,7 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
codegen.markLineNumber(expression)
|
codegen.markLineNumber(expression)
|
||||||
IntrinsicType.Simple
|
IntrinsicType.Simple
|
||||||
}
|
}
|
||||||
SerializationJvmIrIntrinsicSupport(codegen.context).generateSerializerForType(
|
generateSerializerForType(
|
||||||
argument,
|
argument,
|
||||||
mv,
|
mv,
|
||||||
intrinsicType
|
intrinsicType
|
||||||
@@ -128,6 +100,35 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val serializersModuleType: Type = Type.getObjectType("kotlinx/serialization/modules/SerializersModule")
|
||||||
|
val kTypeType: Type = AsmTypes.K_TYPE
|
||||||
|
|
||||||
|
val stubCallDescriptorWithModule = "(${serializersModuleType.descriptor}${kTypeType.descriptor})${kSerializerType.descriptor}"
|
||||||
|
val stubCallDescriptor = "(${kTypeType.descriptor})${kSerializerType.descriptor}"
|
||||||
|
const val serializersKtInternalName = "kotlinx/serialization/SerializersKt"
|
||||||
|
const val callMethodName = "serializer"
|
||||||
|
const val noCompiledSerializerMethodName = "noCompiledSerializer"
|
||||||
|
|
||||||
|
const val magicMarkerStringPrefix = "kotlinx.serialization.serializer."
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? {
|
||||||
|
val method = symbol.owner
|
||||||
|
if (method.fqNameWhenAvailable?.asString() != "kotlinx.serialization.SerializersKt.serializer"
|
||||||
|
|| method.dispatchReceiverParameter != null
|
||||||
|
|| method.typeParameters.size != 1
|
||||||
|
|| method.valueParameters.isNotEmpty()
|
||||||
|
) return null
|
||||||
|
val receiver = method.extensionReceiverParameter
|
||||||
|
return if (receiver == null)
|
||||||
|
ReifiedSerializerMethod(withModule = false)
|
||||||
|
else if (receiver.type.classFqName?.asString() == "kotlinx.serialization.modules.SerializersModule")
|
||||||
|
ReifiedSerializerMethod(withModule = true)
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private val emptyGenerator: BaseIrGenerator? = null
|
private val emptyGenerator: BaseIrGenerator? = null
|
||||||
private val module = jvmBackendContext.state.module
|
private val module = jvmBackendContext.state.module
|
||||||
@@ -143,14 +144,16 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
return module.findClassAcrossModuleDependencies(classId)?.let { jvmBackendContext.referenceClass(it) }
|
return module.findClassAcrossModuleDependencies(classId)?.let { jvmBackendContext.referenceClass(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val currentVersion = VersionReader.getVersionsForCurrentModuleFromTrace(module, jvmBackendContext.state.bindingTrace)
|
private val currentVersion by lazy {
|
||||||
?.implementationVersion
|
VersionReader.getVersionsForCurrentModuleFromTrace(module, jvmBackendContext.state.bindingTrace)
|
||||||
|
?.implementationVersion
|
||||||
|
}
|
||||||
|
|
||||||
override val runtimeHasEnumSerializerFactoryFunctions: Boolean
|
override val runtimeHasEnumSerializerFactoryFunctions: Boolean
|
||||||
get() = currentVersion != null && currentVersion > ApiVersion.parse("1.4.0")!!
|
get() = currentVersion != null && currentVersion!! > ApiVersion.parse("1.4.0")!!
|
||||||
|
|
||||||
private val hasNewContextSerializerSignature: Boolean
|
private val hasNewContextSerializerSignature: Boolean
|
||||||
get() = currentVersion != null && currentVersion >= ApiVersion.parse("1.2.0")!!
|
get() = currentVersion != null && currentVersion!! >= ApiVersion.parse("1.2.0")!!
|
||||||
|
|
||||||
private fun findTypeSerializerOrContext(argType: IrType): IrClassSymbol? =
|
private fun findTypeSerializerOrContext(argType: IrType): IrClassSymbol? =
|
||||||
emptyGenerator.findTypeSerializerOrContextUnchecked(this, argType)
|
emptyGenerator.findTypeSerializerOrContextUnchecked(this, argType)
|
||||||
@@ -181,7 +184,7 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
* We need to remove instructions from 1 to 5
|
* We need to remove instructions from 1 to 5
|
||||||
* Instructions 0, -1 -2 and -3 would be removed by inliner.
|
* Instructions 0, -1 -2 and -3 would be removed by inliner.
|
||||||
*/
|
*/
|
||||||
fun rewritePluginDefinedReifiedOperationMarker(
|
override fun rewritePluginDefinedOperationMarker(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
stubConstNull: AbstractInsnNode,
|
stubConstNull: AbstractInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
|
|||||||
+29
-68
@@ -8,10 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||||
@@ -35,7 +32,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
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.isTypeParameter
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
@@ -251,89 +247,56 @@ 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
|
// returns false is cannot not use serializer
|
||||||
// use iv == null to check only (do not emit serializer onto stack)
|
// use iv == null to check only (do not emit serializer onto stack)
|
||||||
internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCodegen: ExpressionCodegen, classCodegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||||
expressionCodegen: ExpressionCodegen?, typeMapper: KotlinTypeMapper, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
iv: InstructionAdapter?,
|
||||||
iv: InstructionAdapter?,
|
genericIndex: Int? = null,
|
||||||
genericIndex: Int? = null,
|
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
||||||
insertExceptionOnNoSerializer: Boolean = false,
|
|
||||||
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null,
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (maybeSerializer == null && genericIndex != null) {
|
if (maybeSerializer == null && genericIndex != null) {
|
||||||
// get field from serializer object
|
// get field from serializer object
|
||||||
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex, kType) }
|
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex, kType) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val serializer = maybeSerializer ?: run {
|
val serializer = maybeSerializer ?: return false
|
||||||
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) {
|
if (serializer.kind == ClassKind.OBJECT) {
|
||||||
// singleton serializer -- just get it
|
// singleton serializer -- just get it
|
||||||
if (iv != null)
|
if (iv != null)
|
||||||
StackValue.singleton(serializer, typeMapper).put(kSerializerType, iv)
|
StackValue.singleton(serializer, classCodegen.typeMapper).put(kSerializerType, iv)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// serializer is not singleton object and shall be instantiated
|
// serializer is not singleton object and shall be instantiated
|
||||||
val argSerializers = kType.arguments.map { projection ->
|
val argSerializers = kType.arguments.map { projection ->
|
||||||
// check if any type argument is not serializable
|
// bail out from stackValueSerializerInstance if any type argument is not serializable
|
||||||
val argType = projection.type
|
val argType = projection.type
|
||||||
val argSerializer =
|
val argSerializer = if (argType.isTypeParameter()) null else {
|
||||||
if (argType.isTypeParameter()) null else findTypeSerializerOrContextUnchecked(module, argType)
|
findTypeSerializerOrContext(module, argType, sourceElement = classCodegen.descriptor.findPsi())
|
||||||
|
?: return false
|
||||||
|
}
|
||||||
// check if it can be properly serialized with its args recursively
|
// check if it can be properly serialized with its args recursively
|
||||||
if (!stackValueSerializerInstance(
|
if (!stackValueSerializerInstance(
|
||||||
expressionCodegen,
|
expressionCodegen,
|
||||||
typeMapper,
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
null,
|
null,
|
||||||
argType.genericIndex,
|
argType.genericIndex,
|
||||||
insertExceptionOnNoSerializer = false,
|
|
||||||
genericSerializerFieldGetter
|
genericSerializerFieldGetter
|
||||||
)
|
)
|
||||||
) {
|
)
|
||||||
// bail out only if we do not need to insert exception
|
return false
|
||||||
if (!insertExceptionOnNoSerializer) return false
|
|
||||||
}
|
|
||||||
Pair(argType, argSerializer)
|
Pair(argType, argSerializer)
|
||||||
}
|
}
|
||||||
// new serializer if needed
|
// new serializer if needed
|
||||||
iv?.apply {
|
iv?.apply {
|
||||||
val serializerType = typeMapper.mapClass(serializer)
|
val serializerType = classCodegen.typeMapper.mapClass(serializer)
|
||||||
val classDescriptor = kType.toClassDescriptor!!
|
val classDescriptor = kType.toClassDescriptor!!
|
||||||
if (serializer.classId == enumSerializerId && !classDescriptor.useGeneratedEnumSerializer) {
|
if (serializer.classId == enumSerializerId && !classDescriptor.useGeneratedEnumSerializer) {
|
||||||
// runtime contains enum serializer factory functions
|
// runtime contains enum serializer factory functions
|
||||||
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||||
val enumJavaType = typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||||
val serialName = classDescriptor.serialName()
|
val serialName = classDescriptor.serialName()
|
||||||
|
|
||||||
if (classDescriptor.isEnumWithSerialInfoAnnotation()) {
|
if (classDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||||
@@ -360,7 +323,7 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
} else {
|
} else {
|
||||||
fillArray(annotationType, annotations) { _, annotation ->
|
fillArray(annotationType, annotations) { _, annotation ->
|
||||||
val (annotationClass, args, consParams) = annotation
|
val (annotationClass, args, consParams) = annotation
|
||||||
expressionCodegen?.generateSyntheticAnnotationOnStack(annotationClass, args, consParams) ?: nop()
|
expressionCodegen.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,15 +361,14 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
expressionCodegen,
|
expressionCodegen,
|
||||||
typeMapper,
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
this,
|
this,
|
||||||
argType.genericIndex,
|
argType.genericIndex,
|
||||||
insertExceptionOnNoSerializer,
|
|
||||||
genericSerializerFieldGetter
|
genericSerializerFieldGetter
|
||||||
) || insertExceptionOnNoSerializer
|
)
|
||||||
)
|
)
|
||||||
// wrap into nullable serializer if argType is nullable
|
// wrap into nullable serializer if argType is nullable
|
||||||
if (argType.isMarkedNullable) wrapStackValueIntoNullableSerializer()
|
if (argType.isMarkedNullable) wrapStackValueIntoNullableSerializer()
|
||||||
@@ -419,16 +381,16 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
// support legacy serializer instantiation by constructor for old runtimes
|
// support legacy serializer instantiation by constructor for old runtimes
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
val enumJavaType = typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
val enumJavaType = classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT)
|
||||||
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
val javaEnumArray = Type.getType("[Ljava/lang/Enum;")
|
||||||
invokestatic(enumJavaType.internalName, "values", "()[${enumJavaType.descriptor}", false)
|
invokestatic(enumJavaType.internalName, "values","()[${enumJavaType.descriptor}", false)
|
||||||
checkcast(javaEnumArray)
|
checkcast(javaEnumArray)
|
||||||
signature.append(javaEnumArray.descriptor)
|
signature.append(javaEnumArray.descriptor)
|
||||||
}
|
}
|
||||||
contextSerializerId, polymorphicSerializerId -> {
|
contextSerializerId, polymorphicSerializerId -> {
|
||||||
// a special way to instantiate enum -- need a enum KClass reference
|
// a special way to instantiate enum -- need a enum KClass reference
|
||||||
// GENERIC_ARGUMENT forces boxing in order to obtain KClass
|
// GENERIC_ARGUMENT forces boxing in order to obtain KClass
|
||||||
aconst(typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
if (serializer.classId == contextSerializerId && serializer.constructors.any { it.valueParameters.size == 3 }) {
|
if (serializer.classId == contextSerializerId && serializer.constructors.any { it.valueParameters.size == 3 }) {
|
||||||
@@ -448,7 +410,7 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
}
|
}
|
||||||
referenceArraySerializerId -> {
|
referenceArraySerializerId -> {
|
||||||
// a special way to instantiate reference array serializer -- need an element KClass reference
|
// a special way to instantiate reference array serializer -- need an element KClass reference
|
||||||
aconst(typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType.arguments[0].type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
// Reference array serializer still needs serializer for its argument type
|
// Reference array serializer still needs serializer for its argument type
|
||||||
@@ -457,13 +419,13 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
aconst(typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
||||||
// KClasses vararg
|
// KClasses vararg
|
||||||
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
||||||
aconst(typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(classCodegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
}
|
}
|
||||||
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
||||||
@@ -473,7 +435,7 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
expressionCodegen,
|
expressionCodegen,
|
||||||
typeMapper,
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
argType,
|
argType,
|
||||||
argSerializer,
|
argSerializer,
|
||||||
@@ -484,12 +446,11 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
assert(
|
assert(
|
||||||
stackValueSerializerInstance(
|
stackValueSerializerInstance(
|
||||||
expressionCodegen,
|
expressionCodegen,
|
||||||
typeMapper,
|
classCodegen,
|
||||||
module,
|
module,
|
||||||
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
||||||
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
||||||
this,
|
this
|
||||||
insertExceptionOnNoSerializer = insertExceptionOnNoSerializer
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -501,7 +462,7 @@ internal fun AbstractSerialGenerator?.stackValueSerializerInstance(
|
|||||||
objectSerializerId -> {
|
objectSerializerId -> {
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
StackValue.singleton(kType.toClassDescriptor!!, typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
StackValue.singleton(kType.toClassDescriptor!!, classCodegen.typeMapper).put(Type.getType("Ljava/lang/Object;"), iv)
|
||||||
signature.append("Ljava/lang/Object;")
|
signature.append("Ljava/lang/Object;")
|
||||||
}
|
}
|
||||||
// all serializers get arguments with serializers of their generic types
|
// all serializers get arguments with serializers of their generic types
|
||||||
|
|||||||
+31
-24
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.extensions
|
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.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.CompilationException
|
import org.jetbrains.kotlin.backend.common.CompilationException
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
@@ -12,15 +13,12 @@ import org.jetbrains.kotlin.backend.common.extensions.IrIntrinsicExtension
|
|||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.JvmIrIntrinsicExtension
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
||||||
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -33,9 +31,6 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializationJvmI
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,14 +123,20 @@ private class SerializerClassPreLowering(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SerializationIntrinsicsState {
|
||||||
|
NORMAL, // depends on whether we have noCompiledSerializer function in runtime
|
||||||
|
DISABLED, // disabled if corresponding CLI flag passed
|
||||||
|
FORCE_ENABLED // used for test purposes ONLY
|
||||||
|
}
|
||||||
|
|
||||||
open class SerializationLoweringExtension @JvmOverloads constructor(
|
open class SerializationLoweringExtension @JvmOverloads constructor(
|
||||||
private val metadataPlugin: SerializationDescriptorSerializerPlugin? = null
|
private val metadataPlugin: SerializationDescriptorSerializerPlugin? = null
|
||||||
) : IrGenerationExtension {
|
) : IrGenerationExtension {
|
||||||
|
|
||||||
private var disableIntrinsics = false
|
private var intrinsicsState = SerializationIntrinsicsState.NORMAL
|
||||||
|
|
||||||
constructor(metadataPlugin: SerializationDescriptorSerializerPlugin, disableIntrinsics: Boolean) : this(metadataPlugin) {
|
constructor(metadataPlugin: SerializationDescriptorSerializerPlugin, intrinsicsState: SerializationIntrinsicsState) : this(metadataPlugin) {
|
||||||
this.disableIntrinsics = disableIntrinsics
|
this.intrinsicsState = intrinsicsState
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generate(
|
override fun generate(
|
||||||
@@ -148,21 +149,27 @@ open class SerializationLoweringExtension @JvmOverloads constructor(
|
|||||||
moduleFragment.files.forEach(pass2::runOnFileInOrder)
|
moduleFragment.files.forEach(pass2::runOnFileInOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPlatformIntrinsicExtension(): IrIntrinsicExtension? {
|
override fun getPlatformIntrinsicExtension(backendContext: BackendContext): IrIntrinsicExtension? {
|
||||||
return if (disableIntrinsics) null else object : JvmIrIntrinsicExtension {
|
val ctx = backendContext as? JvmBackendContext ?: return null
|
||||||
override fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? =
|
if (!canEnableIntrinsics(ctx)) return null
|
||||||
SerializationJvmIrIntrinsicSupport.intrinsicForMethod(symbol.owner)
|
return SerializationJvmIrIntrinsicSupport(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
override fun rewritePluginDefinedOperationMarker(
|
private fun canEnableIntrinsics(ctx: JvmBackendContext): Boolean {
|
||||||
v: InstructionAdapter,
|
return when (intrinsicsState) {
|
||||||
next: AbstractInsnNode,
|
SerializationIntrinsicsState.FORCE_ENABLED -> true
|
||||||
instructions: InsnList,
|
SerializationIntrinsicsState.DISABLED -> false
|
||||||
type: IrType,
|
SerializationIntrinsicsState.NORMAL -> {
|
||||||
jvmBackendContext: JvmBackendContext
|
val module = ctx.state.module
|
||||||
): Boolean {
|
if (module.findClassAcrossModuleDependencies(
|
||||||
return SerializationJvmIrIntrinsicSupport(jvmBackendContext).rewritePluginDefinedReifiedOperationMarker(
|
ClassId(
|
||||||
v, next, instructions, type
|
SerializationPackages.packageFqName,
|
||||||
)
|
SerialEntityNames.KSERIALIZER_NAME
|
||||||
|
)
|
||||||
|
) == null
|
||||||
|
) return false
|
||||||
|
module.getPackage(SerializationPackages.packageFqName).memberScope.getFunctionNames()
|
||||||
|
.any { it.asString() == SerializationJvmIrIntrinsicSupport.noCompiledSerializerMethodName }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -53,13 +53,14 @@ class SerializationComponentRegistrar : CompilerPluginRegistrar() {
|
|||||||
Companion.registerExtensions(this, loadDisableIntrinsic(configuration))
|
Companion.registerExtensions(this, loadDisableIntrinsic(configuration))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDisableIntrinsic(configuration: CompilerConfiguration) = configuration.get(DISABLE_INTRINSIC) ?: false
|
private fun loadDisableIntrinsic(configuration: CompilerConfiguration) =
|
||||||
|
if (configuration.get(DISABLE_INTRINSIC) == true) SerializationIntrinsicsState.DISABLED else SerializationIntrinsicsState.NORMAL
|
||||||
|
|
||||||
override val supportsK2: Boolean
|
override val supportsK2: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun registerExtensions(extensionStorage: ExtensionStorage, disableIntrinsics: Boolean = false) = with(extensionStorage) {
|
fun registerExtensions(extensionStorage: ExtensionStorage, intrinsicsState: SerializationIntrinsicsState = SerializationIntrinsicsState.NORMAL) = with(extensionStorage) {
|
||||||
// This method is never called in the IDE, therefore this extension is not available there.
|
// This method is never called in the IDE, therefore this extension is not available there.
|
||||||
// Since IDE does not perform any serialization of descriptors, metadata written to the 'serializationDescriptorSerializer'
|
// Since IDE does not perform any serialization of descriptors, metadata written to the 'serializationDescriptorSerializer'
|
||||||
// is never deleted, effectively causing memory leaks.
|
// is never deleted, effectively causing memory leaks.
|
||||||
@@ -72,7 +73,7 @@ class SerializationComponentRegistrar : CompilerPluginRegistrar() {
|
|||||||
|
|
||||||
ExpressionCodegenExtension.registerExtension(SerializationCodegenExtension(serializationDescriptorSerializer))
|
ExpressionCodegenExtension.registerExtension(SerializationCodegenExtension(serializationDescriptorSerializer))
|
||||||
JsSyntheticTranslateExtension.registerExtension(SerializationJsExtension(serializationDescriptorSerializer))
|
JsSyntheticTranslateExtension.registerExtension(SerializationJsExtension(serializationDescriptorSerializer))
|
||||||
IrGenerationExtension.registerExtension(SerializationLoweringExtension(serializationDescriptorSerializer, disableIntrinsics))
|
IrGenerationExtension.registerExtension(SerializationLoweringExtension(serializationDescriptorSerializer, intrinsicsState))
|
||||||
|
|
||||||
StorageComponentContainerContributor.registerExtension(SerializationPluginComponentContainerContributor())
|
StorageComponentContainerContributor.registerExtension(SerializationPluginComponentContainerContributor())
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -6,12 +6,15 @@
|
|||||||
package org.jetbrains.kotlinx.serialization.compiler.diagnostic
|
package org.jetbrains.kotlinx.serialization.compiler.diagnostic
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.util.slicedMap.Slices
|
import org.jetbrains.kotlin.util.slicedMap.Slices
|
||||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
|
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object VersionReader {
|
object VersionReader {
|
||||||
@@ -30,7 +33,12 @@ object VersionReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getVersionsForCurrentModule(module: ModuleDescriptor): RuntimeVersions? {
|
fun getVersionsForCurrentModule(module: ModuleDescriptor): RuntimeVersions? {
|
||||||
val markerClass = module.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
|
val markerClass = module.findClassAcrossModuleDependencies(
|
||||||
|
ClassId(
|
||||||
|
SerializationPackages.packageFqName,
|
||||||
|
Name.identifier(SerialEntityNames.KSERIALIZER_CLASS)
|
||||||
|
)
|
||||||
|
) ?: return null
|
||||||
return CommonVersionReader.computeRuntimeVersions(markerClass.source)
|
return CommonVersionReader.computeRuntimeVersions(markerClass.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
|||||||
import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider
|
import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComponentRegistrar
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComponentRegistrar
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIntrinsicsState
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationExtensionRegistrar
|
import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationExtensionRegistrar
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ class SerializationEnvironmentConfigurator(
|
|||||||
module: TestModule,
|
module: TestModule,
|
||||||
configuration: CompilerConfiguration
|
configuration: CompilerConfiguration
|
||||||
) {
|
) {
|
||||||
SerializationComponentRegistrar.registerExtensions(this)
|
SerializationComponentRegistrar.registerExtensions(this, SerializationIntrinsicsState.FORCE_ENABLED)
|
||||||
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user