closureelimination.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 240 行

SCALA
240
字号
 /* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author  Iulian Dragos */// $Id: ClosureElimination.scala 14416 2008-03-19 01:17:25Z mihaylov $package scala.tools.nsc.backend.opt;import scala.collection.mutable.{Map, HashMap};import scala.tools.nsc.backend.icode.analysis.LubError;import scala.tools.nsc.symtab._;/** *  @author Iulian Dragos */abstract class ClosureElimination extends SubComponent {  import global._  import icodes._  import icodes.opcodes._  val phaseName = "closelim"  /** Create a new phase */  override def newPhase(p: Phase) = new ClosureEliminationPhase(p)  /** The Inlining phase.   */  class ClosureEliminationPhase(prev: Phase) extends ICodePhase(prev) {    def name = phaseName    val closser = new ClosureElim    override def apply(c: IClass): Unit =      closser.analyzeClass(c)  }  /**    * Remove references to the environemnt through fields of a closure object.    * This has to be run after an 'apply' method has been inlined, but it still    * references the closure object.   *   */  class ClosureElim {    /* fresh name counter */    var count = 0        def freshName(s: String) = {      val ret = s + this.count      this.count += 1      ret    }    /** A simple peephole optimizer. */    val peephole = new PeepholeOpt( (i1, i2) =>    	(i1, i2) match {        case (CONSTANT(c), DROP(_)) =>           if (c.tag == UnitTag)            Some(List(i2))          else            Some(Nil);                  case (LOAD_LOCAL(x), STORE_LOCAL(y)) =>        	if (x eq y) Some(Nil) else None        case (LOAD_LOCAL(_), DROP(_)) =>          Some(Nil)        case (BOX(t1), UNBOX(t2)) if (t1 == t2) =>          Some(Nil)                  case (LOAD_FIELD(sym, isStatic), DROP(_)) =>        	if (isStatic)            Some(Nil)          else            Some(DROP(REFERENCE(definitions.ObjectClass)) :: Nil);                  case _ => None      });        def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim.value) {      cls.methods.foreach { m =>         analyzeMethod(m)        peephole.transformMethod(m);     }}    val cpp = new copyPropagation.CopyAnalysis    import copyPropagation._    /* Some embryonic copy propagation. */    def analyzeMethod(m: IMethod): Unit = try {if (m.code ne null) {      log("Analyzing " + m)      cpp.init(m)      cpp.run      for (bb <- linearizer.linearize(m)) {        var info = cpp.in(bb)        for (i <- bb.toList) {          i match {            case LOAD_LOCAL(l) if (info.bindings.isDefinedAt(LocalVar(l))) =>              val t = info.getBinding(l)              t match {                case Deref(LocalVar(v)) =>                   bb.replaceInstruction(i, valueToInstruction(t));                  log("replaced " + i + " with " + t)                case Deref(This) =>                  bb.replaceInstruction(i, valueToInstruction(t));                  log("replaced " + i + " with " + t)                case _ =>                   bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l)));                  log("replaced " + i + " with " + info.getAlias(l))              }            case LOAD_FIELD(f, false) if accessible(f, m.symbol) =>              info.stack(0) match {                case r @ Record(cls, bindings) if bindings.isDefinedAt(f) =>                  info.getLocalForField(r, f) match {                    case Some(local) =>                      bb.replaceInstruction(i,                           DROP(REFERENCE(cls)) :: valueToInstruction(local) :: Nil);                      log("Replaced " + i + " with " + info.getBinding(r, f));                    case None => ();                  }                case Deref(LocalVar(l)) =>                  info.getBinding(l) match {                    case r @ Record(cls, bindings) if bindings.isDefinedAt(f) =>                      info.getLocalForField(r, f) match {                        case Some(local) =>                          bb.replaceInstruction(i,                               DROP(REFERENCE(cls)) :: valueToInstruction(local) :: Nil);                          log("Replaced " + i + " with " + info.getBinding(r, f));                        case None => ();                      }                    case _ => ();                  }                case _ => ();              }                          case UNBOX(_) =>              info.stack match {                case Deref(LocalVar(loc1)) :: _ if (info.bindings.isDefinedAt(LocalVar(loc1))) =>                  val value = info.getBinding(loc1)                  value match {                    case Boxed(LocalVar(loc2)) =>                      bb.replaceInstruction(i, DROP(icodes.AnyRefReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil)                      log("replaced " + i + " with " + info.getBinding(loc2))                    case _ =>                      ()                  }                case Boxed(LocalVar(loc1)) :: _ =>                  val value = info.getBinding(loc1)                  bb.replaceInstruction(i, DROP(icodes.AnyRefReference) :: valueToInstruction(value) :: Nil)                  log("replaced " + i + " with " + value)                case _ =>                  ()              }            case _ => ();          }          info = cpp.interpret(info, i)        }      }    }} catch {      case e: LubError =>         Console.println("In method: " + m)        Console.println(e)        e.printStackTrace    }    /* Partial mapping from values to instructions that load them. */    def valueToInstruction(v: Value): Instruction = (v: @unchecked) match {      case Deref(LocalVar(v)) =>         LOAD_LOCAL(v)      case Deref(This) =>        THIS(definitions.ObjectClass)    }        /** is field 'f' accessible from method 'm'? */    def accessible(f: Symbol, m: Symbol): Boolean =       f.isPublic || (f.hasFlag(Flags.PROTECTED) && (enclPackage(f) == enclPackage(m)))    private def enclPackage(sym: Symbol): Symbol =       if ((sym == NoSymbol) || sym.isPackageClass) sym else enclPackage(sym.owner)  } /* class ClosureElim */  /** Peephole optimization. */  class PeepholeOpt(peep: (Instruction, Instruction) => Option[List[Instruction]]) {    private var method: IMethod = null    def transformMethod(m: IMethod): Unit = if (m.code ne null) {      method = m      for (b <- m.code.blocks)         transformBlock(b)    }    def transformBlock(b: BasicBlock): Unit = if (b.size >= 2) {      var newInstructions: List[Instruction] = Nil;      newInstructions = b.toList            var redo = false      do {        var h = newInstructions.head;        var t = newInstructions.tail;        var seen: List[Instruction] = Nil;        redo = false;        while (t != Nil) {          peep(h, t.head) match {            case Some(newInstrs) =>              newInstructions = seen.reverse ::: newInstrs ::: t.tail;              redo = true;            case None =>            	()          }          seen = h :: seen;          h = t.head;          t = t.tail        }      } while (redo);      b.fromList(newInstructions)    }  }} /* class ClosureElimination */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?