Remove OperationType.PLUGIN_DEFINED type:
instead, plugins should emit the code similar to the TYPE_OF one with a special call to MagicApiIntrinsics.voidMagicApiCall directly afterwards. This is required because old compiler need to correctly inline code rewritten by plugin.
This commit is contained in:
-16
@@ -42,22 +42,6 @@ interface ExpressionCodegenExtension {
|
|||||||
*/
|
*/
|
||||||
fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when inliner encounters [ReifiedTypeInliner.OperationKind.PLUGIN_DEFINED] marker
|
|
||||||
* to perform extension-specific operation with reified type parameter.
|
|
||||||
*
|
|
||||||
* @return Required stack size for method after inlining is performed, 0 if the size is unknown, or -1 if extension ignores this marker
|
|
||||||
*/
|
|
||||||
fun applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn: MethodInsnNode,
|
|
||||||
instructions: InsnList,
|
|
||||||
type: KotlinType,
|
|
||||||
asmType: Type,
|
|
||||||
typeMapper: KotlinTypeMapper,
|
|
||||||
typeSystem: TypeSystemCommonBackendContext,
|
|
||||||
module: ModuleDescriptor
|
|
||||||
): Int = -1
|
|
||||||
|
|
||||||
fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {}
|
fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {}
|
||||||
|
|
||||||
val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
|
val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
|
||||||
|
|||||||
-17
@@ -86,21 +86,4 @@ class PsiInlineIntrinsicsSupport(
|
|||||||
override fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name) {
|
override fun reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameterName: Name) {
|
||||||
state.diagnostics.report(TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND.on(reportErrorsOn, typeParameterName.asString()))
|
state.diagnostics.report(TYPEOF_NON_REIFIED_TYPE_PARAMETER_WITH_RECURSIVE_BOUND.on(reportErrorsOn, typeParameterName.asString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn: MethodInsnNode,
|
|
||||||
instructions: InsnList,
|
|
||||||
type: KotlinType,
|
|
||||||
asmType: Type
|
|
||||||
): Int = pluginExtensions.maxOfOrNull {
|
|
||||||
it.applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn,
|
|
||||||
instructions,
|
|
||||||
type,
|
|
||||||
asmType,
|
|
||||||
state.typeMapper,
|
|
||||||
typeSystem,
|
|
||||||
state.module
|
|
||||||
)
|
|
||||||
} ?: -1
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
private val unifiedNullChecks: Boolean,
|
private val unifiedNullChecks: Boolean,
|
||||||
) {
|
) {
|
||||||
enum class OperationKind {
|
enum class OperationKind {
|
||||||
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS, ENUM_REIFIED, TYPE_OF, PLUGIN_DEFINED;
|
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS, ENUM_REIFIED, TYPE_OF;
|
||||||
|
|
||||||
val id: Int get() = ordinal
|
val id: Int get() = ordinal
|
||||||
}
|
}
|
||||||
@@ -66,21 +66,18 @@ 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 =
|
||||||
* @return Required stack size for method after inlining is performed, 0 if the size is unknown, or -1 if plugin was not applied
|
false
|
||||||
*/
|
|
||||||
fun applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn: MethodInsnNode,
|
|
||||||
instructions: InsnList,
|
|
||||||
type: KT,
|
|
||||||
asmType: Type
|
|
||||||
): Int = -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
|
const val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
|
||||||
const val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
|
const val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
|
||||||
|
|
||||||
|
const val pluginIntrinsicsMarkerOwner = "kotlin/jvm/internal/MagicApiIntrinsics"
|
||||||
|
const val pluginIntrinsicsMarkerMethod = "voidMagicApiCall"
|
||||||
|
const val pluginIntrinsicsMarkerSignature = "(Ljava/lang/Object;)V"
|
||||||
|
|
||||||
fun isOperationReifiedMarker(insn: AbstractInsnNode) =
|
fun isOperationReifiedMarker(insn: AbstractInsnNode) =
|
||||||
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
|
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
|
||||||
|
|
||||||
@@ -180,8 +177,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
||||||
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
|
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
|
||||||
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
|
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
|
||||||
OperationKind.TYPE_OF -> processTypeOf(insn, instructions, type)
|
OperationKind.TYPE_OF -> processTypeOfOrPlugin(insn, instructions, type)
|
||||||
OperationKind.PLUGIN_DEFINED -> processPluginDefined(insn, instructions, type, asmType)
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
instructions.remove(insn.previous.previous!!) // PUSH operation ID
|
instructions.remove(insn.previous.previous!!) // PUSH operation ID
|
||||||
@@ -197,23 +193,6 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPluginDefined(
|
|
||||||
insn: MethodInsnNode,
|
|
||||||
instructions: InsnList,
|
|
||||||
type: KT,
|
|
||||||
asmType: Type
|
|
||||||
): Boolean {
|
|
||||||
val applyResult = intrinsicsSupport.applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn,
|
|
||||||
instructions,
|
|
||||||
type,
|
|
||||||
asmType
|
|
||||||
)
|
|
||||||
if (applyResult == -1) return false
|
|
||||||
maxStackSize = max(maxStackSize, applyResult)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reify(argument: ReificationArgument, replacementAsmType: Type, type: KT): Pair<Type, KT> =
|
private fun reify(argument: ReificationArgument, replacementAsmType: Type, type: KT): Pair<Type, KT> =
|
||||||
with(typeSystem) {
|
with(typeSystem) {
|
||||||
val arrayType = type.arrayOf(argument.arrayDepth)
|
val arrayType = type.arrayOf(argument.arrayDepth)
|
||||||
@@ -282,13 +261,21 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processTypeOf(
|
private fun processTypeOfOrPlugin(
|
||||||
insn: MethodInsnNode,
|
insn: MethodInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
type: KT
|
type: KT
|
||||||
) = rewriteNextTypeInsn(insn, Opcodes.ACONST_NULL) { stubConstNull: AbstractInsnNode ->
|
) = rewriteNextTypeInsn(insn, Opcodes.ACONST_NULL) { stubConstNull: AbstractInsnNode ->
|
||||||
val newMethodNode = newMethodNodeWithCorrectStackSize {
|
val newMethodNode = newMethodNodeWithCorrectStackSize {
|
||||||
typeSystem.generateTypeOf(it, type, intrinsicsSupport)
|
if (!isPluginNext(stubConstNull) || !intrinsicsSupport.rewritePluginDefinedOperationMarker(
|
||||||
|
it,
|
||||||
|
stubConstNull,
|
||||||
|
instructions,
|
||||||
|
type,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
typeSystem.generateTypeOf(it, type, intrinsicsSupport)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions.insert(insn, newMethodNode.instructions)
|
instructions.insert(insn, newMethodNode.instructions)
|
||||||
@@ -298,6 +285,15 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isPluginNext(insn: AbstractInsnNode): Boolean {
|
||||||
|
val magicInsn = insn.next?.next ?: return false
|
||||||
|
return magicInsn is MethodInsnNode && magicInsn.opcode == Opcodes.INVOKESTATIC
|
||||||
|
&& magicInsn.owner == pluginIntrinsicsMarkerOwner
|
||||||
|
&& magicInsn.name == pluginIntrinsicsMarkerMethod
|
||||||
|
&& magicInsn.desc == pluginIntrinsicsMarkerSignature
|
||||||
|
&& insn.next is LdcInsnNode
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun rewriteNextTypeInsn(
|
private inline fun rewriteNextTypeInsn(
|
||||||
marker: MethodInsnNode,
|
marker: MethodInsnNode,
|
||||||
expectedNextOpcode: Int,
|
expectedNextOpcode: Int,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ dependencies {
|
|||||||
api(project(":compiler:ir.tree"))
|
api(project(":compiler:ir.tree"))
|
||||||
api(project(":compiler:ir.interpreter"))
|
api(project(":compiler:ir.interpreter"))
|
||||||
compileOnly(intellijCore())
|
compileOnly(intellijCore())
|
||||||
compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
+4
-14
@@ -32,8 +32,8 @@ 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.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
|
|
||||||
class IrInlineIntrinsicsSupport(
|
class IrInlineIntrinsicsSupport(
|
||||||
private val classCodegen: ClassCodegen,
|
private val classCodegen: ClassCodegen,
|
||||||
@@ -127,17 +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 applyPluginDefinedReifiedOperationMarker(
|
override fun rewritePluginDefinedOperationMarker(v: InstructionAdapter, next: AbstractInsnNode, instructions: InsnList, type: IrType): Boolean {
|
||||||
insn: MethodInsnNode,
|
return pluginExtensions.any { it.rewritePluginDefinedOperationMarker(v, next, instructions, type, classCodegen.context) }
|
||||||
instructions: InsnList,
|
}
|
||||||
type: IrType,
|
|
||||||
asmType: Type
|
|
||||||
): Int = pluginExtensions.maxOfOrNull {
|
|
||||||
it.applyPluginDefinedReifiedOperationMarker(
|
|
||||||
insn,
|
|
||||||
instructions,
|
|
||||||
type,
|
|
||||||
classCodegen.context
|
|
||||||
)
|
|
||||||
} ?: -1
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-5
@@ -10,16 +10,22 @@ 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
|
||||||
|
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 org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
|
|
||||||
interface JvmIrIntrinsicExtension : IrIntrinsicExtension {
|
interface JvmIrIntrinsicExtension : IrIntrinsicExtension {
|
||||||
fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod?
|
fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod?
|
||||||
|
|
||||||
fun applyPluginDefinedReifiedOperationMarker(
|
/**
|
||||||
insn: MethodInsnNode,
|
* Should return `true` if marker was processed.
|
||||||
|
* If this method returns `false`, a regular `TYPE_OF` intrinsic would be inserted.
|
||||||
|
*/
|
||||||
|
fun rewritePluginDefinedOperationMarker(
|
||||||
|
v: InstructionAdapter,
|
||||||
|
next: AbstractInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
type: IrType,
|
type: IrType,
|
||||||
jvmBackendContext: JvmBackendContext,
|
jvmBackendContext: JvmBackendContext
|
||||||
): Int = -1
|
): Boolean
|
||||||
}
|
}
|
||||||
+65
-51
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
|||||||
import org.jetbrains.kotlin.backend.jvm.mapping.mapClass
|
import org.jetbrains.kotlin.backend.jvm.mapping.mapClass
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||||
import org.jetbrains.kotlin.codegen.inline.newMethodNodeWithCorrectStackSize
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIntrinsicsMarkerMethod
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIntrinsicsMarkerOwner
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIntrinsicsMarkerSignature
|
||||||
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
|
||||||
@@ -51,7 +53,7 @@ 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.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
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 {
|
||||||
@@ -60,6 +62,11 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
|
|
||||||
class WithModule(val storedIndex: Int) :
|
class WithModule(val storedIndex: Int) :
|
||||||
IntrinsicType(stubCallDescriptorWithModule)
|
IntrinsicType(stubCallDescriptorWithModule)
|
||||||
|
|
||||||
|
fun magicMarkerString(): String = magicMarkerStringPrefix + when(this) {
|
||||||
|
is Simple -> "simple"
|
||||||
|
is WithModule -> "withModule"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -78,13 +85,16 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
val serializersModuleType: Type = Type.getObjectType("kotlinx/serialization/modules/SerializersModule")
|
val serializersModuleType: Type = Type.getObjectType("kotlinx/serialization/modules/SerializersModule")
|
||||||
|
val kTypeType: Type = AsmTypes.K_TYPE
|
||||||
|
|
||||||
val stubCallDescriptorWithModule = "(${serializersModuleType.descriptor})${kSerializerType.descriptor}"
|
val stubCallDescriptorWithModule = "(${serializersModuleType.descriptor}${kTypeType.descriptor})${kSerializerType.descriptor}"
|
||||||
val stubCallDescriptor = "()${kSerializerType.descriptor}"
|
val stubCallDescriptor = "(${kTypeType.descriptor})${kSerializerType.descriptor}"
|
||||||
const val serializersKtInternalName = "kotlinx/serialization/SerializersKt"
|
const val serializersKtInternalName = "kotlinx/serialization/SerializersKt"
|
||||||
const val callMethodName = "serializer"
|
const val callMethodName = "serializer"
|
||||||
const val noCompiledSerializerMethodName = "noCompiledSerializer"
|
const val noCompiledSerializerMethodName = "noCompiledSerializer"
|
||||||
|
|
||||||
|
const val magicMarkerStringPrefix = "kotlinx.serialization.serializer."
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReifiedSerializerMethod(private val withModule: Boolean) : IntrinsicMethod() {
|
class ReifiedSerializerMethod(private val withModule: Boolean) : IntrinsicMethod() {
|
||||||
@@ -154,54 +164,53 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
iv.visitFieldInsn(Opcodes.GETSTATIC, ownerType.internalName, targetField.name.asString(), fieldType.descriptor)
|
iv.visitFieldInsn(Opcodes.GETSTATIC, ownerType.internalName, targetField.name.asString(), fieldType.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyPluginDefinedReifiedOperationMarker(
|
/**
|
||||||
insn: MethodInsnNode,
|
* Instructions at the moment of call:
|
||||||
|
*
|
||||||
|
* -3: iconst(6) // TYPE_OF
|
||||||
|
* -2: aconst(typeParamName) // TYPE_OF
|
||||||
|
* -1: invokestatic(reifiedOperationMarker)
|
||||||
|
* < instructions from instructionAdapter will be inserted here by inliner >
|
||||||
|
* 0 (stubConstNull): aconst(null)
|
||||||
|
* 1: aconst(kotlinx.serialization.serializer.<operationType>)
|
||||||
|
* 2: invokestatic(voidMagicApiCall)
|
||||||
|
* 3: aload(moduleVar) // if withModule
|
||||||
|
* 4: swap // if withModule
|
||||||
|
* 5: invokestatic(kotlinx.serialization.serializer(module?, kType)
|
||||||
|
*
|
||||||
|
* We need to remove instructions from 1 to 5
|
||||||
|
* Instructions 0, -1 -2 and -3 would be removed by inliner.
|
||||||
|
*/
|
||||||
|
fun rewritePluginDefinedReifiedOperationMarker(
|
||||||
|
v: InstructionAdapter,
|
||||||
|
stubConstNull: AbstractInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
type: IrType,
|
type: IrType
|
||||||
): Int {
|
): Boolean {
|
||||||
val intrinsicType = getOperationTypeFromInsn(insn) ?: return -1
|
val operationTypeStr = (stubConstNull.next as LdcInsnNode).cst as String
|
||||||
val newMethodNode = newMethodNodeWithCorrectStackSize {
|
if (!operationTypeStr.startsWith(magicMarkerStringPrefix)) return false
|
||||||
generateSerializerForType(type, it, intrinsicType)
|
val operationType = if (operationTypeStr.endsWith("withModule")) {
|
||||||
}
|
val aload = stubConstNull.next.next.next as VarInsnNode
|
||||||
|
val storedVar = aload.`var`
|
||||||
when (intrinsicType) {
|
instructions.remove(aload.next)
|
||||||
is IntrinsicType.Simple -> instructions.remove(insn.next)
|
instructions.remove(aload)
|
||||||
is IntrinsicType.WithModule -> {
|
IntrinsicType.WithModule(storedVar)
|
||||||
instructions.remove(insn.next.next)
|
} else IntrinsicType.Simple
|
||||||
instructions.remove(insn.next)
|
// Remove other instructions
|
||||||
}
|
instructions.remove(stubConstNull.next.next.next)
|
||||||
}
|
instructions.remove(stubConstNull.next.next)
|
||||||
instructions.insert(insn, newMethodNode.instructions)
|
instructions.remove(stubConstNull.next)
|
||||||
|
// generate serializer
|
||||||
return newMethodNode.maxStack
|
generateSerializerForType(type, v, operationType)
|
||||||
}
|
return true
|
||||||
|
|
||||||
private fun getOperationTypeFromInsn(insn: MethodInsnNode): IntrinsicType? {
|
|
||||||
// insn is reification marker
|
|
||||||
// insn.next is serializer() OR load(module)
|
|
||||||
// insn.next.next is serializer(module) if insn.next was load(module)
|
|
||||||
val mayBeSerializerModuleCall: AbstractInsnNode? = insn.next?.next
|
|
||||||
val next = insn.next ?: error("Reification marker cannot be the last instruction in method")
|
|
||||||
if (
|
|
||||||
mayBeSerializerModuleCall is MethodInsnNode
|
|
||||||
&& mayBeSerializerModuleCall.opcode == Opcodes.INVOKESTATIC
|
|
||||||
&& mayBeSerializerModuleCall.owner == serializersKtInternalName
|
|
||||||
&& mayBeSerializerModuleCall.name == callMethodName
|
|
||||||
&& mayBeSerializerModuleCall.desc == stubCallDescriptorWithModule
|
|
||||||
) {
|
|
||||||
val loadIns = next as? VarInsnNode ?: error("Expected load(SerializersModule) instruction")
|
|
||||||
// It's possible to also check opcode, but that doesn't seem necessary
|
|
||||||
return IntrinsicType.WithModule(loadIns.`var`)
|
|
||||||
} else if (next is MethodInsnNode
|
|
||||||
&& next.opcode == Opcodes.INVOKESTATIC
|
|
||||||
&& next.owner == serializersKtInternalName
|
|
||||||
&& next.name == callMethodName
|
|
||||||
&& next.desc == stubCallDescriptor
|
|
||||||
) {
|
|
||||||
return IntrinsicType.Simple
|
|
||||||
} else return null // May be reification marker from other plugin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function produces identical to TYPE_OF reification marker. This is needed for compatibility reasons:
|
||||||
|
* old compiler should be able to inline and run newer versions of kotlinx-serialization or other libraries.
|
||||||
|
*
|
||||||
|
* Operation detection in new compilers performed by voidMagicApiCall.
|
||||||
|
*/
|
||||||
private fun InstructionAdapter.putReifyMarkerIfNeeded(type: KotlinTypeMarker, intrinsicType: IntrinsicType): Boolean =
|
private fun InstructionAdapter.putReifyMarkerIfNeeded(type: KotlinTypeMarker, intrinsicType: IntrinsicType): Boolean =
|
||||||
with(typeSystemContext) {
|
with(typeSystemContext) {
|
||||||
val typeDescriptor = type.typeConstructor().getTypeParameterClassifier()
|
val typeDescriptor = type.typeConstructor().getTypeParameterClassifier()
|
||||||
@@ -209,12 +218,17 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
ReifiedTypeInliner.putReifiedOperationMarkerIfNeeded(
|
ReifiedTypeInliner.putReifiedOperationMarkerIfNeeded(
|
||||||
typeDescriptor,
|
typeDescriptor,
|
||||||
false,
|
false,
|
||||||
ReifiedTypeInliner.OperationKind.PLUGIN_DEFINED,
|
ReifiedTypeInliner.OperationKind.TYPE_OF,
|
||||||
this@putReifyMarkerIfNeeded,
|
this@putReifyMarkerIfNeeded,
|
||||||
typeSystemContext
|
typeSystemContext
|
||||||
)
|
)
|
||||||
|
aconst(null)
|
||||||
|
aconst(intrinsicType.magicMarkerString())
|
||||||
|
invokestatic(pluginIntrinsicsMarkerOwner, pluginIntrinsicsMarkerMethod, pluginIntrinsicsMarkerSignature, false)
|
||||||
if (intrinsicType is IntrinsicType.WithModule) {
|
if (intrinsicType is IntrinsicType.WithModule) {
|
||||||
|
// Force emit load instruction so we can retrieve var index later
|
||||||
load(intrinsicType.storedIndex, serializersModuleType)
|
load(intrinsicType.storedIndex, serializersModuleType)
|
||||||
|
swap()
|
||||||
}
|
}
|
||||||
invokestatic(serializersKtInternalName, callMethodName, intrinsicType.methodDescriptor, false)
|
invokestatic(serializersKtInternalName, callMethodName, intrinsicType.methodDescriptor, false)
|
||||||
return true
|
return true
|
||||||
@@ -317,7 +331,7 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
signature?.append(kSerializerType.descriptor)
|
signature?.append(kSerializerType.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val serializer = maybeSerializer ?: iv.run {
|
val serializer = maybeSerializer ?: iv.run {// insert noCompilerSerializer(module, kClass, arguments)
|
||||||
require(intrinsicType is IntrinsicType.WithModule) // SIMPLE is covered in previous if
|
require(intrinsicType is IntrinsicType.WithModule) // SIMPLE is covered in previous if
|
||||||
// SerializersModule
|
// SerializersModule
|
||||||
load(intrinsicType.storedIndex, serializersModuleType)
|
load(intrinsicType.storedIndex, serializersModuleType)
|
||||||
|
|||||||
+10
-9
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
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
|
||||||
@@ -34,8 +33,9 @@ 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 org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,16 +146,17 @@ open class SerializationLoweringExtension @JvmOverloads constructor(
|
|||||||
override fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? =
|
override fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? =
|
||||||
SerializationJvmIrIntrinsicSupport.intrinsicForMethod(symbol.owner)
|
SerializationJvmIrIntrinsicSupport.intrinsicForMethod(symbol.owner)
|
||||||
|
|
||||||
override fun applyPluginDefinedReifiedOperationMarker(
|
override fun rewritePluginDefinedOperationMarker(
|
||||||
insn: MethodInsnNode,
|
v: InstructionAdapter,
|
||||||
|
next: AbstractInsnNode,
|
||||||
instructions: InsnList,
|
instructions: InsnList,
|
||||||
type: IrType,
|
type: IrType,
|
||||||
jvmBackendContext: JvmBackendContext
|
jvmBackendContext: JvmBackendContext
|
||||||
): Int = SerializationJvmIrIntrinsicSupport(jvmBackendContext).applyPluginDefinedReifiedOperationMarker(
|
): Boolean {
|
||||||
insn,
|
return SerializationJvmIrIntrinsicSupport(jvmBackendContext).rewritePluginDefinedReifiedOperationMarker(
|
||||||
instructions,
|
v, next, instructions, type
|
||||||
type,
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -16,11 +16,15 @@ public final class IntrinsicsAdvancedKt : java/lang/Object {
|
|||||||
LINENUMBER (18)
|
LINENUMBER (18)
|
||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
ASTORE (2)
|
ASTORE (2)
|
||||||
BIPUSH (7)
|
BIPUSH (6)
|
||||||
LDC (T)
|
LDC (T)
|
||||||
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
|
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, reifiedOperationMarker, (ILjava/lang/String;)V)
|
||||||
|
ACONST_NULL
|
||||||
|
LDC (kotlinx.serialization.serializer.withModule)
|
||||||
|
INVOKESTATIC (kotlin/jvm/internal/MagicApiIntrinsics, voidMagicApiCall, (Ljava/lang/Object;)V)
|
||||||
ALOAD (2)
|
ALOAD (2)
|
||||||
INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlinx/serialization/modules/SerializersModule;)Lkotlinx/serialization/KSerializer;)
|
SWAP
|
||||||
|
INVOKESTATIC (kotlinx/serialization/SerializersKt, serializer, (Lkotlinx/serialization/modules/SerializersModule;Lkotlin/reflect/KType;)Lkotlinx/serialization/KSerializer;)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L2)
|
LABEL (L2)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user