JVM_IR KT-48945 generate special bridge with unsubstituted signature
This commit is contained in:
committed by
TeamCityServer
parent
4c3404888a
commit
30ceb49442
+4
-3
@@ -24,6 +24,7 @@ data class SpecialMethodWithDefaultInfo(
|
||||
val defaultValueGenerator: (IrSimpleFunction) -> IrExpression,
|
||||
val argumentsToCheck: Int,
|
||||
val needsGenericSignature: Boolean = false,
|
||||
val needsUnsubstitutedBridge: Boolean = false
|
||||
)
|
||||
|
||||
class BuiltInWithDifferentJvmName(
|
||||
@@ -78,11 +79,11 @@ class SpecialBridgeMethods(val context: CommonBackendContext) {
|
||||
makeDescription(StandardNames.FqNames.list, "lastIndexOf", 1) to
|
||||
SpecialMethodWithDefaultInfo(::constMinusOne, 1),
|
||||
makeDescription(StandardNames.FqNames.map, "getOrDefault", 2) to
|
||||
SpecialMethodWithDefaultInfo(::getSecondArg, 1, needsGenericSignature = true),
|
||||
SpecialMethodWithDefaultInfo(::getSecondArg, 1, needsGenericSignature = true, needsUnsubstitutedBridge = true),
|
||||
makeDescription(StandardNames.FqNames.map, "get", 1) to
|
||||
SpecialMethodWithDefaultInfo(::constNull, 1, needsGenericSignature = true),
|
||||
SpecialMethodWithDefaultInfo(::constNull, 1, needsGenericSignature = true, needsUnsubstitutedBridge = true),
|
||||
makeDescription(StandardNames.FqNames.mutableMap, "remove", 1) to
|
||||
SpecialMethodWithDefaultInfo(::constNull, 1, needsGenericSignature = true)
|
||||
SpecialMethodWithDefaultInfo(::constNull, 1, needsGenericSignature = true, needsUnsubstitutedBridge = true)
|
||||
)
|
||||
|
||||
private val specialProperties = mapOf(
|
||||
|
||||
+26
-5
@@ -265,18 +265,35 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
irClass.addSpecialBridge(superBridge, superTarget)
|
||||
}
|
||||
}
|
||||
else -> irFunction
|
||||
else -> {
|
||||
irFunction
|
||||
}
|
||||
}
|
||||
|
||||
blacklist += bridgeTarget.jvmMethod
|
||||
}
|
||||
|
||||
if (irClass.functions.any { !it.isFakeOverride && it.name == irFunction.name && specialBridge.signature == it.jvmMethod }) {
|
||||
return irFunction
|
||||
// Add special bridge with unsubstituted signature (as generated by old JVM back-end) if required.
|
||||
// According to KT-40277 we generate special bridges for 'get', 'getOrDefault', and 'remove' with substituted return type.
|
||||
// However, this introduces performance regressions and changes in behavior if cases like KT-48945
|
||||
// (where a Kotlin class implements a read-only collection interface and extends a Java collection class).
|
||||
val unsubstitutedSpecialBridge = specialBridge.unsubstitutedSpecialBridge
|
||||
if (unsubstitutedSpecialBridge != null &&
|
||||
irClass.functions.none { it.isClashingWithPotentialBridge(irFunction.name, unsubstitutedSpecialBridge.signature) }
|
||||
) {
|
||||
blacklist += unsubstitutedSpecialBridge.signature
|
||||
// TODO what should be the special bridge target if we CAN NOT add a substituted special bridge
|
||||
// (below, clashes with existing method),
|
||||
// but CAN add an unsubstituted special bridge (here)?
|
||||
irClass.addSpecialBridge(unsubstitutedSpecialBridge, bridgeTarget)
|
||||
}
|
||||
|
||||
blacklist += specialBridge.signature
|
||||
return irClass.addSpecialBridge(specialBridge, bridgeTarget)
|
||||
if (irClass.functions.none { it.isClashingWithPotentialBridge(irFunction.name, specialBridge.signature) }) {
|
||||
blacklist += specialBridge.signature
|
||||
return irClass.addSpecialBridge(specialBridge, bridgeTarget)
|
||||
}
|
||||
|
||||
return irFunction
|
||||
}
|
||||
|
||||
val specialBridgeTarget = getSpecialBridgeTargetAddingExtraBridges()
|
||||
@@ -339,6 +356,10 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
.forEach { irClass.addBridge(it, bridgeTarget) }
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isClashingWithPotentialBridge(name: Name, signature: Method): Boolean =
|
||||
(!this.isFakeOverride || this.modality == Modality.FINAL) && this.name == name && this.jvmMethod == signature
|
||||
|
||||
|
||||
// Returns the special bridge overridden by the current methods if it exists.
|
||||
private val IrSimpleFunction.specialBridgeOrNull: SpecialBridge?
|
||||
get() = context.bridgeLoweringCache.computeSpecialBridge(this)
|
||||
|
||||
@@ -42,4 +42,9 @@ data class SpecialBridge(
|
||||
val isFinal: Boolean = true,
|
||||
val isSynthetic: Boolean = false,
|
||||
val isOverriding: Boolean = true,
|
||||
// 'true' if we also should produce a synthetic bridge with unsubstituted signature.
|
||||
// NB this is passed down the hierarchy to the point where 'unsubstitutedSpecialBridge' is created,
|
||||
// see BridgeLoweringCache::computeSpecialBridge
|
||||
val needsUnsubstitutedBridge: Boolean = false,
|
||||
val unsubstitutedSpecialBridge: SpecialBridge? = null
|
||||
)
|
||||
|
||||
+18
-3
@@ -54,7 +54,10 @@ class BridgeLoweringCache(private val context: JvmBackendContext) {
|
||||
val specialMethodInfo = specialBridgeMethods.getSpecialMethodInfo(function)
|
||||
if (specialMethodInfo != null)
|
||||
return SpecialBridge(
|
||||
function, computeJvmMethod(function), specialMethodInfo.needsGenericSignature, methodInfo = specialMethodInfo
|
||||
overridden = function, signature = computeJvmMethod(function),
|
||||
needsGenericSignature = specialMethodInfo.needsGenericSignature,
|
||||
methodInfo = specialMethodInfo,
|
||||
needsUnsubstitutedBridge = specialMethodInfo.needsUnsubstitutedBridge
|
||||
)
|
||||
|
||||
val specialBuiltInInfo = specialBridgeMethods.getBuiltInWithDifferentJvmName(function)
|
||||
@@ -87,10 +90,22 @@ class BridgeLoweringCache(private val context: JvmBackendContext) {
|
||||
parent = function.parent
|
||||
}
|
||||
|
||||
val substitutedOverrideSignature = computeJvmMethod(substitutedOverride)
|
||||
val unsubstitutedSpecialBridge =
|
||||
when {
|
||||
specialBridge.unsubstitutedSpecialBridge != null ->
|
||||
specialBridge.unsubstitutedSpecialBridge
|
||||
specialBridge.needsUnsubstitutedBridge && specialBridge.signature != substitutedOverrideSignature ->
|
||||
specialBridge.copy(isSynthetic = true)
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
return specialBridge.copy(
|
||||
signature = computeJvmMethod(substitutedOverride),
|
||||
signature = substitutedOverrideSignature,
|
||||
substitutedParameterTypes = substitutedParameterTypes,
|
||||
substitutedReturnType = function.returnType
|
||||
substitutedReturnType = function.returnType,
|
||||
unsubstitutedSpecialBridge = unsubstitutedSpecialBridge
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user