From c75af5cf5dd5967db0b3375fdb01fb6efed72fd6 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 14 Apr 2020 10:29:28 +0500 Subject: [PATCH] [devirtualization] Removed redundant code with associated objects + test It turned out that it is not needed to explicitly add all associated objects to instantiating classes since their constructors have been already added to the root set and all constructors have additional parameter () and its type will be added to instantiating classes since it is final for all objects --- .../konan/optimizations/Devirtualization.kt | 20 +++------ .../tests/objcexport/expectedLazy.h | 6 +++ backend.native/tests/objcexport/kt35940.kt | 44 +++++++++++++++++++ backend.native/tests/objcexport/kt35940.swift | 18 ++++++++ 4 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 backend.native/tests/objcexport/kt35940.kt create mode 100644 backend.native/tests/objcexport/kt35940.swift 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 b42a56d8d81..1532a88e7ed 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 @@ -97,7 +97,9 @@ internal object Devirtualization { moduleDFG.symbolTable.functionMap.values.filter { it.explicitlyExported } + externalModulesDFG.functionDFGs.keys.filter { it.explicitlyExported } - // Conservatively assume each associated object could be instantiated. + // Conservatively assume each associated object could be called. + // Note: for constructors there is additional parameter () and its type will be added + // to instantiating classes since all objects are final types. val associatedObjects = mutableListOf() context.irModule!!.acceptChildrenVoid(object: IrElementVisitorVoid { override fun visitElement(element: IrElement) { @@ -898,6 +900,8 @@ internal object Devirtualization { } if (entryPoint == null) { // For library assume all public non-abstract classes could be instantiated. + // Note: for constructors there is additional parameter () and for associated objects + // its type will be added to instantiating classes since all objects are final types. symbolTable.classMap.values .filterIsInstance() .filter { !it.isAbstract } @@ -907,20 +911,6 @@ internal object Devirtualization { addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()) addEdge(concreteClass(symbolTable.mapType(context.irBuiltIns.stringType).resolved()), fieldNode(constraintGraph.arrayItemField)) - // 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).resolved()) - } - super.visitClass(declaration) - } - }) } rootSet.forEach { createFunctionConstraintGraph(it, true) } while (stack.isNotEmpty()) { diff --git a/backend.native/tests/objcexport/expectedLazy.h b/backend.native/tests/objcexport/expectedLazy.h index a90ae1b33ce..a233bc6e11c 100644 --- a/backend.native/tests/objcexport/expectedLazy.h +++ b/backend.native/tests/objcexport/expectedLazy.h @@ -204,6 +204,12 @@ __attribute__((swift_name("GH4002Argument"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("Kt35940Kt"))) +@interface KtKt35940Kt : KtBase ++ (NSString *)testKt35940 __attribute__((swift_name("testKt35940()"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("LibraryKt"))) @interface KtLibraryKt : KtBase diff --git a/backend.native/tests/objcexport/kt35940.kt b/backend.native/tests/objcexport/kt35940.kt new file mode 100644 index 00000000000..7a032bfcdcf --- /dev/null +++ b/backend.native/tests/objcexport/kt35940.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package kt35940 + +import kotlin.reflect.* + +@OptIn(ExperimentalAssociatedObjects::class) +@AssociatedObjectKey +@Retention(AnnotationRetention.BINARY) +annotation class Associated(val kClass: KClass<*>) + +private interface I1 { + val s: String +} + +private class I1Impl : I1 { + override val s = "zzz" +} + +private class C(var i1: I1?) + +private interface I2 { + fun bar(c: C) +} + +private object I2Impl : I2 { + override fun bar(c: C) { + c.i1 = I1Impl() + } +} + +@Associated(I2Impl::class) +private class I2ImplHolder + +@OptIn(ExperimentalAssociatedObjects::class) +fun testKt35940(): String { + val i2 = I2ImplHolder::class.findAssociatedObject()!! as I2 + val c = C(null) + i2.bar(c) + return c.i1!!.s +} diff --git a/backend.native/tests/objcexport/kt35940.swift b/backend.native/tests/objcexport/kt35940.swift new file mode 100644 index 00000000000..6fba9a53182 --- /dev/null +++ b/backend.native/tests/objcexport/kt35940.swift @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +import Kt + +private func test1() throws { + try assertEquals(actual: Kt35940Kt.testKt35940(), expected: "zzz") +} + +class Kt35940Tests : SimpleTestProvider { + override init() { + super.init() + + test("Test1", test1) + } +} \ No newline at end of file