[K/N] Fixed a bug in escape analysis

#KT-59693 Fixed
This commit is contained in:
Igor Chevdar
2023-06-30 12:07:09 +03:00
committed by Space Team
parent 0bbf16dff4
commit 4f859a634e
@@ -1175,11 +1175,11 @@ internal object EscapeAnalysis {
is PointsToGraphEdge.Assignment -> is PointsToGraphEdge.Assignment ->
compressedEdges += CompressedPointsToGraph.Edge(fromCompressedNode, toCompressedNode) compressedEdges += CompressedPointsToGraph.Edge(fromCompressedNode, toCompressedNode)
is PointsToGraphEdge.Field -> is PointsToGraphEdge.Field -> {
if (edge.node == from /* A loop */) { val next = fromCompressedNode.goto(edge.field)
compressedEdges += CompressedPointsToGraph.Edge( if (next != toCompressedNode) // Skip loops.
fromCompressedNode.goto(edge.field), toCompressedNode) compressedEdges += CompressedPointsToGraph.Edge(next, toCompressedNode)
} }
} }
} }
} }
@@ -1768,30 +1768,40 @@ internal object EscapeAnalysis {
nodeIds[drain] = drainFactory() nodeIds[drain] = drainFactory()
} }
var front = nodeIds.keys.toList() var front = nodeIds.keys.toMutableList()
while (front.isNotEmpty()) { do {
val nextFront = mutableListOf<PointsToGraphNode>() while (front.isNotEmpty()) {
for (node in front) { val nextFront = mutableListOf<PointsToGraphNode>()
val nodeId = nodeIds[node]!! for (node in front) {
node.edges.filterIsInstance<PointsToGraphEdge.Field>().forEach { edge -> val nodeId = nodeIds[node]!!
val field = edge.field node.edges.filterIsInstance<PointsToGraphEdge.Field>().forEach { edge ->
val nextNode = edge.node val field = edge.field
if (nextNode.drain in interestingDrains && nextNode != node /* Skip loops */) { val nextNode = edge.node
val nextNodeId = nodeId.goto(field) if (nextNode.drain in interestingDrains && nextNode != node /* Skip loops */) {
if (nodeIds[nextNode] != null) val nextNodeId = nodeId.goto(field)
error("Expected only one incoming field edge. ${nodeIds[nextNode]} != $nextNodeId") if (nodeIds[nextNode] == null) {
nodeIds[nextNode] = nextNodeId nodeIds[nextNode] = nextNodeId
if (nextNode.isDrain) if (nextNode.isDrain)
nextFront += nextNode nextFront += nextNode
}
}
} }
} }
front = nextFront
} }
front = nextFront
} // Find unpainted drain.
for (drain in interestingDrains) { for (drain in interestingDrains) {
if (nodeIds[drain] == null && drain.edges.any { it.node.drain in interestingDrains }) if (nodeIds[drain] == null
error("Drains have not been painted properly") // A little optimization - skip leaf drains.
} && drain.edges.any { it.node.drain in interestingDrains }
) {
nodeIds[drain] = drainFactory()
front += drain
break
}
}
} while (front.isNotEmpty()) // Loop until all drains have been painted.
return nodeIds return nodeIds
} }