From 0338b5aa0fbd55ffa28cabd41f257e830a678431 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 22 Jan 2020 14:05:15 +0300 Subject: [PATCH] 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 --- .../konan/optimizations/Devirtualization.kt | 17 +++++++++++++++++ .../associatedObjects/associatedObjects1.kt | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index 1fd901399f7..cbe6b66d269 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -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
. 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) } diff --git a/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt b/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt index 92f5c9123cc..a239b8ba0fa 100644 --- a/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt +++ b/backend.native/tests/codegen/associatedObjects/associatedObjects1.kt @@ -45,14 +45,23 @@ object Baz fun testGlobalOptimizations1() { val i1 = I1ImplHolder::class.findAssociatedObject()!! as I1 assertEquals(42, i1.foo()) + val c = C(null) + i1.bar(c) + assertEquals("zzz", c.list!![0]) } +private class C(var list: List?) + 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)