Make Node's edges be nullable and point to null instead of empty list
This commit is contained in:
committed by
Pavel Punegov
parent
67385f3096
commit
f517d5b4a3
+5
-5
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
internal interface DirectedGraphNode<out K> {
|
||||
val key: K
|
||||
val directEdges: List<K>
|
||||
val reversedEdges: List<K>
|
||||
val directEdges: List<K>?
|
||||
val reversedEdges: List<K>?
|
||||
}
|
||||
|
||||
internal interface DirectedGraph<K, out N: DirectedGraphNode<K>> {
|
||||
@@ -70,7 +70,7 @@ internal class DirectedGraphCondensationBuilder<K, out N: DirectedGraphNode<K>>(
|
||||
|
||||
private fun findOrder(node: N) {
|
||||
visited += node.key
|
||||
node.directEdges.forEach {
|
||||
node.directEdges?.forEach {
|
||||
if (!visited.contains(it))
|
||||
findOrder(graph.get(it))
|
||||
}
|
||||
@@ -80,7 +80,7 @@ internal class DirectedGraphCondensationBuilder<K, out N: DirectedGraphNode<K>>(
|
||||
private fun paint(node: N, multiNode: MutableSet<K>) {
|
||||
visited += node.key
|
||||
multiNode += node.key
|
||||
node.reversedEdges.forEach {
|
||||
node.reversedEdges?.forEach {
|
||||
if (!visited.contains(it))
|
||||
paint(graph.get(it), multiNode)
|
||||
}
|
||||
@@ -89,7 +89,7 @@ internal class DirectedGraphCondensationBuilder<K, out N: DirectedGraphNode<K>>(
|
||||
private fun findMultiNodesOrder(node: DirectedGraphMultiNode<K>) {
|
||||
visited.addAll(node.nodes)
|
||||
node.nodes.forEach {
|
||||
graph.get(it).directEdges.forEach {
|
||||
graph.get(it).directEdges?.forEach {
|
||||
if (!visited.contains(it))
|
||||
findMultiNodesOrder(nodeToMultiNodeMap[graph.get(it)]!!)
|
||||
}
|
||||
|
||||
+25
-20
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
// Devirtualization analysis is performed using Variable Type Analysis algorithm.
|
||||
// See http://web.cs.ucla.edu/~palsberg/tba/papers/sundaresan-et-al-oopsla00.pdf for details.
|
||||
@@ -103,25 +104,29 @@ internal object Devirtualization {
|
||||
private val symbolTable = moduleDFG.symbolTable
|
||||
|
||||
sealed class Node(val id: Int) : DirectedGraphNode<Node> {
|
||||
override val directEdges = mutableListOf<Node>()
|
||||
override val reversedEdges = mutableListOf<Node>()
|
||||
override var directEdges: MutableList<Node>? = null
|
||||
override var reversedEdges : MutableList<Node>? = null
|
||||
override val key get() = this
|
||||
|
||||
val directCastEdges = mutableListOf<CastEdge>()
|
||||
val reversedCastEdges = mutableListOf<CastEdge>()
|
||||
var directCastEdges: MutableList<CastEdge>? = null
|
||||
var reversedCastEdges: MutableList<CastEdge>? = null
|
||||
|
||||
val types = BitSet()
|
||||
|
||||
var priority = -1
|
||||
|
||||
fun addEdge(node: Node) {
|
||||
directEdges += node
|
||||
node.reversedEdges += this
|
||||
if (directEdges == null) directEdges = ArrayList(1)
|
||||
directEdges!!.add(node)
|
||||
if (node.reversedEdges == null) node.reversedEdges = ArrayList(1)
|
||||
node.reversedEdges!!.add(this)
|
||||
}
|
||||
|
||||
fun addCastEdge(edge: CastEdge) {
|
||||
directCastEdges += edge
|
||||
edge.node.reversedCastEdges += CastEdge(this, edge.suitableTypes)
|
||||
if (directCastEdges == null) directCastEdges = ArrayList(1)
|
||||
directCastEdges!!.add(edge)
|
||||
if (edge.node.reversedCastEdges == null) edge.node.reversedCastEdges = ArrayList(1)
|
||||
edge.node.reversedCastEdges!!.add(CastEdge(this, edge.suitableTypes))
|
||||
}
|
||||
|
||||
abstract fun toString(allTypes: List<DataFlowIR.Type.Declared>): String
|
||||
@@ -407,10 +412,10 @@ internal object Devirtualization {
|
||||
println("FULL CONSTRAINT GRAPH")
|
||||
constraintGraph.nodes.forEach {
|
||||
println(" NODE #${it.id}")
|
||||
it.directEdges.forEach {
|
||||
it.directEdges?.forEach {
|
||||
println(" EDGE: #${it.id}z")
|
||||
}
|
||||
it.directCastEdges.forEach {
|
||||
it.directCastEdges?.forEach {
|
||||
println(" CAST EDGE: #${it.node.id}z casted to ${it.suitableTypes.format(allTypes)}")
|
||||
}
|
||||
allTypes.forEachIndexed { index, type ->
|
||||
@@ -422,14 +427,14 @@ internal object Devirtualization {
|
||||
|
||||
constraintGraph.nodes.forEach {
|
||||
if (it is Node.Source) {
|
||||
assert(it.reversedEdges.isEmpty(), { "A source node #${it.id} has incoming edges" })
|
||||
assert(it.reversedCastEdges.isEmpty(), { "A source node #${it.id} has incoming edges" })
|
||||
assert(it.reversedEdges?.isEmpty() ?: true, { "A source node #${it.id} has incoming edges" })
|
||||
assert(it.reversedCastEdges?.isEmpty() ?: true, { "A source node #${it.id} has incoming edges" })
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_OUTPUT(0) {
|
||||
println("CONSTRAINT GRAPH: ${constraintGraph.nodes.size} nodes, " +
|
||||
"${constraintGraph.nodes.sumBy { it.directEdges.size + it.directCastEdges.size } } edges")
|
||||
"${constraintGraph.nodes.sumBy { (it.directEdges?.size ?: 0) + (it.directCastEdges?.size ?: 0) } } edges")
|
||||
}
|
||||
|
||||
val topologicalOrder = DirectedGraphCondensationBuilder(constraintGraph).build().topologicalOrder
|
||||
@@ -453,10 +458,10 @@ internal object Devirtualization {
|
||||
continue // A source has no incoming edges.
|
||||
val types = BitSet()
|
||||
for (node in multiNode.nodes) {
|
||||
node.reversedEdges.forEach { types.or(it.types) }
|
||||
node.reversedEdges?.forEach { types.or(it.types) }
|
||||
node.reversedCastEdges
|
||||
.filter { it.node.priority < node.priority } // Doesn't contradict topological order.
|
||||
.forEach {
|
||||
?.filter { it.node.priority < node.priority } // Doesn't contradict topological order.
|
||||
?.forEach {
|
||||
val sourceTypes = it.node.types.copy()
|
||||
sourceTypes.and(it.suitableTypes)
|
||||
types.or(sourceTypes)
|
||||
@@ -468,20 +473,20 @@ internal object Devirtualization {
|
||||
val badEdges = mutableListOf<Pair<Node, Node.CastEdge>>()
|
||||
for (node in constraintGraph.nodes) {
|
||||
node.directCastEdges
|
||||
.filter { it.node.priority < node.priority } // Contradicts topological order.
|
||||
.forEach { badEdges += node to it }
|
||||
?.filter { it.node.priority < node.priority } // Contradicts topological order.
|
||||
?.forEach { badEdges += node to it }
|
||||
}
|
||||
badEdges.sortBy { it.second.node.priority } // Heuristic.
|
||||
|
||||
do {
|
||||
fun propagateTypes(node: Node, types: BitSet) {
|
||||
node.types.or(types)
|
||||
for (edge in node.directEdges) {
|
||||
node.directEdges?.forEach { edge ->
|
||||
val missingTypes = types.copy().apply { andNot(edge.types) }
|
||||
if (!missingTypes.isEmpty)
|
||||
propagateTypes(edge, missingTypes)
|
||||
}
|
||||
for (castEdge in node.directCastEdges) {
|
||||
node.directCastEdges?.forEach { castEdge ->
|
||||
val missingTypes = types.copy().apply { andNot(castEdge.node.types) }
|
||||
missingTypes.and(castEdge.suitableTypes)
|
||||
if (!missingTypes.isEmpty)
|
||||
|
||||
Reference in New Issue
Block a user