JVM_IR: fix a couple of inline class reflection issues.

1. Postpone the computation of the signature for property
   reference getters for extension properties until codegen time.

2. Generate metadata for static replacement functions instead
   of the original functions.
This commit is contained in:
Mads Ager
2019-12-23 08:53:14 +01:00
committed by Alexander Udalov
parent 2ebb797e61
commit e7835fecfc
8 changed files with 37 additions and 22 deletions
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.ir.util.collectRealOverrides
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
/**
@@ -20,15 +21,9 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
object SignatureString : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
val function = (expression.getValueArgument(0) as IrFunctionReference).symbol.owner
// TODO do not use descriptors
val declaration = codegen.context.referenceFunction(
DescriptorUtils.unwrapFakeOverride(function.descriptor).original
).owner
val method = codegen.context.methodSignatureMapper.mapAsmMethod(declaration)
val resolved = if (function is IrSimpleFunction) function.collectRealOverrides().first() else function
val method = codegen.context.methodSignatureMapper.mapAsmMethod(resolved)
val descriptor = method.name + method.descriptor
return object : PromisedValue(codegen, AsmTypes.JAVA_STRING_TYPE, codegen.context.irBuiltIns.stringType) {
override fun materialize() {
codegen.mv.aconst(descriptor)
@@ -19,10 +19,12 @@ import org.jetbrains.kotlin.backend.jvm.ir.irArrayOf
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.createType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -64,14 +66,11 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
private val IrField.signature: String
get() = "${JvmAbi.getterName(name.asString())}()${context.methodSignatureMapper.mapReturnType(this)}"
private val IrMemberAccessExpression.signature: String
get() = getter?.let { getter ->
localPropertyIndices[getter]?.let { "<v#$it>" }
} ?: getter?.owner?.signature ?: field!!.owner.signature
private val arrayItemGetter =
context.ir.symbols.array.owner.functions.single { it.name.asString() == "get" }
private val signatureStringIntrinsic = context.ir.symbols.signatureStringIntrinsic
private val kPropertyStarType = IrSimpleTypeImpl(
context.irBuiltIns.kPropertyClass,
false,
@@ -95,6 +94,23 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
calculateOwner(expression.propertyContainer, this@PropertyReferenceLowering.context)
}
private fun IrBuilderWithScope.computeSignatureString(expression: IrCallableReference): IrExpression {
return expression.getter?.let { getter ->
localPropertyIndices[getter]?.let { irString("<v#$it>") }
?: if (getter.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
// Default property accessor. Compute the signature now, so that we will not get into trouble
// if the getter is transformed to a static method by inline classes lowering.
irString(getter.owner.signature)
} else {
// Delay the computation of the signature until after inline classes lowering to make sure
// we mangle the function names correctly for things like extension methods on inline classes.
irCall(signatureStringIntrinsic).apply {
putValueArgument(0, IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.type, getter, 0, null))
}
}
} ?: irString(expression.field!!.owner.signature)
}
private fun IrClass.addOverride(method: IrSimpleFunction, buildBody: IrBuilderWithScope.(List<IrValueParameter>) -> IrExpression) =
addFunction {
setSourceRange(this@addOverride)
@@ -204,7 +220,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
putValueArgument(0, irCall(referenceKind.reflectedSymbol.constructors.single()).apply {
putValueArgument(0, buildReflectedContainerReference(expression))
putValueArgument(1, irString(expression.symbol.descriptor.name.asString()))
putValueArgument(2, irString(expression.signature))
putValueArgument(2, computeSignatureString(expression))
})
}
}
@@ -266,7 +282,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
referenceClass.addSimpleDelegatingConstructor(superConstructor, context.irBuiltIns, isPrimary = true)
referenceClass.addOverride(getName) { irString(expression.symbol.descriptor.name.asString()) }
referenceClass.addOverride(getOwner) { buildReflectedContainerReference(expression) }
referenceClass.addOverride(getSignature) { irString(expression.signature) }
referenceClass.addOverride(getSignature) { computeSignatureString(expression) }
val receiverField = referenceClass.addField {
name = backingFieldFromSuper.name
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildFunWithDescriptorForInlining
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionBase
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -169,8 +170,11 @@ class MemoizedInlineClassReplacements {
private fun createStaticReplacement(function: IrFunction): IrReplacementFunction {
val parameterMap = mutableMapOf<IrValueParameterSymbol, IrValueParameter>()
val replacement = buildReplacement(function) {
if (function !is IrSimpleFunction || function.overriddenSymbols.isEmpty())
// Generate metadata for the replacement function instead of the original.
if (function is IrFunctionBase) {
metadata = function.metadata
function.metadata = null
}
for ((index, parameter) in function.explicitParameters.withIndex()) {
val name = when (parameter) {
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.reflect.KMutableProperty2
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals