[devirtualization] Reduced the number of cast nodes

This commit is contained in:
Igor Chevdar
2020-03-04 16:33:08 +03:00
parent eef026fe55
commit 7a437a6a84
@@ -885,7 +885,7 @@ internal object Devirtualization {
val callee = receiverType.calleeAt(virtualCall.virtualCall) val callee = receiverType.calleeAt(virtualCall.virtualCall)
doCall(virtualCall.caller, callee, virtualCall.arguments, doCall(virtualCall.caller, callee, virtualCall.arguments,
virtualCall.virtualCall.returnType.resolved()).addEdge(virtualCall.returnsNode) callee.returnParameter.type.resolved()).addEdge(virtualCall.returnsNode)
} }
private fun checkSupertypes(type: DataFlowIR.Type.Declared, private fun checkSupertypes(type: DataFlowIR.Type.Declared,
@@ -934,6 +934,12 @@ internal object Devirtualization {
return castNode return castNode
} }
private fun castIfNeeded(function: Function, node: Node,
nodeType: DataFlowIR.Type.Declared, type: DataFlowIR.Type.Declared) =
if (!useTypes || type == nodeType)
node
else doCast(function, node, type)
private fun edgeToConstraintNode(function: Function, private fun edgeToConstraintNode(function: Function,
edge: DataFlowIR.Edge): Node { edge: DataFlowIR.Edge): Node {
val result = dfgNodeToConstraintNode(function, edge.node) val result = dfgNodeToConstraintNode(function, edge.node)
@@ -949,10 +955,7 @@ internal object Devirtualization {
callee.parameters.forEachIndexed { index, parameter -> callee.parameters.forEachIndexed { index, parameter ->
arguments[index].addEdge(parameter) arguments[index].addEdge(parameter)
} }
return if (!useTypes || returnType == callee.symbol.returnParameter.type.resolved()) return castIfNeeded(caller, callee.returns, callee.symbol.returnParameter.type.resolved(), returnType)
callee.returns
else
doCast(caller, callee.returns, returnType)
} }
fun doCall(caller: Function, callee: DataFlowIR.FunctionSymbol, fun doCall(caller: Function, callee: DataFlowIR.FunctionSymbol,
@@ -1092,7 +1095,7 @@ internal object Devirtualization {
ConstraintGraphVirtualCall(function, node, arguments, returnsNode)) ConstraintGraphVirtualCall(function, node, arguments, returnsNode))
forEachBitInBoth(typeHierarchy.inheritorsOf(receiverType), instantiatingClasses) { forEachBitInBoth(typeHierarchy.inheritorsOf(receiverType), instantiatingClasses) {
val actualCallee = allTypes[it].calleeAt(node) val actualCallee = allTypes[it].calleeAt(node)
doCall(actualCallee, arguments, returnType).addEdge(returnsNode) doCall(actualCallee, arguments, actualCallee.returnParameter.type.resolved()).addEdge(returnsNode)
} }
// Add cast to [Virtual] edge from receiver to returns, if return type is not final. // 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. // With this we're reflecting the fact that unknown function can return anything.
@@ -1103,7 +1106,7 @@ internal object Devirtualization {
receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter)) receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter))
constraintGraph.virtualCallSiteReceivers[node] = receiverNode constraintGraph.virtualCallSiteReceivers[node] = receiverNode
returnsNode castIfNeeded(function, returnsNode, node.callee.returnParameter.type.resolved(), returnType)
} }
is DataFlowIR.Node.Singleton -> { is DataFlowIR.Node.Singleton -> {