summaryrefslogblamecommitdiff
path: root/examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/optimizer/IncOptimizer.scala
blob: d115618c28fcb78bdbe38b06f4848762782598f4 (plain) (tree)





























































































































































                                                                                   
/*                     __                                               *\
**     ________ ___   / /  ___      __ ____  Scala.js tools             **
**    / __/ __// _ | / /  / _ | __ / // __/  (c) 2013-2014, LAMP/EPFL   **
**  __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \    http://scala-js.org/       **
** /____/\___/_/ |_/____/_/ | |__/ /____/                               **
**                          |/____/                                     **
\*                                                                      */


package scala.scalajs.tools.optimizer

import scala.collection.{GenTraversableOnce, GenIterable}
import scala.collection.mutable

import scala.scalajs.tools.sem.Semantics

class IncOptimizer(semantics: Semantics) extends GenIncOptimizer(semantics) {

  protected object CollOps extends GenIncOptimizer.AbsCollOps {
    type Map[K, V] = mutable.Map[K, V]
    type ParMap[K, V] = mutable.Map[K, V]
    type AccMap[K, V] = mutable.Map[K, mutable.ListBuffer[V]]
    type ParIterable[V] = mutable.ListBuffer[V]
    type Addable[V] = mutable.ListBuffer[V]

    def emptyAccMap[K, V]: AccMap[K, V] = mutable.Map.empty
    def emptyMap[K, V]: Map[K, V] = mutable.Map.empty
    def emptyParMap[K, V]: ParMap[K, V] = mutable.Map.empty
    def emptyParIterable[V]: ParIterable[V] = mutable.ListBuffer.empty

    // Operations on ParMap
    def put[K, V](map: ParMap[K, V], k: K, v: V): Unit = map.put(k, v)
    def remove[K, V](map: ParMap[K, V], k: K): Option[V] = map.remove(k)

    def retain[K, V](map: ParMap[K, V])(p: (K, V) => Boolean): Unit =
      map.retain(p)

    // Operations on AccMap
    def acc[K, V](map: AccMap[K, V], k: K, v: V): Unit =
      map.getOrElseUpdate(k, mutable.ListBuffer.empty) += v

    def getAcc[K, V](map: AccMap[K, V], k: K): GenIterable[V] =
      map.getOrElse(k, Nil)

    def parFlatMapKeys[A, B](map: AccMap[A, _])(
        f: A => GenTraversableOnce[B]): GenIterable[B] =
      map.keys.flatMap(f).toList

    // Operations on ParIterable
    def prepAdd[V](it: ParIterable[V]): Addable[V] = it
    def add[V](addable: Addable[V], v: V): Unit = addable += v
    def finishAdd[V](addable: Addable[V]): ParIterable[V] = addable
  }

  private val _interfaces = mutable.Map.empty[String, InterfaceType]
  protected def getInterface(encodedName: String): InterfaceType =
    _interfaces.getOrElseUpdate(encodedName, new SeqInterfaceType(encodedName))

  private val methodsToProcess = mutable.ListBuffer.empty[MethodImpl]
  protected def scheduleMethod(method: MethodImpl): Unit =
    methodsToProcess += method

  protected def newMethodImpl(owner: MethodContainer,
      encodedName: String): MethodImpl = new SeqMethodImpl(owner, encodedName)

  protected def processAllTaggedMethods(): Unit = {
    logProcessingMethods(methodsToProcess.count(!_.deleted))
    for (method <- methodsToProcess)
      method.process()
    methodsToProcess.clear()
  }

  private class SeqInterfaceType(encName: String) extends InterfaceType(encName) {
    private val ancestorsAskers = mutable.Set.empty[MethodImpl]
    private val dynamicCallers = mutable.Map.empty[String, mutable.Set[MethodImpl]]
    private val staticCallers = mutable.Map.empty[String, mutable.Set[MethodImpl]]

    private var _ancestors: List[String] = encodedName :: Nil

    private var _instantiatedSubclasses: Set[Class] = Set.empty

    def instantiatedSubclasses: Iterable[Class] = _instantiatedSubclasses

    def addInstantiatedSubclass(x: Class): Unit =
      _instantiatedSubclasses += x

    def removeInstantiatedSubclass(x: Class): Unit =
      _instantiatedSubclasses -= x

    def ancestors: List[String] = _ancestors

    def ancestors_=(v: List[String]): Unit = {
      if (v != _ancestors) {
        _ancestors = v
        ancestorsAskers.foreach(_.tag())
        ancestorsAskers.clear()
      }
    }

    def registerAskAncestors(asker: MethodImpl): Unit =
      ancestorsAskers += asker

    def registerDynamicCaller(methodName: String, caller: MethodImpl): Unit =
      dynamicCallers.getOrElseUpdate(methodName, mutable.Set.empty) += caller

    def registerStaticCaller(methodName: String, caller: MethodImpl): Unit =
      staticCallers.getOrElseUpdate(methodName, mutable.Set.empty) += caller

    def unregisterDependee(dependee: MethodImpl): Unit = {
      ancestorsAskers -= dependee
      dynamicCallers.values.foreach(_ -= dependee)
      staticCallers.values.foreach(_ -= dependee)
    }

    def tagDynamicCallersOf(methodName: String): Unit =
      dynamicCallers.remove(methodName).foreach(_.foreach(_.tag()))

    def tagStaticCallersOf(methodName: String): Unit =
      staticCallers.remove(methodName).foreach(_.foreach(_.tag()))
  }

  private class SeqMethodImpl(owner: MethodContainer,
      encodedName: String) extends MethodImpl(owner, encodedName) {

    private val bodyAskers = mutable.Set.empty[MethodImpl]

    def registerBodyAsker(asker: MethodImpl): Unit =
      bodyAskers += asker

    def unregisterDependee(dependee: MethodImpl): Unit =
      bodyAskers -= dependee

    def tagBodyAskers(): Unit = {
      bodyAskers.foreach(_.tag())
      bodyAskers.clear()
    }

    private var _registeredTo: List[Unregisterable] = Nil
    private var tagged = false

    protected def registeredTo(intf: Unregisterable): Unit =
      _registeredTo ::= intf

    protected def unregisterFromEverywhere(): Unit = {
      _registeredTo.foreach(_.unregisterDependee(this))
      _registeredTo = Nil
    }

    protected def protectTag(): Boolean = {
      val res = !tagged
      tagged = true
      res
    }
    protected def resetTag(): Unit = tagged = false

  }

}