Parcelize: do not copy call in ParcelizeIrTransformer

This is just a refactoring/optimization that makes use of the fact that
IrCall.symbol and IrFunctionReference.symbol are now mutable.
This commit is contained in:
Alexander Udalov
2023-06-17 00:08:05 +02:00
committed by Space Team
parent b75aa9af4e
commit 755d140e16
2 changed files with 35 additions and 61 deletions
@@ -16,24 +16,19 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
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.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -57,40 +52,32 @@ class ParcelableIrTransformer(private val context: IrPluginContext, private val
deferredOperations.forEach { it() } deferredOperations.forEach { it() }
// Remap broken stubs, which psi2ir generates for the synthetic descriptors coming from the ParcelizeResolveExtension. // Remap broken stubs, which psi2ir generates for the synthetic descriptors coming from the ParcelizeResolveExtension.
moduleFragment.transformChildrenVoid(object : IrElementTransformerVoid() { moduleFragment.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitCall(expression: IrCall): IrExpression { override fun visitElement(element: IrElement) {
val remappedSymbol = symbolMap[expression.symbol] element.acceptChildren(this, null)
?: return super.visitCall(expression)
return IrCallImpl(
expression.startOffset, expression.endOffset, expression.type, remappedSymbol,
expression.typeArgumentsCount, expression.valueArgumentsCount, expression.origin,
expression.superQualifierSymbol
).apply {
copyTypeAndValueArgumentsFrom(expression)
}
} }
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { override fun visitCall(expression: IrCall) {
expression.acceptChildren(this, null)
expression.symbol = symbolMap[expression.symbol] ?: return
}
override fun visitFunctionReference(expression: IrFunctionReference) {
expression.acceptChildren(this, null)
val remappedSymbol = symbolMap[expression.symbol] val remappedSymbol = symbolMap[expression.symbol]
val remappedReflectionTarget = expression.reflectionTarget?.let { symbolMap[it] } val remappedReflectionTarget = expression.reflectionTarget?.let { symbolMap[it] }
if (remappedSymbol == null && remappedReflectionTarget == null) if (remappedSymbol == null && remappedReflectionTarget == null) return
return super.visitFunctionReference(expression)
return IrFunctionReferenceImpl( expression.symbol = remappedSymbol ?: expression.symbol
expression.startOffset, expression.endOffset, expression.type, remappedSymbol ?: expression.symbol, expression.reflectionTarget = remappedReflectionTarget
expression.typeArgumentsCount, expression.valueArgumentsCount, remappedReflectionTarget,
expression.origin
).apply {
copyTypeAndValueArgumentsFrom(expression)
}
} }
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { override fun visitSimpleFunction(declaration: IrSimpleFunction) {
declaration.acceptChildren(this, null)
// Remap overridden symbols, otherwise the code might break in BridgeLowering // Remap overridden symbols, otherwise the code might break in BridgeLowering
declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol -> declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol ->
symbolMap[symbol] ?: symbol symbolMap[symbol] ?: symbol
} }
return super.visitSimpleFunction(declaration)
} }
}) })
} }
@@ -19,12 +19,9 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.util.companionObject
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -51,18 +48,8 @@ class ParcelizeIrTransformer(
// Replace the `parcelableCreator` intrinsic with a direct field access. // Replace the `parcelableCreator` intrinsic with a direct field access.
moduleFragment.transformChildrenVoid(object : IrElementTransformerVoid() { moduleFragment.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
// Handle the `parcelableCreator` intrinsic
val callee = expression.symbol.owner val callee = expression.symbol.owner
if ( if (callee.isParcelableCreatorIntrinsic()) {
callee.dispatchReceiverParameter == null
&& callee.extensionReceiverParameter == null
&& callee.valueParameters.isEmpty()
&& callee.isInline
&& callee.fqNameWhenAvailable?.asString() == "kotlinx.parcelize.ParcelableCreatorKt.parcelableCreator"
&& callee.typeParameters.singleOrNull()?.let {
it.isReified && it.superTypes.singleOrNull()?.classFqName == PARCELABLE_FQN
} == true
) {
expression.getTypeArgument(0)?.getClass()?.let { parcelableClass -> expression.getTypeArgument(0)?.getClass()?.let { parcelableClass ->
androidSymbols.createBuilder(expression.symbol).apply { androidSymbols.createBuilder(expression.symbol).apply {
return getParcelableCreator(parcelableClass) return getParcelableCreator(parcelableClass)
@@ -71,30 +58,30 @@ class ParcelizeIrTransformer(
} }
// Remap calls to `describeContents` and `writeToParcel` // Remap calls to `describeContents` and `writeToParcel`
val remappedSymbol = symbolMap[expression.symbol] expression.transformChildren(this, null)
?: return super.visitCall(expression) expression.symbol = symbolMap[expression.symbol] ?: return expression
return IrCallImpl( return expression
expression.startOffset, expression.endOffset, expression.type, remappedSymbol,
expression.typeArgumentsCount, expression.valueArgumentsCount, expression.origin,
expression.superQualifierSymbol
).apply {
copyTypeAndValueArgumentsFrom(expression)
}
} }
private fun IrSimpleFunction.isParcelableCreatorIntrinsic(): Boolean =
dispatchReceiverParameter == null
&& extensionReceiverParameter == null
&& valueParameters.isEmpty()
&& isInline
&& fqNameWhenAvailable?.asString() == "kotlinx.parcelize.ParcelableCreatorKt.parcelableCreator"
&& typeParameters.singleOrNull()?.let {
it.isReified && it.superTypes.singleOrNull()?.classFqName == PARCELABLE_FQN
} == true
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildren(this, null)
val remappedSymbol = symbolMap[expression.symbol] val remappedSymbol = symbolMap[expression.symbol]
val remappedReflectionTarget = expression.reflectionTarget?.let { symbolMap[it] } val remappedReflectionTarget = expression.reflectionTarget?.let { symbolMap[it] }
if (remappedSymbol == null && remappedReflectionTarget == null) if (remappedSymbol == null && remappedReflectionTarget == null) return expression
return super.visitFunctionReference(expression)
return IrFunctionReferenceImpl( expression.symbol = remappedSymbol ?: expression.symbol
expression.startOffset, expression.endOffset, expression.type, remappedSymbol ?: expression.symbol, expression.reflectionTarget = remappedReflectionTarget
expression.typeArgumentsCount, expression.valueArgumentsCount, remappedReflectionTarget, return expression
expression.origin
).apply {
copyTypeAndValueArgumentsFrom(expression)
}
} }
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement {