Skip to content

Commit

Permalink
Using IdentityHashSet in EOG pass to remove superfluous EOG nodes (#…
Browse files Browse the repository at this point in the history
…1275)

* EOG pass speedup

There was an issue that massivly slowed down the EOG pass for programs that a LOT (>500.000) EOG nodes. Now we are using an identity hash set instead of a regular hash set to store the set of unique EOG nodes.

* Add some comments

* revert js change

---------

Co-authored-by: Alexander Kuechler <[email protected]>
  • Loading branch information
oxisto and KuechA authored Aug 9, 2023
1 parent ef8df7e commit 6192503
Showing 1 changed file with 17 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import de.fraunhofer.aisec.cpg.graph.scopes.*
import de.fraunhofer.aisec.cpg.graph.statements.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.helpers.IdentitySet
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import de.fraunhofer.aisec.cpg.helpers.Util
import de.fraunhofer.aisec.cpg.passes.order.DependsOn
Expand Down Expand Up @@ -177,28 +178,34 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa

/**
* Removes EOG edges by first building the negative set of nodes that cannot be visited and then
* remove there outgoing edges.In contrast to truncateLooseEdges this also removes cycles.
* remove there outgoing edges. This also removes cycles.
*/
protected fun removeUnreachableEOGEdges(tu: TranslationUnitDeclaration) {
val eognodes =
SubgraphWalker.flattenAST(tu)
.filter { it.prevEOG.isNotEmpty() || it.nextEOG.isNotEmpty() }
.toMutableList()
// All nodes which have an eog edge
val eogNodes = IdentitySet<Node>()
eogNodes.addAll(
SubgraphWalker.flattenAST(tu).filter {
it.prevEOG.isNotEmpty() || it.nextEOG.isNotEmpty()
}
)
// only eog entry points
var validStarts =
eognodes
eogNodes
.filter { node ->
node is FunctionDeclaration ||
node is RecordDeclaration ||
node is NamespaceDeclaration ||
node is TranslationUnitDeclaration
}
.toSet()
// Remove all nodes from eogNodes which are reachable from validStarts and transitively.
while (validStarts.isNotEmpty()) {
eognodes.removeAll(validStarts)
validStarts = validStarts.flatMap { it.nextEOG }.filter { it in eognodes }.toSet()
eogNodes.removeAll(validStarts)
validStarts = validStarts.flatMap { it.nextEOG }.filter { it in eogNodes }.toSet()
}
// remaining eognodes were not visited and have to be removed from the EOG
for (unvisitedNode in eognodes) {
// The remaining nodes are unreachable from the entry points. We delete their outgoing EOG
// edges.
for (unvisitedNode in eogNodes) {
unvisitedNode.nextEOGEdges.forEach { next ->
next.end.removePrevEOGEntry(unvisitedNode)
}
Expand Down

0 comments on commit 6192503

Please sign in to comment.