/* __ *\ ** ________ ___ / / ___ __ ____ 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 } }