JVM_IR: use correct signatures for local delegated property references
Which is `<v#N>` where N is the index of that property in the containing class.
This commit is contained in:
+29
-6
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
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.*
|
||||||
@@ -45,9 +46,14 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
private val IrMemberAccessExpression.field: IrFieldSymbol?
|
private val IrMemberAccessExpression.field: IrFieldSymbol?
|
||||||
get() = (this as? IrPropertyReference)?.field
|
get() = (this as? IrPropertyReference)?.field
|
||||||
|
|
||||||
|
// Reflection metadata for local properties is serialized under the signature "<v#$N>" attached to the containing class.
|
||||||
|
// This maps properties to values of N.
|
||||||
|
private val localPropertyIndices = mutableMapOf<IrSymbol, Int>()
|
||||||
|
|
||||||
private val IrMemberAccessExpression.signature: String
|
private val IrMemberAccessExpression.signature: String
|
||||||
// Plain Java fields do not have a getter, but can be referenced nonetheless.
|
get() = localPropertyIndices[getter]?.let { "<v#$it>" }
|
||||||
get() = getter?.owner?.let { context.state.typeMapper.mapSignatureSkipGeneric(it.descriptor).toString() }
|
?: getter?.owner?.let { context.state.typeMapper.mapSignatureSkipGeneric(it.descriptor).toString() }
|
||||||
|
// Plain Java fields do not have a getter, but can be referenced nonetheless.
|
||||||
?: TODO("plain Java field signature")
|
?: TODO("plain Java field signature")
|
||||||
|
|
||||||
private val IrMemberAccessExpression.symbol: IrSymbol
|
private val IrMemberAccessExpression.symbol: IrSymbol
|
||||||
@@ -74,18 +80,29 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
private val kPropertiesFieldType =
|
private val kPropertiesFieldType =
|
||||||
context.ir.symbols.array.createType(false, listOf(makeTypeProjection(kPropertyType, Variance.OUT_VARIANCE)))
|
context.ir.symbols.array.createType(false, listOf(makeTypeProjection(kPropertyType, Variance.OUT_VARIANCE)))
|
||||||
|
|
||||||
|
// Return some declaration the parent of which is the containing class/package for the referenced property. This is
|
||||||
|
// a bit of a hack, as the reason for not returning the container itself is the `mapImplementationOwner` call below.
|
||||||
|
// TODO: move after LocalDeclarationsLowering and always use the getter/field? (not possible right now:
|
||||||
|
// need Java field support to move below PropertiesToFieldsLowering)
|
||||||
|
private val IrMemberAccessExpression.propertyContainerChild: IrDeclaration?
|
||||||
|
get() {
|
||||||
|
var current: IrDeclaration? = getter?.owner ?: field?.owner
|
||||||
|
while (current?.parent is IrFunction)
|
||||||
|
current = current.parent as IrFunction
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: remove code duplication with CallableReferenceLowering
|
// TODO: remove code duplication with CallableReferenceLowering
|
||||||
private val IrMemberAccessExpression.parentJavaClassReference
|
private val IrMemberAccessExpression.parentJavaClassReference
|
||||||
get() = IrClassReferenceImpl(
|
get() = IrClassReferenceImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
plainJavaClass.defaultType,
|
plainJavaClass.defaultType,
|
||||||
plainJavaClass.symbol,
|
plainJavaClass.symbol,
|
||||||
CrIrType(context.state.typeMapper.mapImplementationOwner(descriptor))
|
CrIrType(context.state.typeMapper.mapImplementationOwner(propertyContainerChild!!.descriptor))
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun IrBuilderWithScope.buildReflectedContainerReference(expression: IrMemberAccessExpression): IrExpression {
|
private fun IrBuilderWithScope.buildReflectedContainerReference(expression: IrMemberAccessExpression): IrExpression {
|
||||||
val parent = expression.getter?.owner?.parent ?: expression.field?.owner?.parent
|
return when (expression.propertyContainerChild?.parent) {
|
||||||
return when (parent) {
|
|
||||||
is IrPackageFragment -> irCall(getOrCreateKotlinPackage).apply {
|
is IrPackageFragment -> irCall(getOrCreateKotlinPackage).apply {
|
||||||
putValueArgument(0, expression.parentJavaClassReference)
|
putValueArgument(0, expression.parentJavaClassReference)
|
||||||
putValueArgument(1, irString(this@PropertyReferenceLowering.context.state.moduleName))
|
putValueArgument(1, irString(this@PropertyReferenceLowering.context.state.moduleName))
|
||||||
@@ -93,7 +110,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
is IrClass -> irCall(getOrCreateKotlinClass).apply {
|
is IrClass -> irCall(getOrCreateKotlinClass).apply {
|
||||||
putValueArgument(0, expression.parentJavaClassReference)
|
putValueArgument(0, expression.parentJavaClassReference)
|
||||||
}
|
}
|
||||||
else -> irNull()
|
else -> throw AssertionError("referenced property not inside a class/package fragment")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,11 +153,17 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
isFinal = true
|
isFinal = true
|
||||||
isStatic = true
|
isStatic = true
|
||||||
}
|
}
|
||||||
|
var localPropertiesInClass = 0
|
||||||
|
|
||||||
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression =
|
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression =
|
||||||
cachedKProperty(expression)
|
cachedKProperty(expression)
|
||||||
|
|
||||||
|
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrStatement {
|
||||||
|
localPropertyIndices[declaration.getter.symbol] = localPropertiesInClass++
|
||||||
|
return super.visitLocalDelegatedProperty(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression =
|
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression =
|
||||||
cachedKProperty(expression)
|
cachedKProperty(expression)
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user