[K/N] Refactor devirtualization graph build to avoid too deep recursion

^KT-52386
This commit is contained in:
Pavel Kunyavskiy
2022-05-30 15:30:32 +02:00
committed by Space
parent 72b7d8da6d
commit 574562d9f9
@@ -644,7 +644,7 @@ internal object DevirtualizationAnalysis {
context.logMultiple { context.logMultiple {
+"Devirtualized from current module:" +"Devirtualized from current module:"
result.forEach { virtualCall, devirtualizedCallSite -> result.forEach { (virtualCall, devirtualizedCallSite) ->
if (virtualCall.irCallSite != null) { if (virtualCall.irCallSite != null) {
+"DEVIRTUALIZED" +"DEVIRTUALIZED"
+"FUNCTION: ${devirtualizedCallSite.second}" +"FUNCTION: ${devirtualizedCallSite.second}"
@@ -656,7 +656,7 @@ internal object DevirtualizationAnalysis {
} }
} }
+"Devirtualized from external modules:" +"Devirtualized from external modules:"
result.forEach { virtualCall, devirtualizedCallSite -> result.forEach { (virtualCall, devirtualizedCallSite) ->
if (virtualCall.irCallSite == null) { if (virtualCall.irCallSite == null) {
+"DEVIRTUALIZED" +"DEVIRTUALIZED"
+"FUNCTION: ${devirtualizedCallSite.second}" +"FUNCTION: ${devirtualizedCallSite.second}"
@@ -896,7 +896,12 @@ internal object DevirtualizationAnalysis {
val body = function.body val body = function.body
val functionConstraintGraph = constraintGraph.functions[symbol]!! val functionConstraintGraph = constraintGraph.functions[symbol]!!
body.forEachNonScopeNode { dfgNodeToConstraintNode(functionConstraintGraph, it) } body.forEachNonScopeNode {
val node = dfgNodeToConstraintNode(functionConstraintGraph, it)
if (it is DataFlowIR.Node.Variable) {
generateVariableEdges(functionConstraintGraph, it, node)
}
}
addEdge(functionNodesMap[body.returns]!!, functionConstraintGraph.returns) addEdge(functionNodesMap[body.returns]!!, functionConstraintGraph.returns)
addEdge(functionNodesMap[body.throws]!!, functionConstraintGraph.throws) addEdge(functionNodesMap[body.throws]!!, functionConstraintGraph.throws)
@@ -1077,9 +1082,19 @@ internal object DevirtualizationAnalysis {
} }
} }
fun generateVariableEdges(function: Function, node: DataFlowIR.Node.Variable, variableNode: Node) {
for (value in node.values) {
addEdge(edgeToConstraintNode(function, value), variableNode)
}
if (node.kind == DataFlowIR.VariableKind.CatchParameter)
function.throws.addCastEdge(createCastEdge(variableNode, node.type.resolved()))
}
/** /**
* Takes a function DFG's node and creates a constraint graph node corresponding to it. * Takes a function DFG's node and creates a constraint graph node corresponding to it.
* Also creates all necessary edges. * Also creates all necessary edges, except for variable nodes.
* For variable nodes edges must be created separately, otherwise recursion can be too deep.
*/ */
private fun dfgNodeToConstraintNode(function: Function, node: DataFlowIR.Node): Node { private fun dfgNodeToConstraintNode(function: Function, node: DataFlowIR.Node): Node {
@@ -1102,17 +1117,9 @@ internal object DevirtualizationAnalysis {
fun writeField(field: DataFlowIR.Field, value: Node) = addEdge(value, fieldNode(field)) fun writeField(field: DataFlowIR.Field, value: Node) = addEdge(value, fieldNode(field))
if (node is DataFlowIR.Node.Variable && node.kind != DataFlowIR.VariableKind.Temporary) { if (node is DataFlowIR.Node.Variable && node.kind != DataFlowIR.VariableKind.Temporary) {
var variableNode = variables[node] return variables.getOrPut(node) {
if (variableNode == null) { ordinaryNode { "Variable\$${function.symbol}" }
variableNode = ordinaryNode { "Variable\$${function.symbol}" }
variables[node] = variableNode
for (value in node.values) {
addEdge(edgeToConstraintNode(value), variableNode)
}
if (node.kind == DataFlowIR.VariableKind.CatchParameter)
function.throws.addCastEdge(createCastEdge(variableNode, node.type.resolved()))
} }
return variableNode
} }
return functionNodesMap.getOrPut(node) { return functionNodesMap.getOrPut(node) {