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:
Georgy Bronnikov
2020-02-14 17:11:07 +03:00
parent fa74eabbd1
commit dd7d5dfdb3
@@ -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