From 141fe9bb8bff265795c00306ac845bbadd531873 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 2 Jul 2019 17:12:21 +0300 Subject: [PATCH] Devirtuliazation: removed additional cast edges Looks like they are not needed, FE already handles these cases --- .../konan/optimizations/Devirtualization.kt | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 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 19664fe9d9d..6a1d02d3808 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 @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.types.IrType @@ -612,9 +611,11 @@ internal object Devirtualization { println("Devirtualized callsite " + (virtualCall.irCallSite?.let { ir2stringWhole(it) } ?: virtualCall.callee.toString())) } + val inheritorsOfReceiverType = virtualCallSiteReceivers.devirtualizedCallees.map { it.receiverType }.toSet() val possibleReceivers = allTypes.asSequence() .withIndex() .filter { virtualCallSiteReceivers.receiver.types[it.index] } + .filter { inheritorsOfReceiverType.contains(it.value) } .filterNot { it.value == nothing } .map { DEBUG_OUTPUT(0) { @@ -763,7 +764,7 @@ internal object Devirtualization { symbol.parameters.forEachIndexed { index, type -> val resolvedType = type.type.resolved() val node = if (!resolvedType.isFinal) - constraintGraph.virtualNode // TODO: May be do this only for a library? + constraintGraph.virtualNode // TODO: OBJC-INTEROP-GENERATED-CLASSES else concreteClass(resolvedType) node.addEdge(parameters[index]) @@ -836,8 +837,7 @@ internal object Devirtualization { fun doCall(callee: DataFlowIR.FunctionSymbol, arguments: List, - returnType: DataFlowIR.Type.Declared, - receiverType: DataFlowIR.Type.Declared?): Node { + returnType: DataFlowIR.Type.Declared): Node { val resolvedCallee = callee.resolved() val calleeConstraintGraph = createFunctionConstraintGraph(resolvedCallee, false) return if (calleeConstraintGraph == null) { @@ -848,6 +848,7 @@ internal object Devirtualization { else { constraintGraph.virtualNode.addEdge(fictitiousReturnNode) // TODO: Unconservative way - when we can use it? + // TODO: OBJC-INTEROP-GENERATED-CLASSES // typeHierarchy.inheritorsOf(returnType) // .filterNot { it.isAbstract } // .filter { instantiatingClasses.containsKey(it) } @@ -857,14 +858,7 @@ internal object Devirtualization { } } else { calleeConstraintGraph.throws.addEdge(function.throws) - if (!useTypes || receiverType == null || receiverType == callee.parameters[0].type.resolved()) - doCall(calleeConstraintGraph, arguments, returnType) - else { - val receiverNode = argumentToConstraintNode(arguments[0]) - doCall(calleeConstraintGraph, - listOf(doCast(function, receiverNode, receiverType)) + arguments.drop(1), - returnType) - } + doCall(calleeConstraintGraph, arguments, returnType) } } @@ -912,13 +906,12 @@ internal object Devirtualization { function.parameters[node.index] is DataFlowIR.Node.StaticCall -> - doCall(node.callee, node.arguments, node.returnType.resolved(), - node.receiverType?.resolved()) + doCall(node.callee, node.arguments, node.returnType.resolved()) is DataFlowIR.Node.NewObject -> { val returnType = node.constructedType.resolved() val instanceNode = concreteClass(returnType) - doCall(node.callee, listOf(instanceNode) + node.arguments, returnType, null) + doCall(node.callee, listOf(instanceNode) + node.arguments, returnType) instanceNode } @@ -960,12 +953,13 @@ internal object Devirtualization { val receiverNode = edgeToConstraintNode(node.arguments[0]) if (receiverType == DataFlowIR.Type.Virtual) constraintGraph.virtualNode.addEdge(receiverNode) - val castedReceiver = doCast(function, receiverNode, receiverType) + val castedReceiver = ordinaryNode { "CastedReceiver\$${function.symbol}" } + receiverNode.addEdge(castedReceiver) val arguments = listOf(castedReceiver) + node.arguments.drop(1) val returnsNode = ordinaryNode { "VirtualCallReturns\$${function.symbol}" } callees.forEachIndexed { index, actualCallee -> - doCall(actualCallee, arguments, returnType, possibleReceiverTypes[index]).addEdge(returnsNode) + doCall(actualCallee, arguments, returnType).addEdge(returnsNode) } // Add cast to [Virtual] edge from receiver to returns, if return type is not final. // With this we're reflecting the fact that unknown function can return anything. @@ -993,7 +987,7 @@ internal object Devirtualization { is DataFlowIR.Node.Singleton -> { val type = node.type.resolved() val instanceNode = concreteClass(type) - node.constructor?.let { doCall(it, listOf(instanceNode), type, null) } + node.constructor?.let { doCall(it, listOf(instanceNode), type) } instanceNode }