All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalanative.optimizer.Optimizer.scala Maven / Gradle / Ivy

The newest version!
package scala.scalanative
package optimizer

import scala.collection.mutable
import nir._

/** Optimizer reporters can override one of the corresponding methods to
 *  get notified whenever one of the optimization events happens.
 */
object Optimizer {

  private def time[T](msg: String)(f: => T): T = {
    import java.lang.System.nanoTime
    val start = nanoTime()
    val res   = f
    val end   = nanoTime()
    println(s"[info] $msg (${(end - start) / 1000000} ms)")
    res
  }

  private def partition(defns: Seq[Defn]) = {
    val batches = java.lang.Runtime.getRuntime.availableProcessors * 4
    defns.groupBy { defn =>
      Math.abs(System.identityHashCode(defn)) % batches
    }
  }

  /** Run all of the passes on given assembly. */
  def apply(config: tools.Config,
            driver: Driver,
            assembly: Seq[Defn],
            dyns: Seq[String],
            reporter: Reporter): Seq[Defn] = {
    import reporter._

    val injects    = driver.passes.filter(_.isInjectionPass)
    val transforms = driver.passes.filterNot(_.isInjectionPass)
    val world      = analysis.ClassHierarchy(assembly, dyns)

    val injected = {
      val buf = mutable.UnrolledBuffer.empty[Defn]
      buf ++= assembly
      injects.foreach { make =>
        make(config, world) match {
          case NoPass         => ()
          case inject: Inject => inject(buf)
          case _              => util.unreachable
        }
      }
      buf
    }

    def loop(batchId: Int,
             batchDefns: Seq[Defn],
             passes: Seq[(AnyPass, Int)]): Seq[Defn] =
      passes match {
        case Seq() =>
          batchDefns

        case (NoPass, _) +: rest =>
          loop(batchId, batchDefns, rest)

        case (pass: Pass, passId) +: rest =>
          val passResult = pass.onDefns(batchDefns)
          onPass(batchId, passId, pass, passResult)
          loop(batchId, passResult, rest)
      }

    partition(injected).par
      .map {
        case (batchId, batchDefns) =>
          onStart(batchId, batchDefns)
          val passes = transforms.map(_.apply(config, world))
          val res    = loop(batchId, batchDefns, passes.zipWithIndex)
          onComplete(batchId, res)
          res
      }
      .seq
      .flatten
      .toSeq
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy