diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/icode/Members.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/Members.scala | 95 |
1 files changed, 36 insertions, 59 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index b74770f051..4389afb2b7 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -3,14 +3,13 @@ * @author Martin Odersky */ -package scala.tools.nsc +package scala +package tools.nsc package backend package icode -import java.io.PrintWriter import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.{ SourceFile, NoSourceFile } -import symtab.Flags.{ DEFERRED } trait ReferenceEquality { override def hashCode = System.identityHashCode(this) @@ -48,27 +47,33 @@ trait Members { def touched = _touched def touched_=(b: Boolean): Unit = { - if (b) - blocks foreach (_.touched = true) + @annotation.tailrec def loop(xs: List[BasicBlock]) { + xs match { + case Nil => + case x :: xs => x.touched = true ; loop(xs) + } + } + if (b) loop(blocks.toList) _touched = b } // Constructor code - startBlock = newBlock + startBlock = newBlock() def removeBlock(b: BasicBlock) { - if (settings.debug.value) { - assert(blocks forall (p => !(p.successors contains b)), - "Removing block that is still referenced in method code " + b + "preds: " + b.predecessors - ) - assert(b != startBlock || b.successors.length == 1, - "Removing start block with more than one successor." - ) + if (settings.debug) { + // only do this sanity check when debug is turned on because it's moderately expensive + val referers = blocks filter (_.successors contains b) + assert(referers.isEmpty, s"Trying to removing block $b (with preds ${b.predecessors.mkString}) but it is still refered to from block(s) ${referers.mkString}") } - if (b == startBlock) + if (b == startBlock) { + assert(b.successors.length == 1, + s"Removing start block ${b} with ${b.successors.length} successors (${b.successors.mkString})." + ) startBlock = b.successors.head + } blocks -= b assert(!blocks.contains(b)) @@ -77,7 +82,7 @@ trait Members { } /** This methods returns a string representation of the ICode */ - override def toString = "ICode '" + name + "'"; + override def toString = "ICode '" + name + "'" /* Compute a unique new label */ def nextLabel: Int = { @@ -89,8 +94,8 @@ trait Members { */ def newBlock(): BasicBlock = { touched = true - val block = new BasicBlock(nextLabel, method); - blocks += block; + val block = new BasicBlock(nextLabel, method) + blocks += block block } } @@ -112,25 +117,23 @@ trait Members { var cunit: CompilationUnit = _ def addField(f: IField): this.type = { - fields = f :: fields; + fields = f :: fields this } def addMethod(m: IMethod): this.type = { - methods = m :: methods; + methods = m :: methods this } def setCompilationUnit(unit: CompilationUnit): this.type = { - this.cunit = unit; + this.cunit = unit this } override def toString() = symbol.fullName - def lookupField(s: Symbol) = fields find (_.symbol == s) def lookupMethod(s: Symbol) = methods find (_.symbol == s) - def lookupMethod(s: Name) = methods find (_.symbol.name == s) /* returns this methods static ctor if it has one. */ def lookupStaticCtor: Option[IMethod] = methods find (_.symbol.isStaticConstructor) @@ -154,14 +157,13 @@ trait Members { class IMethod(val symbol: Symbol) extends IMember { var code: Code = NoCode - def newBlock() = code.newBlock + def newBlock() = code.newBlock() def startBlock = code.startBlock def lastBlock = { assert(blocks.nonEmpty, symbol); blocks.last } def blocks = code.blocksList def linearizedBlocks(lin: Linearizer = self.linearizer): List[BasicBlock] = lin linearize this def foreachBlock[U](f: BasicBlock => U): Unit = blocks foreach f - def foreachInstr[U](f: Instruction => U): Unit = foreachBlock(_.toList foreach f) var native = false @@ -181,7 +183,7 @@ trait Members { def hasCode = code ne NoCode def setCode(code: Code): IMethod = { - this.code = code; + this.code = code this } @@ -195,7 +197,6 @@ trait Members { } def addLocals(ls: List[Local]) = ls foreach addLocal - def addParams(as: List[Local]) = as foreach addParam def lookupLocal(n: Name): Option[Local] = locals find (_.sym.name == n) def lookupLocal(sym: Symbol): Option[Local] = locals find (_.sym == sym) @@ -210,28 +211,7 @@ trait Members { override def toString() = symbol.fullName - def matchesSignature(other: IMethod) = { - (symbol.name == other.symbol.name) && - (params corresponds other.params)(_.kind == _.kind) && - (returnType == other.returnType) - } - import opcodes._ - def checkLocals(): Unit = { - def localsSet = (code.blocks flatMap { bb => - bb.iterator collect { - case LOAD_LOCAL(l) => l - case STORE_LOCAL(l) => l - } - }).toSet - - if (hasCode) { - log("[checking locals of " + this + "]") - locals filterNot localsSet foreach { l => - log("Local " + l + " is not declared in " + this) - } - } - } /** Merge together blocks that have a single successor which has a * single predecessor. Exception handlers are taken into account (they @@ -243,10 +223,10 @@ trait Members { val nextBlock: mutable.Map[BasicBlock, BasicBlock] = mutable.HashMap.empty for (b <- code.blocks.toList if b.successors.length == 1; - succ = b.successors.head; - if succ ne b; - if succ.predecessors.length == 1; - if succ.predecessors.head eq b; + succ = b.successors.head + if succ ne b + if succ.predecessors.length == 1 + if succ.predecessors.head eq b if !(exh.exists { (e: ExceptionHandler) => (e.covers(succ) && !e.covers(b)) || (e.covers(b) && !e.covers(succ)) })) { nextBlock(b) = succ @@ -255,10 +235,10 @@ trait Members { var bb = code.startBlock while (!nextBlock.isEmpty) { if (nextBlock.isDefinedAt(bb)) { - bb.open + bb.open() var succ = bb do { - succ = nextBlock(succ); + succ = nextBlock(succ) val lastInstr = bb.lastInstruction /* Ticket SI-5672 * Besides removing the control-flow instruction at the end of `bb` (usually a JUMP), we have to pop any values it pushes. @@ -269,7 +249,7 @@ trait Members { val oldTKs = lastInstr.consumedTypes assert(lastInstr.consumed == oldTKs.size, "Someone forgot to override consumedTypes() in " + lastInstr) - bb.removeLastInstruction + bb.removeLastInstruction() for(tk <- oldTKs.reverse) { bb.emit(DROP(tk), lastInstr.pos) } succ.toList foreach { i => bb.emit(i, i.pos) } code.removeBlock(succ) @@ -277,9 +257,9 @@ trait Members { nextBlock -= bb } while (nextBlock.isDefinedAt(succ)) - bb.close + bb.close() } else - bb = nextBlock.keysIterator.next + bb = nextBlock.keysIterator.next() } checkValid(this) } @@ -297,9 +277,6 @@ trait Members { /** Starting PC for this local's visibility range. */ var start: Int = _ - /** Ending PC for this local's visibility range. */ - var end: Int = _ - /** PC-based ranges for this local variable's visibility */ var ranges: List[(Int, Int)] = Nil |