JVM_IR: generate shorter bytecode for reflected property references
This commit is contained in:
+23
-11
@@ -148,22 +148,29 @@ class DelegatedPropertyOptimizer {
|
||||
//
|
||||
// AASTORE
|
||||
//
|
||||
// With the caveat that we might create a class instead of a package as the `KDeclarationContainer`.
|
||||
// With the caveat that we might create a class instead of a package as the `KDeclarationContainer`,
|
||||
// and with optimized references the Java class is passed to the constructor without wrapping.
|
||||
current = matchRange(current) {
|
||||
aload(slot)
|
||||
index = iconst()
|
||||
new(PROPERTY_REFERENCE_CLASSES)
|
||||
dup()
|
||||
// Either getOrCreateKotlinPackage(class, module) or getOrCreateKotlinClass(class)
|
||||
ldc() // java class
|
||||
optional {
|
||||
ldc() // module name
|
||||
}
|
||||
invokestatic("kotlin/jvm/internal/Reflection")
|
||||
ldc() // name
|
||||
ldc() // signature
|
||||
invokespecial("<init>", "(Lkotlin/reflect/KDeclarationContainer;Ljava/lang/String;Ljava/lang/String;)V")
|
||||
invokestatic("kotlin/jvm/internal/Reflection")
|
||||
either(
|
||||
{
|
||||
optional { ldc() } // module name, if package
|
||||
invokestatic("kotlin/jvm/internal/Reflection") // getOrCreateKotlinPackage or getOrCreateKotlinClass
|
||||
ldc() // name
|
||||
ldc() // signature
|
||||
invokespecial("<init>", "(Lkotlin/reflect/KDeclarationContainer;Ljava/lang/String;Ljava/lang/String;)V")
|
||||
}, {
|
||||
ldc() // name
|
||||
ldc() // signature
|
||||
iconst() // flags
|
||||
invokespecial("<init>", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V")
|
||||
}
|
||||
)
|
||||
invokestatic("kotlin/jvm/internal/Reflection") // (property|mutableProperty)[012]
|
||||
aastore()
|
||||
} ?: break
|
||||
|
||||
@@ -239,10 +246,15 @@ private class InstructionMatcher(var current: AbstractInsnNode?) {
|
||||
}
|
||||
|
||||
inline fun optional(block: () -> Unit) {
|
||||
either(block) {}
|
||||
}
|
||||
|
||||
inline fun either(first: () -> Unit, second: () -> Unit) {
|
||||
val start = current
|
||||
block()
|
||||
first()
|
||||
if (current == null) {
|
||||
current = start
|
||||
second()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-6
@@ -279,17 +279,33 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
|
||||
// Example: `C::property` -> `Reflection.property1(PropertyReference1Impl(C::class, "property", "getProperty()LType;"))`.
|
||||
private fun createReflectedKProperty(expression: IrCallableReference<*>): IrExpression {
|
||||
assert(expression.dispatchReceiver == null && expression.extensionReceiver == null) {
|
||||
// TODO: technically can with `generateOptimizedCallableReferenceSuperClasses` - use the 5-argument constructor
|
||||
"cannot create a reflected KProperty if the reference has a bound receiver: ${expression.render()}"
|
||||
}
|
||||
val referenceKind = propertyReferenceKindFor(expression)
|
||||
return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
||||
irCall(referenceKind.wrapper).apply {
|
||||
val constructor = referenceKind.implSymbol.constructors.single { it.owner.valueParameters.size == 3 }
|
||||
putValueArgument(0, irCall(constructor).apply {
|
||||
putValueArgument(0, calculateOwner(expression.propertyContainer, this@PropertyReferenceLowering.context))
|
||||
putValueArgument(1, irString(expression.referencedName.asString()))
|
||||
putValueArgument(2, computeSignatureString(expression))
|
||||
})
|
||||
val container = expression.propertyContainer
|
||||
val name = irString(expression.referencedName.asString())
|
||||
val signature = computeSignatureString(expression)
|
||||
val impl = when {
|
||||
this@PropertyReferenceLowering.context.state.generateOptimizedCallableReferenceSuperClasses ->
|
||||
irCall(referenceKind.implSymbol.constructors.single { it.owner.valueParameters.size == 4 }).apply {
|
||||
val kClass = calculateOwnerKClass(container, this@PropertyReferenceLowering.context)
|
||||
val isPackage = (container is IrClass && container.isFileClass) || container is IrPackageFragment
|
||||
putValueArgument(0, kClassToJavaClass(kClass, this@PropertyReferenceLowering.context))
|
||||
putValueArgument(1, name)
|
||||
putValueArgument(2, signature)
|
||||
putValueArgument(3, irInt(if (isPackage) 1 else 0))
|
||||
}
|
||||
else ->
|
||||
irCall(referenceKind.implSymbol.constructors.single { it.owner.valueParameters.size == 3 }).apply {
|
||||
putValueArgument(0, calculateOwner(container, this@PropertyReferenceLowering.context))
|
||||
putValueArgument(1, name)
|
||||
putValueArgument(2, signature)
|
||||
}
|
||||
}
|
||||
putValueArgument(0, impl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user