Fix for https://youtrack.jetbrains.com/issue/KT-35940 + test
The bug was not taking into account implicit runtime DFG edges generated by associated objects in devirtualization analysis
This commit is contained in:
+17
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -257,6 +258,22 @@ internal object Devirtualization {
|
||||
} else {
|
||||
// String is implicitly created as argument of <main>.
|
||||
addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType))
|
||||
|
||||
// Conservatively assume each associated object could be instantiated.
|
||||
context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
context.getLayoutBuilder(declaration).associatedObjects.values.forEach {
|
||||
assert (it.kind == ClassKind.OBJECT) { "An object expected but was ${it.dump()}" }
|
||||
addInstantiatingClass(symbolTable.mapType(it.defaultType))
|
||||
}
|
||||
super.visitClass(declaration)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
// Traverse call graph from the roots.
|
||||
rootSet.forEach { dfs(it, it.returnParameter.type) }
|
||||
|
||||
@@ -45,14 +45,23 @@ object Baz
|
||||
fun testGlobalOptimizations1() {
|
||||
val i1 = I1ImplHolder::class.findAssociatedObject<Associated1>()!! as I1
|
||||
assertEquals(42, i1.foo())
|
||||
val c = C(null)
|
||||
i1.bar(c)
|
||||
assertEquals("zzz", c.list!![0])
|
||||
}
|
||||
|
||||
private class C(var list: List<String>?)
|
||||
|
||||
private interface I1 {
|
||||
fun foo(): Int
|
||||
fun bar(c: C)
|
||||
}
|
||||
|
||||
private object I1Impl : I1 {
|
||||
override fun foo() = 42
|
||||
override fun bar(c: C) {
|
||||
c.list = mutableListOf("zzz")
|
||||
}
|
||||
}
|
||||
|
||||
@Associated1(I1Impl::class)
|
||||
|
||||
Reference in New Issue
Block a user