JVM_IR: try to avoid resolveFakeOverride() in BridgeLowering
One of the uses can be avoided, the other remains. Special overrides are now generated for MutableMap.remove and getOrDefault when there is an intermediate Java class, same as in old backend.
This commit is contained in:
+16
-9
@@ -165,15 +165,10 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
if (irFunction.isJvmAbstract)
|
||||
return !irFunction.parentAsClass.isJvmInterface
|
||||
|
||||
// Finally, the JVM backend also ignores concrete fake overrides which are implemented in interfaces.
|
||||
// Finally, the JVM backend also ignores concrete fake overrides whose implementation is directly inherited from an interface.
|
||||
// This is sound, since we do not generate type-specialized versions of fake overrides and if the method
|
||||
// were to override several interface methods the frontend would require a separate implementation.
|
||||
//
|
||||
// In addition, there are @PlatformDependent methods which only exist on newer JDK versions
|
||||
// (MutableMap.remove and getOrDefault). Trying to produce (special) bridges for these methods could
|
||||
// result in incorrect bytecode on older JVM versions. However, all such methods are declared
|
||||
// in interfaces and thus we don't need a separate check for them.
|
||||
return !irFunction.isFakeOverride || !irFunction.resolveFakeOverride()!!.parentAsClass.isJvmInterface
|
||||
return !irFunction.isFakeOverride || irFunction.resolvesToClass()
|
||||
})
|
||||
|
||||
for (member in potentialBridgeTargets) {
|
||||
@@ -226,12 +221,15 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
irClass.addAbstractMethodStub(irFunction, specialBridge.methodInfo?.needsArgumentBoxing == true)
|
||||
}
|
||||
irFunction.modality != Modality.FINAL -> {
|
||||
val superTarget = irFunction.overriddenSymbols.first { !it.owner.parentAsClass.isInterface }.owner
|
||||
val overriddenFromClass = irFunction.overriddenFromClass()!!
|
||||
val superBridge = SpecialBridge(
|
||||
irFunction, irFunction.jvmMethod, superQualifierSymbol = superTarget.parentAsClass.symbol,
|
||||
irFunction, irFunction.jvmMethod, superQualifierSymbol = overriddenFromClass.parentAsClass.symbol,
|
||||
methodInfo = specialBridge.methodInfo?.copy(argumentsToCheck = 0), // For potential argument boxing
|
||||
isFinal = false,
|
||||
)
|
||||
// The part after ?: is needed for methods with default implementations in collection interfaces:
|
||||
// MutableMap.remove() and getOrDefault().
|
||||
val superTarget = overriddenFromClass.takeIf { !it.isFakeOverride } ?: specialBridge.overridden
|
||||
irClass.declarations.remove(irFunction)
|
||||
irClass.addSpecialBridge(superBridge, superTarget)
|
||||
}
|
||||
@@ -486,3 +484,12 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
}
|
||||
|
||||
private fun IrDeclaration.comesFromJava() = parentAsClass.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
|
||||
// Check whether a fake override will resolve to an implementation in class, not an interface.
|
||||
private fun IrSimpleFunction.resolvesToClass(): Boolean {
|
||||
val overriddenFromClass = overriddenFromClass() ?: return false
|
||||
return overriddenFromClass.modality != Modality.ABSTRACT
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.overriddenFromClass(): IrSimpleFunction? =
|
||||
overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isJvmInterface }?.owner
|
||||
|
||||
Reference in New Issue
Block a user