Added some debug output to devirtualization
This commit is contained in:
+63
-4
@@ -396,6 +396,53 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
fun BitSet.copy() = BitSet(this.size()).apply { this.or(this@copy) }
|
fun BitSet.copy() = BitSet(this.size()).apply { this.or(this@copy) }
|
||||||
|
|
||||||
|
fun printPathToType(node: Node, type: Int) {
|
||||||
|
val visited = mutableSetOf<Node>()
|
||||||
|
val prev = mutableMapOf<Node, Node>()
|
||||||
|
var front = mutableListOf<Node>()
|
||||||
|
front.add(node)
|
||||||
|
visited.add(node)
|
||||||
|
lateinit var source: Node.Source
|
||||||
|
bfs@while (front.isNotEmpty()) {
|
||||||
|
val prevFront = front
|
||||||
|
front = mutableListOf()
|
||||||
|
for (from in prevFront) {
|
||||||
|
val reversedEdges = from.reversedEdges
|
||||||
|
if (reversedEdges != null)
|
||||||
|
for (to in reversedEdges) {
|
||||||
|
if (!visited.contains(to) && to.types[type]) {
|
||||||
|
visited.add(to)
|
||||||
|
prev[to] = from
|
||||||
|
front.add(to)
|
||||||
|
if (to is Node.Source) {
|
||||||
|
source = to
|
||||||
|
break@bfs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val reversedCastEdges = from.reversedCastEdges
|
||||||
|
if (reversedCastEdges != null)
|
||||||
|
for (castEdge in reversedCastEdges) {
|
||||||
|
val to = castEdge.node
|
||||||
|
if (!visited.contains(to) && castEdge.suitableTypes[type] && to.types[type]) {
|
||||||
|
visited.add(to)
|
||||||
|
prev[to] = from
|
||||||
|
front.add(to)
|
||||||
|
if (to is Node.Source) {
|
||||||
|
source = to
|
||||||
|
break@bfs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var cur: Node = source
|
||||||
|
do {
|
||||||
|
println(" #${cur.id}")
|
||||||
|
cur = prev[cur]!!
|
||||||
|
} while (cur != node)
|
||||||
|
}
|
||||||
|
|
||||||
fun analyze(): Map<DataFlowIR.Node.VirtualCall, DevirtualizedCallSite> {
|
fun analyze(): Map<DataFlowIR.Node.VirtualCall, DevirtualizedCallSite> {
|
||||||
val functions = moduleDFG.functions + externalModulesDFG.functionDFGs
|
val functions = moduleDFG.functions + externalModulesDFG.functionDFGs
|
||||||
val typeHierarchy = TypeHierarchy(symbolTable.classMap.values.filterIsInstance<DataFlowIR.Type.Declared>() +
|
val typeHierarchy = TypeHierarchy(symbolTable.classMap.values.filterIsInstance<DataFlowIR.Type.Declared>() +
|
||||||
@@ -532,19 +579,31 @@ internal object Devirtualization {
|
|||||||
.forEach { virtualCall ->
|
.forEach { virtualCall ->
|
||||||
assert (nodesMap[virtualCall] != null, { "Node for virtual call $virtualCall has not been built" })
|
assert (nodesMap[virtualCall] != null, { "Node for virtual call $virtualCall has not been built" })
|
||||||
val virtualCallSiteReceivers = constraintGraph.virtualCallSiteReceivers[virtualCall]
|
val virtualCallSiteReceivers = constraintGraph.virtualCallSiteReceivers[virtualCall]
|
||||||
if (virtualCallSiteReceivers == null || virtualCallSiteReceivers.receiver.types[VIRTUAL_TYPE_ID]) {
|
?: error("virtualCallSiteReceivers were not built for virtual call $virtualCall")
|
||||||
|
if (virtualCallSiteReceivers.receiver.types[VIRTUAL_TYPE_ID]) {
|
||||||
|
|
||||||
DEBUG_OUTPUT(0) {
|
DEBUG_OUTPUT(0) {
|
||||||
println("Unable to devirtualize callsite ${virtualCall.irCallSite?.let { ir2stringWhole(it) } ?: virtualCall.toString() }")
|
println("Unable to devirtualize callsite ${virtualCall.irCallSite?.let { ir2stringWhole(it) } ?: virtualCall.callee.toString() }")
|
||||||
println(" receiver is Virtual")
|
println(" receiver is Virtual")
|
||||||
|
printPathToType(virtualCallSiteReceivers.receiver, VIRTUAL_TYPE_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
DEBUG_OUTPUT(0) {
|
||||||
|
println("Devirtualized callsite ${virtualCall.irCallSite?.let { ir2stringWhole(it) } ?: virtualCall.callee.toString() }")
|
||||||
|
}
|
||||||
val possibleReceivers = allTypes.withIndex()
|
val possibleReceivers = allTypes.withIndex()
|
||||||
.filter { virtualCallSiteReceivers.receiver.types[it.index] }
|
.filter { virtualCallSiteReceivers.receiver.types[it.index] }
|
||||||
.map { it.value }
|
.filterNot { it.value == nothing }
|
||||||
.filterNot { it == nothing }
|
.map {
|
||||||
|
DEBUG_OUTPUT(0) {
|
||||||
|
println("Path to type ${it.value}")
|
||||||
|
printPathToType(virtualCallSiteReceivers.receiver, it.index)
|
||||||
|
}
|
||||||
|
it.value
|
||||||
|
}
|
||||||
|
|
||||||
val map = virtualCallSiteReceivers.devirtualizedCallees.associateBy({ it.receiverType }, { it })
|
val map = virtualCallSiteReceivers.devirtualizedCallees.associateBy({ it.receiverType }, { it })
|
||||||
result[virtualCall] = DevirtualizedCallSite(virtualCall.callee.resolved(), possibleReceivers.map { receiverType ->
|
result[virtualCall] = DevirtualizedCallSite(virtualCall.callee.resolved(), possibleReceivers.map { receiverType ->
|
||||||
assert (map[receiverType] != null) {
|
assert (map[receiverType] != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user