Skip to content

Commit

Permalink
Create a copy of incorrectly deserialized parent's writeSelf function
Browse files Browse the repository at this point in the history
To avoid problems during code generation when INVOKEDYNAMIC
is used instead of static

 #KT-47161 Fixed

(cherry picked from commit dd21326)
  • Loading branch information
sandwwraith authored and Space committed Jul 2, 2021
1 parent 68474d7 commit 18328f9
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,22 @@ class SerializableIrGenerator(
ignoreIndexTo = bindingContext.serializablePropertiesFor(superClass.descriptor).size

// call super.writeSelf
val superWriteSelfF = superClass.findWriteSelfMethod()
var superWriteSelfF = superClass.findWriteSelfMethod()

if (superWriteSelfF != null) {
// Workaround for incorrect DeserializedClassDescriptor on JVM (see MemberDeserializer#getDispatchReceiverParameter):
// Because Kotlin does not have static functions, descriptors from other modules are deserialized with dispatch receiver,
// even if they were created without it
if (superWriteSelfF.dispatchReceiverParameter != null) {
superWriteSelfF = compilerContext.copiedStaticWriteSelf.getOrPut(superWriteSelfF) {
superWriteSelfF!!.deepCopyWithSymbols(initialParent = superClass).also { it.dispatchReceiverParameter = null }
}
}

val args = mutableListOf<IrExpression>(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc))

val typeArgsForParent = serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
val typeArgsForParent =
serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
val parentWriteSelfSerializers = typeArgsForParent.map { arg ->
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(arg).let { if (it == -1) null else it }
val serial = findTypeSerializerOrContext(serializableDescriptor.module, arg.type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ 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.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
Expand All @@ -23,6 +21,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableCompa
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializableIrGenerator
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import java.util.concurrent.ConcurrentHashMap

/**
* Copy of [runOnFilePostfix], but this implementation first lowers declaration, then its children.
Expand All @@ -40,17 +39,24 @@ fun ClassLoweringPass.runOnFileInOrder(irFile: IrFile) {
})
}

typealias SerializationPluginContext = IrPluginContext

class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugin: SerializationDescriptorSerializerPlugin?) :
IrPluginContext by baseContext {
lateinit var serialInfoImplJvmIrGenerator: SerialInfoImplJvmIrGenerator

internal val copiedStaticWriteSelf: MutableMap<IrSimpleFunction, IrSimpleFunction> = ConcurrentHashMap()
}

private class SerializerClassLowering(
val context: SerializationPluginContext,
val metadataPlugin: SerializationDescriptorSerializerPlugin?
baseContext: IrPluginContext,
metadataPlugin: SerializationDescriptorSerializerPlugin?
) : IrElementTransformerVoid(), ClassLoweringPass {
private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context)
val context: SerializationPluginContext = SerializationPluginContext(baseContext, metadataPlugin)
private val serialInfoJvmGenerator = SerialInfoImplJvmIrGenerator(context).also { context.serialInfoImplJvmIrGenerator = it }

override fun lower(irClass: IrClass) {
SerializableIrGenerator.generate(irClass, context, context.bindingContext)
SerializerIrGenerator.generate(irClass, context, context.bindingContext, metadataPlugin, serialInfoJvmGenerator)
SerializerIrGenerator.generate(irClass, context, context.bindingContext, context.metadataPlugin, serialInfoJvmGenerator)
SerializableCompanionIrGenerator.generate(irClass, context, context.bindingContext)

if (context.platform.isJvm() && KSerializerDescriptorResolver.isSerialInfoImpl(irClass.descriptor)) {
Expand Down

0 comments on commit 18328f9

Please sign in to comment.