JVM_IR: redirect to correct function in special brigdes

The fix in MethodSignatureMapper allows us to avoid the hack
with orphanedCopy() in BridgeLowering.
This commit is contained in:
Georgy Bronnikov
2019-11-20 18:26:44 +03:00
parent ef567c868e
commit 307c82e3a4
7 changed files with 15 additions and 19 deletions
@@ -346,7 +346,7 @@ class ExpressionCodegen(
classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol) classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol)
?.invoke(expression, this, data)?.let { return it } ?.invoke(expression, this, data)?.let { return it }
val callable = methodSignatureMapper.mapToCallableMethod(expression) val callable = methodSignatureMapper.mapToCallableMethod(irFunction, expression)
val callee = expression.symbol.owner val callee = expression.symbol.owner
val callGenerator = getOrCreateCallGenerator(expression, data, callable.signature) val callGenerator = getOrCreateCallGenerator(expression, data, callable.signature)
val asmType = if (expression is IrConstructorCall) typeMapper.mapTypeAsDeclaration(expression.type) else expression.asmType val asmType = if (expression is IrConstructorCall) typeMapper.mapTypeAsDeclaration(expression.type) else expression.asmType
@@ -286,7 +286,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
if (valueArgumentsCount > 0) (getValueArgument(0) as? IrConst<*>)?.value as? Boolean ?: true else null if (valueArgumentsCount > 0) (getValueArgument(0) as? IrConst<*>)?.value as? Boolean ?: true else null
} }
fun mapToCallableMethod(expression: IrFunctionAccessExpression): IrCallableMethod { fun mapToCallableMethod(caller: IrFunction, expression: IrFunctionAccessExpression): IrCallableMethod {
val callee = expression.symbol.owner.getOrCreateSuspendFunctionViewIfNeeded(context) val callee = expression.symbol.owner.getOrCreateSuspendFunctionViewIfNeeded(context)
val calleeParent = callee.parent val calleeParent = callee.parent
if (calleeParent !is IrClass) { if (calleeParent !is IrClass) {
@@ -316,14 +316,17 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
} }
val declaration = findSuperDeclaration(callee, isSuperCall) val declaration = findSuperDeclaration(callee, isSuperCall)
val signature = mapOverriddenSpecialBuiltinIfNeeded(declaration, isSuperCall) val signature = mapOverriddenSpecialBuiltinIfNeeded(caller, declaration, isSuperCall)
?: mapSignatureSkipGeneric(declaration) ?: mapSignatureSkipGeneric(declaration)
return IrCallableMethod(owner, invokeOpcode, signature, isInterface) return IrCallableMethod(owner, invokeOpcode, signature, isInterface)
} }
// TODO: get rid of this (probably via some special lowering) // TODO: get rid of this (probably via some special lowering)
private fun mapOverriddenSpecialBuiltinIfNeeded(callee: IrFunction, superCall: Boolean): JvmMethodSignature? { private fun mapOverriddenSpecialBuiltinIfNeeded(caller: IrFunction, callee: IrFunction, superCall: Boolean): JvmMethodSignature? {
// Do not remap special builtin methods when called from a bridge. The bridges are there to provide the
// remapped name or signature and forward to the actually declared method.
if (caller.origin == IrDeclarationOrigin.BRIDGE || caller.origin == IrDeclarationOrigin.BRIDGE_SPECIAL) return null
val overriddenSpecialBuiltinFunction = callee.descriptor.original.getOverriddenBuiltinReflectingJvmDescriptor() val overriddenSpecialBuiltinFunction = callee.descriptor.original.getOverriddenBuiltinReflectingJvmDescriptor()
if (overriddenSpecialBuiltinFunction != null && !superCall) { if (overriddenSpecialBuiltinFunction != null && !superCall) {
return mapSignatureSkipGeneric(context.referenceFunction(overriddenSpecialBuiltinFunction.original).owner) return mapSignatureSkipGeneric(context.referenceFunction(overriddenSpecialBuiltinFunction.original).owner)
@@ -120,6 +120,8 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
irFunction.overriddenSymbols.all { it.owner.getJvmName() != ourMethodName } irFunction.overriddenSymbols.all { it.owner.getJvmName() != ourMethodName }
) { ) {
// Bridges for abstract fake overrides whose JVM names differ from overridden functions. // Bridges for abstract fake overrides whose JVM names differ from overridden functions.
// The orphaned copy will get irFunction's name; the original irFunction will be renamed
// according to its overrides,
val bridge = irFunction.orphanedCopy() val bridge = irFunction.orphanedCopy()
irClass.declarations.add(bridge) irClass.declarations.add(bridge)
targetForCommonBridges = bridge targetForCommonBridges = bridge
@@ -320,18 +322,13 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
isSpecial: Boolean, isSpecial: Boolean,
invokeStatically: Boolean = false invokeStatically: Boolean = false
) { ) {
val maybeOrphanedTarget = if (isSpecial)
target.orphanedCopy()
else
target
context.createIrBuilder(symbol).run { context.createIrBuilder(symbol).run {
body = irBlockBody { body = irBlockBody {
if (specialMethodInfo != null) { if (specialMethodInfo != null) {
valueParameters.take(specialMethodInfo.argumentsToCheck).forEach { valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
addParameterTypeCheck( addParameterTypeCheck(
it, it,
maybeOrphanedTarget.valueParameters[it.index].type, target.valueParameters[it.index].type,
specialMethodInfo.defaultValueGenerator, specialMethodInfo.defaultValueGenerator,
this@createBridgeBody this@createBridgeBody
) )
@@ -341,17 +338,17 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
irImplicitCast( irImplicitCast(
IrCallImpl( IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET,
maybeOrphanedTarget.returnType, target.returnType,
maybeOrphanedTarget.symbol, origin = IrStatementOrigin.BRIDGE_DELEGATION, target.symbol, origin = IrStatementOrigin.BRIDGE_DELEGATION,
superQualifierSymbol = if (invokeStatically) maybeOrphanedTarget.parentAsClass.symbol else null superQualifierSymbol = if (invokeStatically) target.parentAsClass.symbol else null
).apply { ).apply {
passTypeArgumentsFrom(this@createBridgeBody) passTypeArgumentsFrom(this@createBridgeBody)
dispatchReceiver = irGet(dispatchReceiverParameter!!) dispatchReceiver = irGet(dispatchReceiverParameter!!)
extensionReceiverParameter?.let { extensionReceiverParameter?.let {
extensionReceiver = irImplicitCast(irGet(it), maybeOrphanedTarget.extensionReceiverParameter!!.type) extensionReceiver = irImplicitCast(irGet(it), target.extensionReceiverParameter!!.type)
} }
valueParameters.forEach { valueParameters.forEach {
putValueArgument(it.index, irImplicitCast(irGet(it), maybeOrphanedTarget.valueParameters[it.index].type)) putValueArgument(it.index, irImplicitCast(irGet(it), target.valueParameters[it.index].type))
} }
}, },
returnType returnType
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// FILE: J.java // FILE: J.java
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: J.java // FILE: J.java
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS // IGNORE_BACKEND: JS
private object NotEmptyMap : MutableMap<Any, Int> { private object NotEmptyMap : MutableMap<Any, Int> {
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: NATIVE // IGNORE_BACKEND: NATIVE
interface A0 { interface A0 {