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
|
interfaceDelegationPhase then
|
||||||
interfaceSuperCallsPhase then
|
interfaceSuperCallsPhase then
|
||||||
interfaceDefaultCallsPhase then
|
interfaceDefaultCallsPhase then
|
||||||
|
interfaceObjectCallsPhase then
|
||||||
|
|
||||||
addContinuationPhase then
|
addContinuationPhase then
|
||||||
|
|
||||||
|
|||||||
+27
-4
@@ -127,11 +127,11 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
|
|||||||
super.visitSimpleFunction(declaration)
|
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(
|
internal val interfaceSuperCallsPhase = makeIrFilePhase(
|
||||||
lowering = ::InterfaceSuperCallsLowering,
|
lowering = ::InterfaceSuperCallsLowering,
|
||||||
name = "InterfaceSuperCalls",
|
name = "InterfaceSuperCalls",
|
||||||
@@ -145,7 +145,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (expression.superQualifierSymbol?.owner?.isInterface != true) {
|
if (expression.superQualifierSymbol?.owner?.isInterface != true || expression.isSuperToAny()) {
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,3 +201,26 @@ private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod() =
|
|||||||
(name.asString() == "clone" &&
|
(name.asString() == "clone" &&
|
||||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||||
valueParameters.isEmpty())
|
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,
|
call: IrFunctionAccessExpression,
|
||||||
newFunction: IrFunction,
|
newFunction: IrFunction,
|
||||||
receiversAsArguments: Boolean = false,
|
receiversAsArguments: Boolean = false,
|
||||||
argumentsAsReceivers: Boolean = false
|
argumentsAsReceivers: Boolean = false,
|
||||||
|
newSuperQualifierSymbol: IrClassSymbol? = null
|
||||||
): IrCall =
|
): IrCall =
|
||||||
irCall(
|
irCall(
|
||||||
call,
|
call,
|
||||||
newFunction.symbol,
|
newFunction.symbol,
|
||||||
receiversAsArguments,
|
receiversAsArguments,
|
||||||
argumentsAsReceivers
|
argumentsAsReceivers,
|
||||||
|
newSuperQualifierSymbol
|
||||||
)
|
)
|
||||||
|
|
||||||
fun irCall(
|
fun irCall(
|
||||||
call: IrFunctionAccessExpression,
|
call: IrFunctionAccessExpression,
|
||||||
newSymbol: IrFunctionSymbol,
|
newSymbol: IrFunctionSymbol,
|
||||||
receiversAsArguments: Boolean = false,
|
receiversAsArguments: Boolean = false,
|
||||||
argumentsAsReceivers: Boolean = false
|
argumentsAsReceivers: Boolean = false,
|
||||||
|
newSuperQualifierSymbol: IrClassSymbol? = null
|
||||||
): IrCall =
|
): IrCall =
|
||||||
call.run {
|
call.run {
|
||||||
IrCallImpl(
|
IrCallImpl(
|
||||||
@@ -521,7 +524,8 @@ fun irCall(
|
|||||||
type,
|
type,
|
||||||
newSymbol,
|
newSymbol,
|
||||||
typeArgumentsCount,
|
typeArgumentsCount,
|
||||||
origin
|
origin,
|
||||||
|
newSuperQualifierSymbol
|
||||||
).apply {
|
).apply {
|
||||||
copyTypeAndValueArgumentsFrom(
|
copyTypeAndValueArgumentsFrom(
|
||||||
call,
|
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");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||||
|
|||||||
@@ -2299,6 +2299,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
public void testHashCode() throws Exception {
|
public void testHashCode() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/hashCode.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/ieee754")
|
||||||
|
|||||||
+5
@@ -25539,6 +25539,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/super/innerClassQualifiedPropertyAccess.kt");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
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");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
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");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||||
|
|||||||
+5
@@ -2344,6 +2344,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
public void testHashCode() throws Exception {
|
public void testHashCode() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/hashCode/hashCode.kt");
|
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")
|
@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");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
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");
|
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")
|
@TestMetadata("kt14243.kt")
|
||||||
public void testKt14243() throws Exception {
|
public void testKt14243() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
runTest("compiler/testData/codegen/box/super/kt14243.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user