diff options
Diffstat (limited to 'examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ParIncOptimizer.scala')
-rw-r--r-- | examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ParIncOptimizer.scala | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ParIncOptimizer.scala b/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ParIncOptimizer.scala new file mode 100644 index 0000000..422238e --- /dev/null +++ b/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ParIncOptimizer.scala @@ -0,0 +1,188 @@ +/* __ *\ +** ________ ___ / / ___ __ ____ 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.concurrent.TrieMap +import scala.collection.parallel.mutable.{ParTrieMap, ParArray} + +import java.util.concurrent.atomic._ + +import scala.scalajs.tools.sem.Semantics + +import ConcurrencyUtils._ + +class ParIncOptimizer(semantics: Semantics) extends GenIncOptimizer(semantics) { + + protected object CollOps extends GenIncOptimizer.AbsCollOps { + type Map[K, V] = TrieMap[K, V] + type ParMap[K, V] = ParTrieMap[K, V] + type AccMap[K, V] = TrieMap[K, AtomicAcc[V]] + type ParIterable[V] = ParArray[V] + type Addable[V] = AtomicAcc[V] + + def emptyAccMap[K, V]: AccMap[K, V] = TrieMap.empty + def emptyMap[K, V]: Map[K, V] = TrieMap.empty + def emptyParMap[K, V]: ParMap[K, V] = ParTrieMap.empty + def emptyParIterable[V]: ParIterable[V] = ParArray.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.foreach { case (k, v) => + if (!p(k, v)) + map.remove(k) + } + } + + // Operations on AccMap + def acc[K, V](map: AccMap[K, V], k: K, v: V): Unit = + map.getOrPut(k, AtomicAcc.empty) += v + + def getAcc[K, V](map: AccMap[K, V], k: K): GenIterable[V] = + map.get(k).fold[Iterable[V]](Nil)(_.removeAll()).toParArray + + def parFlatMapKeys[A, B](map: AccMap[A, _])( + f: A => GenTraversableOnce[B]): GenIterable[B] = + map.keys.flatMap(f).toParArray + + // Operations on ParIterable + def prepAdd[V](it: ParIterable[V]): Addable[V] = + AtomicAcc(it.toList) + + def add[V](addable: Addable[V], v: V): Unit = + addable += v + + def finishAdd[V](addable: Addable[V]): ParIterable[V] = + addable.removeAll().toParArray + } + + private val _interfaces = TrieMap.empty[String, InterfaceType] + protected def getInterface(encodedName: String): InterfaceType = + _interfaces.getOrPut(encodedName, new ParInterfaceType(encodedName)) + + private val methodsToProcess: AtomicAcc[MethodImpl] = AtomicAcc.empty + protected def scheduleMethod(method: MethodImpl): Unit = + methodsToProcess += method + + protected def newMethodImpl(owner: MethodContainer, + encodedName: String): MethodImpl = new ParMethodImpl(owner, encodedName) + + protected def processAllTaggedMethods(): Unit = { + val methods = methodsToProcess.removeAll().toParArray + logProcessingMethods(methods.count(!_.deleted)) + for (method <- methods) + method.process() + } + + private class ParInterfaceType(encName: String) extends InterfaceType(encName) { + private val ancestorsAskers = TrieSet.empty[MethodImpl] + private val dynamicCallers = TrieMap.empty[String, TrieSet[MethodImpl]] + private val staticCallers = TrieMap.empty[String, TrieSet[MethodImpl]] + + private var _ancestors: List[String] = encodedName :: Nil + + private val _instantiatedSubclasses: TrieSet[Class] = TrieSet.empty + + /** PROCESS PASS ONLY. Concurrency safe except with + * [[addInstantiatedSubclass]] and [[removeInstantiatedSubclass]] + */ + def instantiatedSubclasses: Iterable[Class] = + _instantiatedSubclasses.keys + + /** UPDATE PASS ONLY. Concurrency safe except with + * [[instantiatedSubclasses]] + */ + def addInstantiatedSubclass(x: Class): Unit = + _instantiatedSubclasses += x + + /** UPDATE PASS ONLY. Concurrency safe except with + * [[instantiatedSubclasses]] + */ + def removeInstantiatedSubclass(x: Class): Unit = + _instantiatedSubclasses -= x + + /** PROCESS PASS ONLY. Concurrency safe except with [[ancestors_=]] */ + def ancestors: List[String] = _ancestors + + /** UPDATE PASS ONLY. Not concurrency safe. */ + def ancestors_=(v: List[String]): Unit = { + if (v != _ancestors) { + _ancestors = v + ancestorsAskers.keysIterator.foreach(_.tag()) + ancestorsAskers.clear() + } + } + + /** PROCESS PASS ONLY. Concurrency safe except with [[ancestors_=]]. */ + def registerAskAncestors(asker: MethodImpl): Unit = + ancestorsAskers += asker + + /** PROCESS PASS ONLY. */ + def registerDynamicCaller(methodName: String, caller: MethodImpl): Unit = + dynamicCallers.getOrPut(methodName, TrieSet.empty) += caller + + /** PROCESS PASS ONLY. */ + def registerStaticCaller(methodName: String, caller: MethodImpl): Unit = + staticCallers.getOrPut(methodName, TrieSet.empty) += caller + + /** UPDATE PASS ONLY. */ + def unregisterDependee(dependee: MethodImpl): Unit = { + ancestorsAskers -= dependee + dynamicCallers.valuesIterator.foreach(_ -= dependee) + staticCallers.valuesIterator.foreach(_ -= dependee) + } + + /** UPDATE PASS ONLY. */ + def tagDynamicCallersOf(methodName: String): Unit = + dynamicCallers.remove(methodName).foreach(_.keysIterator.foreach(_.tag())) + + /** UPDATE PASS ONLY. */ + def tagStaticCallersOf(methodName: String): Unit = + staticCallers.remove(methodName).foreach(_.keysIterator.foreach(_.tag())) + } + + private class ParMethodImpl(owner: MethodContainer, + encodedName: String) extends MethodImpl(owner, encodedName) { + + private val bodyAskers = TrieSet.empty[MethodImpl] + + /** PROCESS PASS ONLY. */ + def registerBodyAsker(asker: MethodImpl): Unit = + bodyAskers += asker + + /** UPDATE PASS ONLY. */ + def unregisterDependee(dependee: MethodImpl): Unit = + bodyAskers -= dependee + + /** UPDATE PASS ONLY. */ + def tagBodyAskers(): Unit = { + bodyAskers.keysIterator.foreach(_.tag()) + bodyAskers.clear() + } + + private val _registeredTo = AtomicAcc.empty[Unregisterable] + private val tagged = new AtomicBoolean(false) + + protected def registeredTo(intf: Unregisterable): Unit = + _registeredTo += intf + + protected def unregisterFromEverywhere(): Unit = { + _registeredTo.removeAll().foreach(_.unregisterDependee(this)) + } + + protected def protectTag(): Boolean = !tagged.getAndSet(true) + protected def resetTag(): Unit = tagged.set(false) + + } + +} |