From 562c1f396129fb8c46d71966c407b29def5bdeed Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 8 Aug 2018 16:29:55 +0300 Subject: [PATCH] Fixed bug in devirtualization In a library fields of objects might be initialized by some of users with unknown type. --- .../konan/optimizations/Devirtualization.kt | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) 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 e0f3adf5f7c..2151670f927 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 @@ -172,7 +172,7 @@ internal object Devirtualization { val voidNode = addNode { Node.Ordinary(it, { "Void" }) } val virtualNode = addNode { Node.Source(it, VIRTUAL_TYPE_ID, { "Virtual" }) } - val arrayItemField = DataFlowIR.Field(null, symbolTable.mapClass(context.irBuiltIns.anyClass.owner), 1, "Array\$Item") + val arrayItemField = DataFlowIR.Field(null, symbolTable.mapClassReferenceType(context.irBuiltIns.anyClass.owner), 1, "Array\$Item") val functions = mutableMapOf() val concreteClasses = mutableMapOf() val externalFunctions = mutableMapOf() @@ -363,6 +363,14 @@ internal object Devirtualization { is DataFlowIR.Node.StaticCall -> dfs(node.callee) + is DataFlowIR.Node.FieldRead -> + if (entryPoint == null && node.field.type.isFinal) + addInstantiatingClass(node.field.type) + + is DataFlowIR.Node.FieldWrite -> + if (entryPoint == null && node.field.type.isFinal) + addInstantiatingClass(node.field.type) + is DataFlowIR.Node.VirtualCall -> { if (node.receiverType == DataFlowIR.Type.Virtual) continue@nodeLoop @@ -676,7 +684,19 @@ internal object Devirtualization { constraintGraph.concreteClasses.getOrPut(type) { sourceNode(concreteType(type)) { "Class\$$type" } } private fun fieldNode(field: DataFlowIR.Field) = - constraintGraph.fields.getOrPut(field) { ordinaryNode { "Field\$$field" } } + constraintGraph.fields.getOrPut(field) { + val fieldNode = ordinaryNode { "Field\$$field" } + if (entryPoint == null) { + // TODO: This is conservative. + val fieldType = field.type.resolved() + // Some user of our library might place some value into the field. + if (fieldType.isFinal) + concreteClass(fieldType).addEdge(fieldNode) + else + constraintGraph.virtualNode.addEdge(fieldNode) + } + fieldNode + } private var stack = mutableListOf() @@ -898,8 +918,6 @@ internal object Devirtualization { } // And throw anything. receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter)) - // And write to some array anything. TODO: This is conservative. - receiverNode.addCastEdge(Node.CastEdge(fieldNode(constraintGraph.arrayItemField), virtualTypeFilter)) if (callees.isEmpty() && returnType.isFinal && entryPoint == null) { // If we are in a library and facing final return type with no possible callees -