ast pool implementation (#184)

This commit is contained in:
Josef 2019-09-26 10:06:25 +02:00 committed by GitHub
parent 6e9c557682
commit 48e016f515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 8 deletions

View File

@ -0,0 +1,32 @@
package org.enso.data
import scala.reflect.internal.util.WeakHashSet
/** Thread safe pool for objects with 1-1 hashcode-object mapping.
*
* Useful for not having lots of duplicate objects in memory.
*
* As an example it can be used to pool small strings:
* `pool.get("Hi"); pool.get("Hi"); pool.get("Hi")`
* will always return pointer to the first instace "Hi".
*
* Once nobody except [[Pool]] holds references to the first
* "Hi" instance, it will get automatically removed from
* it on the next garbage collection call.
*
* The current usecase is pooling of AST nodes,
* achieving up to 30% memory savings for nontrivial input programs.
*/
final class Pool[T <: AnyRef] {
private val astPool = WeakHashSet[T]()
/** Returns object from pool such that `object == t`, or puts t into pool
* and returns it, if no such object is found.
*
* The asymptotic complexity is almost identical to the of HashSet.get (logN)
* The function is thread safe and throws an error when t is null
*/
def get(t: T): T = synchronized(astPool.findEntryOrUpdate(t))
}

View File

@ -6,9 +6,7 @@ import cats.Functor
import cats.derived._
import cats.implicits._
import org.enso.data.List1._
import org.enso.data.List1
import org.enso.data.Shifted
import org.enso.data.Tree
import org.enso.data.{List1, Pool, Shifted, Tree}
import org.enso.lint.Unused
import org.enso.syntax.text.ast.Repr.R
import org.enso.syntax.text.ast.Repr._
@ -477,30 +475,35 @@ object AST {
val any = UnapplyByType[Ident]
object Blank {
private val blank = BlankOf[AST]()
val any = UnapplyByType[Blank]
def unapply(t: AST) = Unapply[Blank].run(_ => true)(t)
def apply(): Blank = BlankOf[AST]()
def apply(): Blank = blank
}
object Var {
private val pool = new Pool[VarOf[AST]]()
val any = UnapplyByType[Var]
def unapply(t: AST) = Unapply[Var].run(_.name)(t)
def apply(name: String): Var = VarOf[AST](name)
def apply(name: String): Var = pool.get(VarOf[AST](name))
}
object Cons {
private val pool = new Pool[ConsOf[AST]]()
val any = UnapplyByType[Cons]
def unapply(t: AST) = Unapply[Cons].run(_.name)(t)
def apply(name: String): Cons = ConsOf[AST](name)
def apply(name: String): Cons = pool.get(ConsOf[AST](name))
}
object Mod {
private val pool = new Pool[ModOf[AST]]()
val any = UnapplyByType[Mod]
def unapply(t: AST) = Unapply[Mod].run(_.name)(t)
def apply(name: String): Mod = ModOf[AST](name)
def apply(name: String): Mod = pool.get(ModOf[AST](name))
}
object Opr {
private val pool = new Pool[OprOf[AST]]()
val app = Opr(" ")
val any = UnapplyByType[Opr]
def unapply(t: AST) = Unapply[Opr].run(_.name)(t)
def apply(name: String): Opr = OprOf[AST](name)
def apply(name: String): Opr = pool.get(OprOf[AST](name))
}
///////////////////////