JVM_IR: generate shorter bytecode for reflected property references
This commit is contained in:
+23
-11
@@ -148,22 +148,29 @@ class DelegatedPropertyOptimizer {
|
|||||||
//
|
//
|
||||||
// AASTORE
|
// 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) {
|
current = matchRange(current) {
|
||||||
aload(slot)
|
aload(slot)
|
||||||
index = iconst()
|
index = iconst()
|
||||||
new(PROPERTY_REFERENCE_CLASSES)
|
new(PROPERTY_REFERENCE_CLASSES)
|
||||||
dup()
|
dup()
|
||||||
// Either getOrCreateKotlinPackage(class, module) or getOrCreateKotlinClass(class)
|
|
||||||
ldc() // java class
|
ldc() // java class
|
||||||
optional {
|
either(
|
||||||
ldc() // module name
|
{
|
||||||
}
|
optional { ldc() } // module name, if package
|
||||||
invokestatic("kotlin/jvm/internal/Reflection")
|
invokestatic("kotlin/jvm/internal/Reflection") // getOrCreateKotlinPackage or getOrCreateKotlinClass
|
||||||
ldc() // name
|
ldc() // name
|
||||||
ldc() // signature
|
ldc() // signature
|
||||||
invokespecial("<init>", "(Lkotlin/reflect/KDeclarationContainer;Ljava/lang/String;Ljava/lang/String;)V")
|
invokespecial("<init>", "(Lkotlin/reflect/KDeclarationContainer;Ljava/lang/String;Ljava/lang/String;)V")
|
||||||
invokestatic("kotlin/jvm/internal/Reflection")
|
}, {
|
||||||
|
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()
|
aastore()
|
||||||
} ?: break
|
} ?: break
|
||||||
|
|
||||||
@@ -239,10 +246,15 @@ private class InstructionMatcher(var current: AbstractInsnNode?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun optional(block: () -> Unit) {
|
inline fun optional(block: () -> Unit) {
|
||||||
|
either(block) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun either(first: () -> Unit, second: () -> Unit) {
|
||||||
val start = current
|
val start = current
|
||||||
block()
|
first()
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
current = start
|
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;"))`.
|
// Example: `C::property` -> `Reflection.property1(PropertyReference1Impl(C::class, "property", "getProperty()LType;"))`.
|
||||||
private fun createReflectedKProperty(expression: IrCallableReference<*>): IrExpression {
|
private fun createReflectedKProperty(expression: IrCallableReference<*>): IrExpression {
|
||||||
assert(expression.dispatchReceiver == null && expression.extensionReceiver == null) {
|
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()}"
|
"cannot create a reflected KProperty if the reference has a bound receiver: ${expression.render()}"
|
||||||
}
|
}
|
||||||
val referenceKind = propertyReferenceKindFor(expression)
|
val referenceKind = propertyReferenceKindFor(expression)
|
||||||
return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
||||||
irCall(referenceKind.wrapper).apply {
|
irCall(referenceKind.wrapper).apply {
|
||||||
val constructor = referenceKind.implSymbol.constructors.single { it.owner.valueParameters.size == 3 }
|
val container = expression.propertyContainer
|
||||||
putValueArgument(0, irCall(constructor).apply {
|
val name = irString(expression.referencedName.asString())
|
||||||
putValueArgument(0, calculateOwner(expression.propertyContainer, this@PropertyReferenceLowering.context))
|
val signature = computeSignatureString(expression)
|
||||||
putValueArgument(1, irString(expression.referencedName.asString()))
|
val impl = when {
|
||||||
putValueArgument(2, computeSignatureString(expression))
|
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