mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-09 00:21:47 +00:00
IR: Align Interface Defaults with Old Backend
Change the treatment of default implementations on interfaces in JVM compatibility mode. Previously, the IR backend moved the actual default implementation to the DefaultImpls class, and then bridged to it from the interface default. The old backend did the reverse, at the cost of an additional accessor, in order to gain better binary compatibility properties. See #2612 for discussion. The accessor needs to call a specific implementation, so must be performed through an `invokespecial`. We trick the SyntheticAccessorLowering into doing this for us, by marking the bridging call as a super call. We do this in want of an explicit `invokespecial` Ir Node. InterfaceDefaultCallsPhase previously assumed the old behaviour of the IR backend (that calls to default implementations, e.g. `foo$default` should target `DefaultImpls.foo$default`). But now the bridge to foo$default resides on `DefaultImpls` already, causing that pass to create a recursive loop. We cut that loop with a simple check.
This commit is contained in:
committed by
max-kammerer
parent
b5de625350
commit
d1c2862e27
@@ -1,5 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
// FULL_JDK
|
||||
|
||||
@@ -10,7 +9,7 @@ interface KInterface {
|
||||
}
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface.access\$test\$jd
|
||||
// 1 INVOKESTATIC KInterface.access\$test\$
|
||||
// 1 INVOKESTATIC KInterface.test\$default
|
||||
|
||||
// from $default
|
||||
|
||||
22
compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt
vendored
Normal file
22
compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface A {
|
||||
@JvmDefault
|
||||
fun foo() = "FAIL"
|
||||
}
|
||||
|
||||
interface Left : A { }
|
||||
interface Right : A {
|
||||
@JvmDefault
|
||||
override fun foo() = "OK"
|
||||
}
|
||||
|
||||
interface C : Left, Right {}
|
||||
|
||||
fun box(): String {
|
||||
val x = object : C {}
|
||||
return x.foo()
|
||||
}
|
||||
|
||||
// 0 INVOKESTATIC .*\$DefaultImpls\.foo
|
||||
@@ -1,5 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface KInterface {
|
||||
@@ -13,8 +12,8 @@ interface KInterface2 : KInterface {
|
||||
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface2.access\$test2\$jd
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$jd
|
||||
// 1 INVOKESTATIC KInterface2.access\$test2\$
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$
|
||||
|
||||
// 1 INVOKESPECIAL KInterface2.test2
|
||||
// 1 INVOKESPECIAL KInterface.test2
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface KInterface {
|
||||
@@ -14,11 +13,11 @@ interface KInterface2 : KInterface {
|
||||
abstract override fun test2(): String
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$jd
|
||||
// +
|
||||
// 0 INVOKESTATIC KInterface2.access\$test2\$jd
|
||||
// =
|
||||
// 1 INVOKESTATIC
|
||||
|
||||
// 1 INVOKESPECIAL KInterface.test2
|
||||
// 0 INVOKESPECIAL KInterface2.test2
|
||||
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$
|
||||
// +
|
||||
// 0 INVOKESTATIC KInterface2.access\$test2\$
|
||||
// =
|
||||
// 1 INVOKESTATIC KInterface
|
||||
@@ -1,5 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface KInterface {
|
||||
@@ -14,10 +13,10 @@ interface KInterface2 : KInterface {
|
||||
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface2.access\$getBar\$jd
|
||||
// 1 INVOKESTATIC KInterface2.access\$setBar\$jd
|
||||
// 1 INVOKESTATIC KInterface.access\$getBar\$jd
|
||||
// 1 INVOKESTATIC KInterface.access\$setBar\$jd
|
||||
// 1 INVOKESTATIC KInterface2.access\$getBar\$
|
||||
// 1 INVOKESTATIC KInterface2.access\$setBar\$
|
||||
// 1 INVOKESTATIC KInterface.access\$getBar\$
|
||||
// 1 INVOKESTATIC KInterface.access\$setBar\$
|
||||
|
||||
// 1 INVOKESPECIAL KInterface2.getBar
|
||||
// 1 INVOKESPECIAL KInterface2.setBar
|
||||
|
||||
Reference in New Issue
Block a user