JVM_IR: do not do invokeinterface on Object methods
This works on HotSpot, but might confuse other VMs.
This commit is contained in:
@@ -280,6 +280,7 @@ private val jvmFilePhases =
|
||||
interfaceDelegationPhase then
|
||||
interfaceSuperCallsPhase then
|
||||
interfaceDefaultCallsPhase then
|
||||
interfaceObjectCallsPhase then
|
||||
|
||||
addContinuationPhase then
|
||||
|
||||
|
||||
+27
-4
@@ -127,11 +127,11 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
||||
super.visitSimpleFunction(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.hasInterfaceParent() =
|
||||
(parent as? IrClass)?.isInterface == true
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.hasInterfaceParent() =
|
||||
(parent as? IrClass)?.isInterface == true
|
||||
|
||||
internal val interfaceSuperCallsPhase = makeIrFilePhase(
|
||||
lowering = ::InterfaceSuperCallsLowering,
|
||||
name = "InterfaceSuperCalls",
|
||||
@@ -145,7 +145,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
if (expression.superQualifierSymbol?.owner?.isInterface != true) {
|
||||
if (expression.superQualifierSymbol?.owner?.isInterface != true || expression.isSuperToAny()) {
|
||||
return super.visitCall(expression)
|
||||
}
|
||||
|
||||
@@ -201,3 +201,26 @@ private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod() =
|
||||
(name.asString() == "clone" &&
|
||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||
valueParameters.isEmpty())
|
||||
|
||||
internal val interfaceObjectCallsPhase = makeIrFilePhase(
|
||||
lowering = ::InterfaceObjectCallsLowering,
|
||||
name = "InterfaceObjectCalls",
|
||||
description = "Resolve calls to Object methods on interface types to virtual methods"
|
||||
)
|
||||
|
||||
private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid(this)
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
if (expression.superQualifierSymbol != null && !expression.isSuperToAny())
|
||||
return super.visitCall(expression)
|
||||
val callee = expression.symbol.owner
|
||||
if (callee !is IrSimpleFunction || !callee.hasInterfaceParent())
|
||||
return super.visitCall(expression)
|
||||
val resolved = callee.resolveFakeOverride()
|
||||
if (resolved?.isMethodOfAny() != true)
|
||||
return super.visitCall(expression)
|
||||
val newSuperQualifierSymbol = context.irBuiltIns.anyClass.takeIf { expression.superQualifierSymbol != null }
|
||||
return super.visitCall(irCall(expression, resolved, newSuperQualifierSymbol = newSuperQualifierSymbol))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,20 +499,23 @@ fun irCall(
|
||||
call: IrFunctionAccessExpression,
|
||||
newFunction: IrFunction,
|
||||
receiversAsArguments: Boolean = false,
|
||||
argumentsAsReceivers: Boolean = false
|
||||
argumentsAsReceivers: Boolean = false,
|
||||
newSuperQualifierSymbol: IrClassSymbol? = null
|
||||
): IrCall =
|
||||
irCall(
|
||||
call,
|
||||
newFunction.symbol,
|
||||
receiversAsArguments,
|
||||
argumentsAsReceivers
|
||||
argumentsAsReceivers,
|
||||
newSuperQualifierSymbol
|
||||
)
|
||||
|
||||
fun irCall(
|
||||
call: IrFunctionAccessExpression,
|
||||
newSymbol: IrFunctionSymbol,
|
||||
receiversAsArguments: Boolean = false,
|
||||
argumentsAsReceivers: Boolean = false
|
||||
argumentsAsReceivers: Boolean = false,
|
||||
newSuperQualifierSymbol: IrClassSymbol? = null
|
||||
): IrCall =
|
||||
call.run {
|
||||
IrCallImpl(
|
||||
@@ -521,7 +524,8 @@ fun irCall(
|
||||
type,
|
||||
newSymbol,
|
||||
typeArgumentsCount,
|
||||
origin
|
||||
origin,
|
||||
newSuperQualifierSymbol
|
||||
).apply {
|
||||
copyTypeAndValueArgumentsFrom(
|
||||
call,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
interface I
|
||||
class C : I { fun foo() = super<I>.hashCode() }
|
||||
|
||||
fun box(): String {
|
||||
C().foo()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
val x: () -> Unit = {}
|
||||
val y = x.hashCode()
|
||||
|
||||
// 1 INVOKEVIRTUAL java/lang/Object.hashCode \(\)I
|
||||
// 0 INVOKEINTERFACE
|
||||
+5
@@ -26722,6 +26722,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
@@ -2299,6 +2299,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
public void testHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/hashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/ieee754")
|
||||
|
||||
+5
@@ -25539,6 +25539,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
+5
@@ -25221,6 +25221,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
+5
@@ -25221,6 +25221,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
+5
@@ -2344,6 +2344,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
public void testHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/hashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/interfaceHashCode.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/bytecodeText/ieee754")
|
||||
|
||||
Generated
+5
@@ -20747,6 +20747,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
+5
@@ -21882,6 +21882,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceHashCode.kt")
|
||||
public void testInterfaceHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/interfaceHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt14243.kt")
|
||||
public void testKt14243() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||
|
||||
Reference in New Issue
Block a user