JVM_IR: do not do invokeinterface on Object methods

This works on HotSpot, but might confuse other VMs.
This commit is contained in:
pyos
2019-12-10 11:05:31 +01:00
committed by max-kammerer
parent df0a86ea57
commit 498b41b148
13 changed files with 89 additions and 8 deletions
@@ -280,6 +280,7 @@ private val jvmFilePhases =
interfaceDelegationPhase then
interfaceSuperCallsPhase then
interfaceDefaultCallsPhase then
interfaceObjectCallsPhase then
addContinuationPhase then
@@ -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
@@ -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")
@@ -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");
@@ -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");
@@ -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");
@@ -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")
@@ -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");
@@ -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");