From 52f9378bd884936f4ee12fb339e61c3d955f60f1 Mon Sep 17 00:00:00 2001 From: Alistair Michael Date: Fri, 3 Nov 2023 16:11:24 +1000 Subject: [PATCH 1/3] add linkedhashset worklist --- .../analysis/solvers/FixPointSolver.scala | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/scala/analysis/solvers/FixPointSolver.scala b/src/main/scala/analysis/solvers/FixPointSolver.scala index 064a3c619..635ae1bb2 100644 --- a/src/main/scala/analysis/solvers/FixPointSolver.scala +++ b/src/main/scala/analysis/solvers/FixPointSolver.scala @@ -2,6 +2,7 @@ package analysis.solvers import analysis._ import scala.collection.immutable.ListSet +import scala.collection.mutable.LinkedHashSet /** Base trait for lattice solvers. */ @@ -75,10 +76,15 @@ trait Worklist[N]: */ def run(first: Set[N], intra: Boolean): Unit -/** A simple worklist algorithm based on `scala.collection.immutable.ListSet`. +/** A simple n^2 worklist algorithm based on `scala.collection.immutable.ListSet`. * * @tparam N * type of the elements in the worklist. + * + * Note: + * add(m) is O(n * m) + * worklist.run() is O(|first|^2) + * - ListSet.tail() and ListSet.head() are both O(n) */ trait ListSetWorklist[N] extends Worklist[N]: @@ -96,12 +102,34 @@ trait ListSetWorklist[N] extends Worklist[N]: worklist = worklist.tail process(n, intra) + +/** A more performant worklist algorithm. + * + * @tparam N + * type of the elements in the worklist. + */ +trait LinkedHashSetWorklist[N] extends Worklist[N]: + private val worklist = new LinkedHashSet[N] + + def add(n: N) = + worklist += n + + def add(ns: Set[N]) = worklist ++= ns + + def run(first: Set[N], intra: Boolean) = + worklist.addAll(first); + while (worklist.nonEmpty) do + val n = worklist.head; + worklist.remove(n) + process(n, intra) + + /** Base trait for worklist-based fixpoint solvers. * * @tparam N * type of the elements in the worklist. */ -trait WorklistFixpointSolver[N] extends MapLatticeSolver[N] with ListSetWorklist[N] with Dependencies[N]: +trait WorklistFixpointSolver[N] extends MapLatticeSolver[N] with LinkedHashSetWorklist[N] with Dependencies[N]: /** The current lattice element. */ var x: lattice.Element = _ @@ -147,7 +175,7 @@ trait SimpleWorklistFixpointSolver[N] extends WorklistFixpointSolver[N]: * Better implementation of the same thing * https://github.com/cs-au-dk/TIP/blob/master/src/tip/solvers/FixpointSolvers.scala#L311 */ -trait PushDownWorklistFixpointSolver[N] extends MapLatticeSolver[N] with ListSetWorklist[N] with Dependencies[N]: +trait PushDownWorklistFixpointSolver[N] extends MapLatticeSolver[N] with LinkedHashSetWorklist[N] with Dependencies[N]: /** The current lattice element. */ var x: lattice.Element = _ From f256ec86d8e6eac24a31e99801184e063eafef8c Mon Sep 17 00:00:00 2001 From: Alistair Michael Date: Mon, 6 Nov 2023 14:57:08 +1000 Subject: [PATCH 2/3] remove unneccessary lub --- src/main/scala/analysis/solvers/FixPointSolver.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/analysis/solvers/FixPointSolver.scala b/src/main/scala/analysis/solvers/FixPointSolver.scala index 635ae1bb2..73326cd10 100644 --- a/src/main/scala/analysis/solvers/FixPointSolver.scala +++ b/src/main/scala/analysis/solvers/FixPointSolver.scala @@ -197,8 +197,6 @@ trait PushDownWorklistFixpointSolver[N] extends MapLatticeSolver[N] with LinkedH val xn = x(n) val y = transfer(n, xn) - val t = lattice.sublattice.lub(xn, y) - for succ <- outdep(n, intra) do propagate(y, succ) /** Worklist-based fixpoint solver. From c66582418d325276382c9342b22fc98737591c16 Mon Sep 17 00:00:00 2001 From: Alistair Michael Date: Mon, 6 Nov 2023 14:59:57 +1000 Subject: [PATCH 3/3] use linkedhashset for simplemonotonicsolver --- src/main/scala/analysis/solvers/MonotonicSolver.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/analysis/solvers/MonotonicSolver.scala b/src/main/scala/analysis/solvers/MonotonicSolver.scala index 1c8f5aaeb..8eedcf8a5 100644 --- a/src/main/scala/analysis/solvers/MonotonicSolver.scala +++ b/src/main/scala/analysis/solvers/MonotonicSolver.scala @@ -2,7 +2,6 @@ package analysis.solvers import analysis._ -import scala.collection.immutable.ListSet import scala.collection.mutable /** Fixpoint solver. @@ -13,7 +12,7 @@ import scala.collection.mutable * TODO: investigate how to visit all reachable nodes at least once, then remove loopEscape. TODO: in longer term, add * a worklist to avoid processing nodes twice. */ -trait SimpleMonotonicSolver[N] extends MapLatticeSolver[N] with ListSetWorklist[N] with Dependencies[N]: +trait SimpleMonotonicSolver[N] extends MapLatticeSolver[N] with LinkedHashSetWorklist[N] with Dependencies[N]: /** The current lattice element. */ var x: lattice.Element = _