summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-09-22 20:24:08 +0000
committerPaul Phillips <paulp@improving.org>2010-09-22 20:24:08 +0000
commita992ec2d579b65b79d61c7c2997812deb58250cd (patch)
treecfc2a9bb128935788f6e01cc36655817532e3742 /src
parent285d2182f1aeb113aba55be804eefa2f61ce2624 (diff)
downloadscala-a992ec2d579b65b79d61c7c2997812deb58250cd.tar.gz
scala-a992ec2d579b65b79d61c7c2997812deb58250cd.tar.bz2
scala-a992ec2d579b65b79d61c7c2997812deb58250cd.zip
A cleanup of the inliner.
and still came out of the washing machine smiling. Already reviewed by a certain i. dragos so no review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/Platform.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala254
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Checkers.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala194
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala136
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala41
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Repository.scala11
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala20
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala18
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala88
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala34
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/SemiLattice.scala29
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala95
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala134
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala25
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala49
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala11
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala4
21 files changed, 450 insertions, 743 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index dbe4a587ba..70641f9037 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -60,6 +60,11 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable =>
/** Apply `f' to each subtree */
def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(tree) }
+ /** If 'pf' is defined for a given subtree, call super.traverse(pf(tree)),
+ * otherwise super.traverse(tree).
+ */
+ def foreachPartial(pf: PartialFunction[Tree, Tree]) { new ForeachPartialTreeTraverser(pf).traverse(tree) }
+
/** Find all subtrees matching predicate `p' */
def filter(f: Tree => Boolean): List[Tree] = {
val ft = new FilterTreeTraverser(f)
@@ -1019,6 +1024,13 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable =>
tree
}
+ class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser {
+ override def traverse(tree: Tree) {
+ val t = if (pf isDefinedAt tree) pf(tree) else tree
+ super.traverse(t)
+ }
+ }
+
class ForeachTreeTraverser(f: Tree => Unit) extends Traverser {
override def traverse(t: Tree) {
f(t)
diff --git a/src/compiler/scala/tools/nsc/backend/Platform.scala b/src/compiler/scala/tools/nsc/backend/Platform.scala
index 90075687c6..e0f755323a 100644
--- a/src/compiler/scala/tools/nsc/backend/Platform.scala
+++ b/src/compiler/scala/tools/nsc/backend/Platform.scala
@@ -29,3 +29,4 @@ trait Platform[T] {
/** The various ways a boxed primitive might materialize at runtime. */
def isMaybeBoxed(sym: Symbol): Boolean
}
+
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 9b0e52ffac..3ce61cf65e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -8,11 +8,10 @@ package scala.tools.nsc
package backend
package icode
-//import scala.tools.nsc.ast._
-import scala.collection.mutable.{Map, Set}
-import scala.collection.mutable.LinkedHashSet
-import scala.tools.nsc.util.{Position,NoPosition}
-import scala.tools.nsc.backend.icode.analysis.ProgramPoint
+import scala.collection.{ mutable, immutable }
+import mutable.{ ArrayBuffer }
+import util.{ Position, NoPosition }
+import backend.icode.analysis.ProgramPoint
trait BasicBlocks {
self: ICodes =>
@@ -79,7 +78,7 @@ trait BasicBlocks {
/** Local variables that are in scope at entry of this basic block. Used
* for debugging information.
*/
- var varsInScope: Set[Local] = new LinkedHashSet()
+ var varsInScope: mutable.Set[Local] = new mutable.LinkedHashSet()
/** ICode instructions, used as temporary storage while emitting code.
* Once closed is called, only the `instrs' array should be used.
@@ -90,11 +89,8 @@ trait BasicBlocks {
private var instrs: Array[Instruction] = _
- override def toList: List[Instruction] = {
- if (closed)
- instrs.toList
- else instructionList.reverse
- }
+ override def toList: List[Instruction] =
+ if (closed) instrs.toList else instructionList.reverse
/** Return an iterator over the instructions in this basic block. */
def iterator: Iterator[Instruction] =
@@ -108,7 +104,7 @@ trait BasicBlocks {
def fromList(is: List[Instruction]) {
code.touched = true
- instrs = toInstructionArray(is)
+ instrs = is.toArray
closed = true
}
@@ -117,17 +113,9 @@ trait BasicBlocks {
*/
def indexOf(inst: Instruction): Int = {
assert(closed)
- var i = 0
- while (i < instrs.length) {
- if (instrs(i) eq inst) return i
- i += 1
- }
- -1
+ instrs indexWhere (_ eq inst)
}
- /** Compute an hashCode for the block */
-// override def hashCode() = label;
-
/** Apply a function to all the instructions of the block. */
override def foreach[U](f: Instruction => U) = {
if (!closed) {
@@ -138,26 +126,7 @@ trait BasicBlocks {
}
/** The number of instructions in this basic block so far. */
- def length: Int =
- if (closed) instrs.length else instructionList.length
-
- /** Return the index of the instruction which produced the value
- * consumed by the given instruction.
- */
- def findDef(pos: Int): Option[Int] = {
- assert(closed)
- var i = pos
- var d = 0
- while (i > 0) {
- i -= 1
- val prod = instrs(i).produced
- if (prod > 0 && d == 0)
- return Some(i)
- d += (instrs(i).consumed - instrs(i).produced)
- }
- None
- }
-
+ def length = if (closed) instrs.length else instructionList.length
/** Return the n-th instruction. */
def apply(n: Int): Instruction =
@@ -185,21 +154,17 @@ trait BasicBlocks {
def replaceInstruction(oldInstr: Instruction, newInstr: Instruction): Boolean = {
assert(closed, "Instructions can be replaced only after the basic block is closed")
- var i = 0
- var changed = false
- while (i < instrs.length && !changed) {
- if (instrs(i) eq oldInstr) {
- newInstr.setPos(oldInstr.pos)
- instrs(i) = newInstr
- changed = true
+ indexOf(oldInstr) match {
+ case -1 => false
+ case idx =>
+ newInstr setPos oldInstr.pos
+ instrs(idx) = newInstr
code.touched = true
- }
- i += 1
+ true
}
- changed
}
- /** Replaces <code>iold</code> with <code>is</code>. It does not update
+ /** Replaces <code>oldInstr</code> with <code>is</code>. It does not update
* the position field in the newly inserted instructions, so it behaves
* differently than the one-instruction versions of this function.
*
@@ -207,51 +172,23 @@ trait BasicBlocks {
* @param is ..
* @return ..
*/
- def replaceInstruction(iold: Instruction, is: List[Instruction]): Boolean = {
+ def replaceInstruction(oldInstr: Instruction, is: List[Instruction]): Boolean = {
assert(closed, "Instructions can be replaced only after the basic block is closed")
- var i = 0
- var changed = false
-
- while (i < instrs.length && (instrs(i) ne iold))
- i += 1
-
- if (i < instrs.length) {
- val newInstrs = new Array[Instruction](instrs.length + is.length - 1);
- changed = true
- code.touched = true
-
- Array.copy(instrs, 0, newInstrs, 0, i)
- var j = i
- for (x <- is) {
- newInstrs(j) = x
- j += 1
- }
- if (i + 1 < instrs.length)
- Array.copy(instrs, i + 1, newInstrs, j, instrs.length - i - 1)
- instrs = newInstrs;
+ indexOf(oldInstr) match {
+ case -1 => false
+ case idx =>
+ instrs = instrs.patch(idx, is, 1)
+ code.touched = true
+ true
}
-
- changed
}
/** Insert instructions in 'is' immediately after index 'idx'. */
def insertAfter(idx: Int, is: List[Instruction]) {
assert(closed, "Instructions can be replaced only after the basic block is closed")
- var i = idx + 1
- if (i < instrs.length) {
- val newInstrs = new Array[Instruction](instrs.length + is.length);
- Array.copy(instrs, 0, newInstrs, 0, i)
- var j = i
- for (x <- is) {
- newInstrs(j) = x
- j += 1
- }
- if (i + 1 < instrs.length)
- Array.copy(instrs, i + 1, newInstrs, j, instrs.length - i)
- instrs = newInstrs;
- }
+ instrs = instrs.patch(idx + 1, is, 0)
code.touched = true
}
@@ -261,18 +198,7 @@ trait BasicBlocks {
*/
def removeInstructionsAt(positions: Int*) {
assert(closed)
- val removed = positions.toList
- val newInstrs = new Array[Instruction](instrs.length - positions.length)
- var i = 0
- var j = 0
- while (i < instrs.length) {
- if (!removed.contains(i)) {
- newInstrs(j) = instrs(i)
- j += 1
- }
- i += 1
- }
- instrs = newInstrs
+ instrs = instrs.indices.toArray filterNot positions.toSet map instrs
code.touched = true
}
@@ -292,33 +218,14 @@ trait BasicBlocks {
*
* @param map ...
*/
- def subst(map: Map[Instruction, Instruction]) {
- if (!closed) substOnList(map) else {
- var i = 0
- while (i < instrs.length) {
- map get instrs(i) match {
- case Some(instr) =>
- val changed = replaceInstruction(i, instr)
- code.touched |= changed
- case None => ()
- }
- i += 1
+ def subst(map: Map[Instruction, Instruction]): Unit =
+ if (!closed)
+ instructionList = instructionList map (x => map.getOrElse(x, x))
+ else
+ instrs.zipWithIndex collect {
+ case (oldInstr, i) if map contains oldInstr =>
+ code.touched |= replaceInstruction(i, map(oldInstr))
}
- }
- }
-
- private def substOnList(map: Map[Instruction, Instruction]) {
- def subst(l: List[Instruction]): List[Instruction] = l match {
- case Nil => Nil
- case x :: xs =>
- map.get(x) match {
- case Some(newInstr) => newInstr :: subst(xs)
- case None => x :: subst(xs)
- }
- }
-
- instructionList = subst(instructionList)
- }
////////////////////// Emit //////////////////////
@@ -327,10 +234,8 @@ trait BasicBlocks {
* using the same source position as the last emitted instruction
*/
def emit(instr: Instruction) {
- if (!instructionList.isEmpty)
- emit(instr, instructionList.head.pos)
- else
- emit(instr, NoPosition)
+ val pos = if (instructionList.isEmpty) NoPosition else instructionList.head.pos
+ emit(instr, pos)
}
/** Emitting does not set touched to true. During code generation this is a hotspot and
@@ -390,7 +295,7 @@ trait BasicBlocks {
closed = true
setFlag(DIRTYSUCCS)
instructionList = instructionList.reverse
- instrs = toInstructionArray(instructionList)
+ instrs = instructionList.toArray
}
def open {
@@ -422,67 +327,38 @@ trait BasicBlocks {
/** Return the last instruction of this basic block. */
def lastInstruction =
- if (closed)
- instrs(instrs.length - 1)
- else
- instructionList.head
+ if (closed) instrs.last
+ else instructionList.head
def firstInstruction =
- if (closed)
- instrs(0)
- else
- instructionList.last
-
- /** Convert the list to an array */
- private def toInstructionArray(l: List[Instruction]): Array[Instruction] = {
- var array = new Array[Instruction](l.length)
- var i: Int = 0
+ if (closed) instrs(0)
+ else instructionList.last
- l foreach (x => { array(i) = x; i += 1 })
- array
- }
+ def exceptionSuccessorsForBlock(block: BasicBlock): List[BasicBlock] =
+ method.exh collect { case x if x covers block => x.startBlock }
/** Cached value of successors. Must be recomputed whenver a block in the current method is changed. */
private var succs: List[BasicBlock] = Nil
+ private def updateSuccs() {
+ resetFlag(DIRTYSUCCS)
+ succs =
+ if (isEmpty) Nil
+ else exceptionSuccessors ++ directSuccessors ++ indirectExceptionSuccessors
+ }
def successors : List[BasicBlock] = {
- if (touched) {
- resetFlag(DIRTYSUCCS)
- succs = if (isEmpty) Nil else {
- var res = lastInstruction match {
- case JUMP(whereto) => List(whereto)
- case CJUMP(success, failure, _, _) => failure :: success :: Nil
- case CZJUMP(success, failure, _, _) => failure :: success :: Nil
- case SWITCH(_, labels) => labels
- case RETURN(_) => Nil
- case THROW() => Nil
- case _ =>
- if (closed) {
- dump
- global.abort("The last instruction is not a control flow instruction: " + lastInstruction)
- }
- else Nil
- }
- method.exh.foreach {
- e: ExceptionHandler =>
- if (e.covers(this)) res = e.startBlock :: res
- }
- val res1 = res ++ exceptionalSucc(this, res)
- res1
- }
- }
-// println("reusing cached successors for " + this + " in method " + method)
+ if (touched) updateSuccs()
succs
}
- def directSuccessors: List[BasicBlock] = {
+ def directSuccessors: List[BasicBlock] =
if (isEmpty) Nil else lastInstruction match {
- case JUMP(whereto) => List(whereto)
- case CJUMP(success, failure, _, _) => failure :: success :: Nil
- case CZJUMP(success, failure, _, _) => failure :: success :: Nil
- case SWITCH(_, labels) => labels
- case RETURN(_) => Nil
- case THROW() => Nil
+ case JUMP(whereto) => List(whereto)
+ case CJUMP(succ, fail, _, _) => fail :: succ :: Nil
+ case CZJUMP(succ, fail, _, _) => fail :: succ :: Nil
+ case SWITCH(_, labels) => labels
+ case RETURN(_) => Nil
+ case THROW() => Nil
case _ =>
if (closed) {
dump
@@ -490,29 +366,23 @@ trait BasicBlocks {
}
else Nil
}
- }
+
+ def exceptionSuccessors: List[BasicBlock] =
+ exceptionSuccessorsForBlock(this)
/** Return a list of successors for 'b' that come from exception handlers
* covering b's (non-exceptional) successors. These exception handlers
* might not cover 'b' itself. This situation corresponds to an
* exception being thrown as the first thing of one of b's successors.
*/
- private def exceptionalSucc(b: BasicBlock, succs: List[BasicBlock]): List[BasicBlock] = {
- def findSucc(s: BasicBlock): List[BasicBlock] = {
- val ss = method.exh flatMap { h =>
- if (h.covers(s) /*&& mayThrow(h.startBlock.firstInstruction)*/) List(h.startBlock) else Nil
- }
- ss ++ (ss flatMap findSucc)
- }
-
- succs.flatMap(findSucc).distinct
- }
+ def indirectExceptionSuccessors: List[BasicBlock] =
+ directSuccessors flatMap exceptionSuccessorsForBlock distinct
/** Returns the predecessors of this block. */
def predecessors: List[BasicBlock] = {
if (hasFlag(DIRTYPREDS)) {
resetFlag(DIRTYPREDS)
- preds = code.blocks.iterator.filter (_.successors.contains(this)).toList
+ preds = code.blocks.iterator filter (_.successors contains this) toList
}
preds
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
index 6067dc6e42..2b4d66fc49 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala
@@ -573,24 +573,16 @@ abstract class Checkers {
def error(msg: String) {
Console.println(method.toString() + " in block: " + basicBlock.label)
- printLastIntructions
+ printLastInstructions
Checkers.this.global.error("ICode checker: " + method + ": " + msg)
}
/** Prints the last 4 instructions. */
- def printLastIntructions {
- var printed = 0
- var buf: List[Instruction] = Nil
-
- for (i <- basicBlock.reverse) {
- if (i == instruction || (printed > 0 && printed < 3)) {
- buf = i :: buf
- printed += 1
- }
- }
- buf foreach Console.println
- Console.println("at: " + (buf.head.pos))
+ def printLastInstructions {
+ val buf = basicBlock.reverse dropWhile (_ != instruction) take 4 reverse;
+ buf foreach (Console println _)
+ Console.println("at: " + buf.head.pos)
}
def error(msg: String, stack: TypeStack) {
@@ -602,8 +594,6 @@ abstract class Checkers {
/** Return true if <code>k1</code> is a subtype of any of the following
* types.
*/
- def isOneOf(k1: TypeKind, kinds: TypeKind*) =
- kinds.exists( k => k1 <:< k)
-
+ def isOneOf(k1: TypeKind, kinds: TypeKind*) = kinds exists (k1 <:< _)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index a5b7370f8d..ec8ffd1ddb 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -26,10 +26,10 @@ abstract class GenICode extends SubComponent {
import icodes._
import icodes.opcodes._
import definitions.{
- ArrayClass, ObjectClass, ThrowableClass, StringClass, NothingClass, NullClass,
+ ArrayClass, ObjectClass, ThrowableClass, StringClass, NothingClass, NullClass, AnyRefClass,
Object_equals, Object_isInstanceOf, Object_asInstanceOf, ScalaRunTimeModule,
BoxedNumberClass, BoxedCharacterClass,
- getMember
+ getMember, getPrimitiveCompanion
}
import scalaPrimitives.{
isArrayOp, isComparisonOp, isLogicalOp,
@@ -894,10 +894,10 @@ abstract class GenICode extends SubComponent {
} else { // normal method call
if (settings.debug.value)
log("Gen CALL_METHOD with sym: " + sym + " isStaticSymbol: " + sym.isStaticMember);
- var invokeStyle =
+ val invokeStyle =
if (sym.isStaticMember)
Static(false)
- else if (sym.hasFlag(Flags.PRIVATE) || sym.isClassConstructor)
+ else if (sym.isPrivate || sym.isClassConstructor)
Static(true)
else
Dynamic
@@ -1168,58 +1168,44 @@ abstract class GenICode extends SubComponent {
* Generate code that loads args into label parameters.
*/
private def genLoadLabelArguments(args: List[Tree], label: Label, ctx: Context): Context = {
- if (settings.debug.value)
+ if (settings.debug.value) {
assert(args.length == label.params.length,
"Wrong number of arguments in call to label " + label.symbol)
+ }
+
var ctx1 = ctx
- var arg = args
- var param = label.params
- val stores: ListBuffer[Instruction] = new ListBuffer
- // store arguments in reverse order on the stack
- while (arg != Nil) {
- arg.head match {
- case This(_) if param.head.name == nme.THIS =>
- //println("skipping trivial argument for " + param.head)
- () // skip trivial arguments
- case Ident(_) if arg.head.symbol == param.head =>
- //println("skipping trivial argument for " + param.head)
- () // skip trivial arguments
- case _ =>
- val Some(l) = ctx.method.lookupLocal(param.head)
- ctx1 = genLoad(arg.head, ctx1, l.kind)
- if (param.head.name == nme.THIS)
- STORE_THIS(toTypeKind(ctx1.clazz.symbol.tpe)).setPos(arg.head.pos) +=: stores
- else {
- STORE_LOCAL(l).setPos(arg.head.pos) +=: stores
- }
- }
- arg = arg.tail
- param = param.tail
+ def isTrivial(kv: (Tree, Symbol)) = kv match {
+ case (This(_), p) if p.name == nme.THIS => true
+ case (arg @ Ident(_), p) if arg.symbol == p => true
+ case _ => false
}
- //println("stores: " + stores)
- ctx1.bb.emit(stores)
- ctx1
- }
+ val stores = args zip label.params filterNot isTrivial map {
+ case (arg, param) =>
+ val local = ctx.method.lookupLocal(param).get
+ ctx1 = genLoad(arg, ctx1, local.kind)
- private def genLoadArguments(args: List[Tree], tpes: List[Type], ctx: Context): Context = {
- var ctx1 = ctx
- var arg = args
- var tpe = tpes
- while (arg != Nil) {
- ctx1 = genLoad(arg.head, ctx1, toTypeKind(tpe.head))
- arg = arg.tail
- tpe = tpe.tail
+ val store =
+ if (param.name == nme.THIS) STORE_THIS(toTypeKind(ctx1.clazz.symbol.tpe))
+ else STORE_LOCAL(local)
+
+ store setPos arg.pos
}
+
+ // store arguments in reverse order on the stack
+ ctx1.bb.emit(stores.reverse)
ctx1
}
+ private def genLoadArguments(args: List[Tree], tpes: List[Type], ctx: Context): Context =
+ (args zip tpes).foldLeft(ctx) {
+ case (res, (arg, tpe)) =>
+ genLoad(arg, res, toTypeKind(tpe))
+ }
+
private def genLoadModule(ctx: Context, sym: Symbol, pos: Position) {
- if (definitions.primitiveCompanions(sym))
- ctx.bb.emit(LOAD_MODULE(definitions.getModule("scala.runtime." + sym.name)), pos)
- else
- ctx.bb.emit(LOAD_MODULE(sym), pos)
+ ctx.bb.emit(LOAD_MODULE(getPrimitiveCompanion(sym) getOrElse sym), pos)
}
def genConversion(from: TypeKind, to: TypeKind, ctx: Context, cast: Boolean) = {
@@ -1409,21 +1395,17 @@ abstract class GenICode extends SubComponent {
* TODO: restrict the scanning to smaller subtrees than the whole method.
* It is sufficient to scan the trees of the innermost enclosing block.
*/
- private def scanForLabels(tree: Tree, ctx: Context): Unit =
- new Traverser() {
- override def traverse(tree: Tree): Unit = tree match {
-
- case LabelDef(name, params, rhs) =>
- if (!ctx.labels.contains(tree.symbol)) {
- ctx.labels += (tree.symbol -> (new Label(tree.symbol) setParams(params map (_.symbol))));
- ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)));
- }
- super.traverse(rhs)
-
- case _ =>
- super.traverse(tree)
- }
- } traverse(tree);
+ //
+ private def scanForLabels(tree: Tree, ctx: Context): Unit = tree foreachPartial {
+ case t @ LabelDef(_, params, rhs) =>
+ ctx.labels.getOrElseUpdate(t.symbol, {
+ val locals = params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false))
+ ctx.method addLocals locals
+
+ new Label(t.symbol) setParams (params map (_.symbol))
+ })
+ rhs
+ }
/**
* Generate code for conditional expressions. The two basic blocks
@@ -1535,7 +1517,7 @@ abstract class GenICode extends SubComponent {
def getTempLocal: Local = ctx.method.lookupLocal(eqEqTempName) match {
case Some(local) => local
case None =>
- val local = ctx.makeLocal(l.pos, definitions.AnyRefClass.typeConstructor, eqEqTempName.toString)
+ val local = ctx.makeLocal(l.pos, AnyRefClass.typeConstructor, eqEqTempName.toString)
//assert(!l.pos.source.isEmpty, "bad position, unit = "+unit+", tree = "+l+", pos = "+l.pos.source)
// Note - I commented these out because they were crashing the test case in ticket #2426
// (and I have also had to comment them out at various times while working on equality.)
@@ -1667,15 +1649,9 @@ abstract class GenICode extends SubComponent {
}
/** Does this tree have a try-catch block? */
- def mayCleanStack(tree: Tree): Boolean = {
- var hasTry = false
- new Traverser() {
- override def traverse(t: Tree) = t match {
- case Try(_, _, _) => hasTry = true
- case _ => super.traverse(t)
- }
- }.traverse(tree);
- hasTry
+ def mayCleanStack(tree: Tree): Boolean = tree exists {
+ case Try(_, _, _) => true
+ case _ => false
}
/**
@@ -1770,13 +1746,8 @@ abstract class GenICode extends SubComponent {
log("Prune fixpoint reached in " + n + " iterations.");
}
- def getMaxType(ts: List[Type]): TypeKind = {
- def maxType(a: TypeKind, b: TypeKind): TypeKind =
- a maxType b;
-
- val kinds = ts map toTypeKind
- kinds reduceLeft maxType
- }
+ def getMaxType(ts: List[Type]): TypeKind =
+ ts map toTypeKind reduceLeft (_ maxType _)
def isLoopHeaderLabel(name: Name): Boolean =
name.startsWith("while$") || name.startsWith("doWhile$")
@@ -1796,7 +1767,7 @@ abstract class GenICode extends SubComponent {
* All LabelDefs are entered into the context label map, since it makes no sense
* to delay it any more: they will be used at some point.
*/
- class DuplicateLabels(boundLabels: collection.Set[Symbol]) extends Transformer {
+ class DuplicateLabels(boundLabels: Set[Symbol]) extends Transformer {
val labels: mutable.Map[Symbol, Symbol] = new HashMap
var method: Symbol = _
var ctx: Context = _
@@ -1808,31 +1779,26 @@ abstract class GenICode extends SubComponent {
}
override def transform(t: Tree): Tree = {
+ val sym = t.symbol
+ def getLabel(pos: Position, name: Name) =
+ labels.getOrElseUpdate(sym,
+ method.newLabel(sym.pos, unit.fresh.newName(pos, name.toString)) setInfo sym.tpe
+ )
+
t match {
- case t @ Apply(fun, args) if (t.symbol.isLabel && !boundLabels(t.symbol)) =>
- if (!labels.isDefinedAt(t.symbol)) {
- val oldLabel = t.symbol
- val sym = method.newLabel(oldLabel.pos, unit.fresh.newName(oldLabel.pos, oldLabel.name.toString))
- sym.setInfo(oldLabel.tpe)
- labels(oldLabel) = sym
- }
- val tree = Apply(global.gen.mkAttributedRef(labels(t.symbol)), transformTrees(args)).setPos(t.pos)
+ case t @ Apply(_, args) if sym.isLabel && !boundLabels(sym) =>
+ val newSym = getLabel(sym.pos, sym.name)
+ val tree = Apply(global.gen.mkAttributedRef(newSym), transformTrees(args)) setPos t.pos
tree.tpe = t.tpe
tree
case t @ LabelDef(name, params, rhs) =>
- val name1 = unit.fresh.newName(t.pos, name.toString)
- if (!labels.isDefinedAt(t.symbol)) {
- val oldLabel = t.symbol
- val sym = method.newLabel(oldLabel.pos, name1)
- sym.setInfo(oldLabel.tpe)
- labels(oldLabel) = sym
- }
- val tree = treeCopy.LabelDef(t, name1, params, transform(rhs))
- tree.symbol = labels(t.symbol)
+ val newSym = getLabel(t.pos, name)
+ val tree = treeCopy.LabelDef(t, newSym.name, params, transform(rhs))
+ tree.symbol = newSym
- ctx.labels += (tree.symbol -> (new Label(tree.symbol) setParams(params map (_.symbol))));
- ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)));
+ ctx.labels += (newSym -> (new Label(newSym) setParams (params map (_.symbol))))
+ ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)))
tree
@@ -1853,7 +1819,7 @@ abstract class GenICode extends SubComponent {
override def equals(other: Any) = f == other;
}
- def duplicateFinalizer(boundLabels: collection.Set[Symbol], targetCtx: Context, finalizer: Tree) = {
+ def duplicateFinalizer(boundLabels: Set[Symbol], targetCtx: Context, finalizer: Tree) = {
(new DuplicateLabels(boundLabels))(targetCtx, finalizer)
}
@@ -1987,10 +1953,9 @@ abstract class GenICode extends SubComponent {
/** Return a new context for a new basic block. */
def newBlock: Context = {
val block = method.code.newBlock
- handlers foreach (h => h addCoveredBlock block)
- currentExceptionHandlers foreach (h => h.addBlock(block))
- block.varsInScope = new HashSet()
- block.varsInScope ++= scope.varsInScope
+ handlers foreach (_ addCoveredBlock block)
+ currentExceptionHandlers foreach (_ addBlock block)
+ block.varsInScope = new HashSet() ++= scope.varsInScope
new Context(this) setBasicBlock block
}
@@ -2035,7 +2000,7 @@ abstract class GenICode extends SubComponent {
* exception handler.
*/
def enterHandler(exh: ExceptionHandler): Context = {
- currentExceptionHandlers = exh :: currentExceptionHandlers
+ currentExceptionHandlers ::= exh
val ctx = newBlock
exh.setStartBlock(ctx.bb)
ctx
@@ -2086,7 +2051,7 @@ abstract class GenICode extends SubComponent {
* } ))</code>
*/
def Try(body: Context => Context,
- handlers: List[(Symbol, TypeKind, (Context => Context))],
+ handlers: List[(Symbol, TypeKind, Context => Context)],
finalizer: Tree,
tree: Tree) = if (forMSIL) TryMsil(body, handlers, finalizer, tree) else {
@@ -2099,7 +2064,7 @@ abstract class GenICode extends SubComponent {
// we need to save bound labels before any code generation is performed on
// the current context (otherwise, any new labels in the finalizer that need to
// be duplicated would be incorrectly considered bound -- see #2850).
- val boundLabels: collection.Set[Symbol] = Set.empty ++ labels.keySet
+ val boundLabels: Set[Symbol] = Set.empty ++ labels.keySet
if (guardResult) {
tmp = this.makeLocal(tree.pos, tree.tpe, "tmp")
@@ -2259,15 +2224,8 @@ abstract class GenICode extends SubComponent {
* jumps to the given basic block.
*/
def patch(code: Code) {
- def substMap: mutable.Map[Instruction, Instruction] = {
- val map = new HashMap[Instruction, Instruction]()
-
- toPatch foreach (i => map += (i -> patch(i)))
- map
- }
-
- val map = substMap
- code.blocks foreach (_.subst(map))
+ val map = toPatch map (i => (i -> patch(i))) toMap;
+ code.blocks foreach (_ subst map)
}
/**
@@ -2350,17 +2308,13 @@ abstract class GenICode extends SubComponent {
class Scope(val outer: Scope) {
val locals: ListBuffer[Local] = new ListBuffer
- def add(l: Local) =
- locals += l
-
- def remove(l: Local) =
- locals -= l
+ def add(l: Local) = locals += l
+ def remove(l: Local) = locals -= l
/** Return all locals that are in scope. */
def varsInScope: Buffer[Local] = outer.varsInScope.clone() ++= locals
- override def toString() =
- outer.toString() + locals.mkString("[", ", ", "]")
+ override def toString() = locals.mkString(outer.toString + "[", ", ", "]")
}
object EmptyScope extends Scope(null) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 32a3c550ed..68360776b3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -10,11 +10,14 @@ package icode
import java.io.PrintWriter
-import scala.collection.mutable.HashMap
-import scala.collection.mutable.{Set, HashSet, ListBuffer}
-import scala.{Symbol => scala_Symbol}
+import scala.collection.{ mutable, immutable }
+import mutable.{ HashMap, ListBuffer }
+import symtab.Flags.{ DEFERRED }
-import scala.tools.nsc.symtab.Flags
+trait ReferenceEquality {
+ override def hashCode = System.identityHashCode(this)
+ override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+}
trait Members { self: ICodes =>
import global._
@@ -38,31 +41,32 @@ trait Members { self: ICodes =>
private var _touched = false
def touched = _touched
- def touched_=(b: Boolean): Unit = if (b) {
- blocks foreach (_.touched = true)
- _touched = true
- } else
- _touched = false
+ def touched_=(b: Boolean): Unit = {
+ if (b)
+ blocks foreach (_.touched = true)
+
+ _touched = b
+ }
// Constructor code
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);
- if (b == startBlock)
- assert(b.successors.length == 1,
- "Removing start block with more than one successor.");
+ 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 (b == startBlock)
- startBlock = b.successors.head;
+ startBlock = b.successors.head
+
blocks -= b
assert(!blocks.contains(b))
- for (handler <- method.exh if handler.covers(b))
- handler.covered -= b
-
+ method.exh filter (_ covers b) foreach (_.covered -= b)
touched = true
}
@@ -109,19 +113,16 @@ trait Members { self: ICodes =>
override def toString() = symbol.fullName
- def lookupField(s: Symbol) = fields find (_.symbol == s)
+ 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)
+ def lookupMethod(s: Name) = methods find (_.symbol.name == s)
- /* determines whether or not this class contains a static ctor. */
- def containsStaticCtor: Boolean = methods.exists(_.isStaticCtor)
/* returns this methods static ctor if it has one. */
- def lookupStaticCtor: Option[IMethod] = methods.find(_.isStaticCtor)
+ def lookupStaticCtor: Option[IMethod] = methods find (_.symbol.isStaticConstructor)
}
/** Represent a field in ICode */
- class IField(val symbol: Symbol) {
- }
+ class IField(val symbol: Symbol) { }
/**
* Represents a method in ICode. Local variables contain
@@ -150,69 +151,56 @@ trait Members { self: ICodes =>
/** method parameters */
var params: List[Local] = Nil
+ def hasCode = code != null
def setCode(code: Code): IMethod = {
this.code = code;
this
}
def addLocal(l: Local): Local =
- locals find (l.==) match {
- case Some(loc) => loc
- case None =>
- locals = l :: locals;
- l
+ locals find (_ == l) getOrElse {
+ locals ::= l
+ l
}
- def addLocals(ls: List[Local]) {
- ls foreach addLocal
- }
- def addParam(p: Local) {
- if (!(params contains p)) {
- params = p :: params;
- locals = p :: locals;
+ def addParam(p: Local): Unit =
+ if (params contains p) ()
+ else {
+ params ::= p
+ locals ::= p
}
- }
- def addParams(as: List[Local]) {
- as foreach addParam
- }
-
- def lookupLocal(n: Name): Option[Local] =
- locals find ((l) => l.sym.name == n);
+ def addLocals(ls: List[Local]) = ls foreach addLocal
+ def addParams(as: List[Local]) = as foreach addParam
- def lookupLocal(sym: Symbol): Option[Local] =
- locals find ((l) => l.sym == sym);
+ def lookupLocal(n: Name): Option[Local] = locals find (_.sym.name == n)
+ def lookupLocal(sym: Symbol): Option[Local] = locals find (_.sym == sym)
- def addHandler(e: ExceptionHandler) {
- exh = e :: exh
- }
+ def addHandler(e: ExceptionHandler) = exh ::= e
- /** Is this method deferred ('abstract' in Java sense) */
- def isDeferred = (
- symbol.hasFlag(Flags.DEFERRED) ||
- symbol.owner.hasFlag(Flags.INTERFACE) ||
- native
- );
+ /** Is this method deferred ('abstract' in Java sense)?
+ * This differs from sym.isDeferred because the symbol only examines the
+ * flag, which may not be set in the other covered cases.
+ */
+ def isDeferred = (symbol hasFlag DEFERRED) || symbol.owner.isInterface || native
def isStatic: Boolean = symbol.isStaticMember
- /* determines whether or not this method is the class static constructor. */
- def isStaticCtor: Boolean = isStatic && symbol.rawname == nme.CONSTRUCTOR
-
override def toString() = symbol.fullName
import opcodes._
- def checkLocals: Unit = if (code ne null) {
- Console.println("[checking locals of " + this + "]")
- for (bb <- code.blocks; i <- bb) i match {
- case LOAD_LOCAL(l) =>
- if (!this.locals.contains(l))
- Console.println("Local " + l + " is not declared in " + this)
- case STORE_LOCAL(l) =>
- if (!this.locals.contains(l))
- Console.println("Local " + l + " is not declared in " + this)
- case _ => ()
+ def checkLocals: Unit = {
+ def localsSet = code.blocks.flatten collect {
+ case LOAD_LOCAL(l) => l
+ case STORE_LOCAL(l) => l
+ } toSet
+
+ if (code != null) {
+ Console.println("[checking locals of " + this + "]")
+ locals filterNot localsSet foreach { l =>
+ Console.println("Local " + l + " is not declared in " + this)
+ }
}
}
@@ -276,13 +264,11 @@ trait Members { self: ICodes =>
/** PC-based ranges for this local variable's visibility */
var ranges: List[(Int, Int)] = Nil
- override def equals(other: Any): Boolean = (
- other.isInstanceOf[Local] &&
- other.asInstanceOf[Local].sym == this.sym
- );
-
+ override def equals(other: Any): Boolean = other match {
+ case x: Local => sym == x.sym
+ case _ => false
+ }
override def hashCode = sym.hashCode
-
- override def toString(): String = sym.toString()
+ override def toString(): String = sym.toString
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index 7024687e0e..7f2dd7684a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -319,12 +319,12 @@ trait Opcodes { self: ICodes =>
* ->: ...:result
*
*/
- case class CALL_METHOD(method: Symbol, style: InvokeStyle) extends Instruction {
+ case class CALL_METHOD(method: Symbol, style: InvokeStyle) extends Instruction with ReferenceEquality {
/** Returns a string representation of this instruction */
override def toString(): String =
"CALL_METHOD " + hostClass.fullName + method.fullName +" ("+style.toString()+")";
- var hostClass: Symbol = method.owner;
+ var hostClass: Symbol = method.owner
def setHostClass(cls: Symbol): this.type = { hostClass = cls; this }
/** This is specifically for preserving the target native Array type long
@@ -333,38 +333,32 @@ trait Opcodes { self: ICodes =>
var targetTypeKind: TypeKind = UNIT // the default should never be used, so UNIT should fail fast.
def setTargetTypeKind(tk: TypeKind) = targetTypeKind = tk
- override def consumed = method.tpe.paramTypes.length + (
- style match {
- case Dynamic | InvokeDynamic => 1
- case Static(true) => 1
- case Static(false) => 0
- case SuperCall(_) => 1
- }
- )
+ private def params = method.info.paramTypes
+ private def consumesInstance = style match {
+ case Static(false) => 0
+ case _ => 1
+ }
+ override def consumed = params.length + consumesInstance
override def consumedTypes = {
- val args = method.tpe.paramTypes map toTypeKind
- style match {
- case Dynamic | Static(true) => AnyRefReference :: args
- case _ => args
- }
+ val args = params map toTypeKind
+ if (consumesInstance > 0) AnyRefReference :: args
+ else args
}
override def produced =
- if(toTypeKind(method.tpe.resultType) == UNIT)
- 0
- else if(method.isConstructor)
- 0
+ if (producedType == UNIT || method.isConstructor) 0
else 1
+ private def producedType: TypeKind = toTypeKind(method.info.resultType)
+ override def producedTypes =
+ if (produced == 0) Nil
+ else List(producedType)
+
/** object identity is equality for CALL_METHODs. Needed for
* being able to store such instructions into maps, when more
* than one CALL_METHOD to the same method might exist.
*/
- override def equals(other: Any) = other match {
- case o: AnyRef => this eq o
- case _ => false
- }
}
case class BOX(boxType: TypeKind) extends Instruction {
@@ -614,7 +608,6 @@ trait Opcodes { self: ICodes =>
/** This class represents a method invocation style. */
sealed abstract class InvokeStyle {
-
/** Is this a dynamic method call? */
def isDynamic: Boolean = this match {
case Dynamic => true
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
index 23e79c1a24..edbbd54769 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
@@ -24,17 +24,13 @@ trait Repository {
def available(sym: Symbol) = classes.contains(sym) || loaded.contains(sym)
/** The icode of the given class, if available */
- def icode(sym: Symbol): Option[IClass] =
- if (classes.contains(sym)) Some(classes(sym))
- else if (loaded.contains(sym)) Some(loaded(sym))
- else None
+ def icode(sym: Symbol): Option[IClass] = (classes get sym) orElse (loaded get sym)
/** The icode of the given class. If not available, it loads
* its bytecode.
*/
def icode(sym: Symbol, force: Boolean): IClass =
- if (available(sym)) icode(sym).get
- else {
+ icode(sym) getOrElse {
log("loading " + sym)
load(sym)
assert(available(sym))
@@ -46,7 +42,8 @@ trait Repository {
try {
val (c1, c2) = icodeReader.readClass(sym)
- assert(c1.symbol == sym || c2.symbol == sym, "c1.symbol = %s, c2.symbol = %s, sym = %s".format(c1.symbol, c2.symbol, sym))
+ assert(c1.symbol == sym || c2.symbol == sym,
+ "c1.symbol = %s, c2.symbol = %s, sym = %s".format(c1.symbol, c2.symbol, sym))
loaded += (c1.symbol -> c1)
loaded += (c2.symbol -> c2)
} catch {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 24e025518e..62042ce3ce 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -94,9 +94,6 @@ trait TypeKinds { self: ICodes =>
case _ => this eq other
})
- override def equals(other: Any): Boolean =
- this eq other.asInstanceOf[AnyRef]
-
/** Is this type a category 2 type in JVM terms? */
def isWideType: Boolean = this match {
case DOUBLE | LONG => true
@@ -288,11 +285,6 @@ trait TypeKinds { self: ICodes =>
}
override def isReferenceType: Boolean = true;
-
- override def equals(other: Any): Boolean = other match {
- case REFERENCE(cls2) => cls == cls2
- case _ => false
- }
}
// final case class VALUE(cls: Symbol) extends TypeKind {
@@ -356,12 +348,6 @@ trait TypeKinds { self: ICodes =>
true // TODO: platform dependent!
case _ => false
}
-
- override def equals(other: Any): Boolean = other match {
- case ARRAY(elem2) => elem == elem2
- case _ => false
- }
-
}
/** A boxed value. */
@@ -393,12 +379,6 @@ trait TypeKinds { self: ICodes =>
case _ => false
}
-
- override def equals(other: Any): Boolean = other match {
- case BOXED(kind2) => kind == kind2
- case _ => false
- }
-
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
index d334af525f..4c52d36d33 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala
@@ -3,7 +3,6 @@
* @author Martin Odersky
*/
-
package scala.tools.nsc
package backend
package icode
@@ -13,23 +12,18 @@ package icode
* @author Iulian Dragos
* @version 1.0
*/
-trait TypeStacks { self: ICodes =>
+trait TypeStacks {
+ self: ICodes =>
+
import opcodes._
- import global.{Symbol, Type, definitions}
/* This class simulates the type of the operand
* stack of the ICode.
*/
type Rep = List[TypeKind]
- class TypeStack {
- var types: Rep = Nil
-
- def this(stack: Rep) = {
- this()
- this.types = stack
- }
-
+ class TypeStack(var types: Rep) {
+ def this() = this(Nil)
def this(that: TypeStack) = this(that.types)
def length: Int = types.length
@@ -82,7 +76,7 @@ trait TypeStacks { self: ICodes =>
override def hashCode() = types.hashCode()
override def equals(other: Any): Boolean = other match {
- case x: TypeStack => x.types sameElements types
+ case x: TypeStack => x.types == types
case _ => false
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index 5d6f5045bc..1c484c7d8e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -56,14 +56,16 @@ abstract class CopyPropagation {
def emptyBinding = new HashMap[Location, Value]()
class State(val bindings: Bindings, var stack: List[Value]) {
- override def equals(that: Any): Boolean =
- (this eq that.asInstanceOf[AnyRef]) || (that match {
- /* comparison with bottom is reference equality! */
- case other: State if (this ne bottom) && (other ne bottom) =>
- (this.bindings == other.bindings) &&
- (this.stack corresponds other.stack)(_ == _) // @PP: corresponds
- case _ => false
- })
+
+ override def hashCode = bindings.hashCode + stack.hashCode
+ /* comparison with bottom is reference equality! */
+ override def equals(that: Any): Boolean = that match {
+ case x: State =>
+ if ((this eq bottom) || (this eq top) || (x eq bottom) || (x eq top)) this eq x
+ else bindings == x.bindings && stack == x.stack
+ case _ =>
+ false
+ }
/* Return an alias for the given local. It returns the last
* local in the chain of aliased locals. Cycles are not allowed
@@ -84,30 +86,20 @@ abstract class CopyPropagation {
/* Return the value bound to the given local. */
def getBinding(l: Local): Value = {
- var target = l
- var stop = false
- var value: Value = Deref(LocalVar(target))
-
- while (bindings.isDefinedAt(LocalVar(target)) && !stop) {
-// Console.println("finding binding for " + target)
- value = bindings(LocalVar(target))
- value match {
- case Deref(LocalVar(t)) => target = t
- case _ => stop = true
- }
+ def loop(lv: Local): Option[Value] = (bindings get LocalVar(lv)) match {
+ case Some(Deref(LocalVar(t))) => loop(t)
+ case x => x
}
- value
+ loop(l) getOrElse Deref(LocalVar(l))
}
/* Return the binding for the given field of the given record */
def getBinding(r: Record, f: Symbol): Value = {
- assert(r.bindings.isDefinedAt(f),
- "Record " + r + " does not contain a field " + f);
+ assert(r.bindings contains f, "Record " + r + " does not contain a field " + f)
- var target: Value = r.bindings(f);
- target match {
+ r.bindings(f) match {
case Deref(LocalVar(l)) => getBinding(l)
- case _ => target
+ case target => target
}
}
@@ -115,17 +107,10 @@ abstract class CopyPropagation {
* If the field holds a reference to a local, the returned value is the
* binding of that local.
*/
- def getFieldValue(r: Record, f: Symbol): Option[Value] = {
- if(!r.bindings.isDefinedAt(f)) None else {
- var target: Value = r.bindings(f)
- target match {
- case Deref(LocalVar(l)) => Some(getBinding(l))
- case Deref(Field(r1, f1)) => getFieldValue(r1, f1) orElse Some(target)
-// case Deref(This) => Some(target)
-// case Const(k) => Some(target)
- case _ => Some(target)
- }
- }
+ def getFieldValue(r: Record, f: Symbol): Option[Value] = r.bindings get f map {
+ case Deref(LocalVar(l)) => getBinding(l)
+ case target @ Deref(Field(r1, f1)) => getFieldValue(r1, f1) getOrElse target
+ case target => target
}
/** The same as getFieldValue, but never returns Record/Field values. Use
@@ -133,26 +118,23 @@ abstract class CopyPropagation {
* or a constant/this value).
*/
def getFieldNonRecordValue(r: Record, f: Symbol): Option[Value] = {
- assert(r.bindings.isDefinedAt(f),
- "Record " + r + " does not contain a field " + f);
+ assert(r.bindings contains f, "Record " + r + " does not contain a field " + f)
- var target: Value = r.bindings(f)
- target match {
+ r.bindings(f) match {
case Deref(LocalVar(l)) =>
val alias = getAlias(l)
val derefAlias = Deref(LocalVar(alias))
- getBinding(alias) match {
- case Record(_, _) => Some(derefAlias)
- case Deref(Field(r1, f1)) =>
- getFieldNonRecordValue(r1, f1) orElse Some(derefAlias)
- case Boxed(_) => Some(derefAlias)
- case v => Some(v)
- }
- case Deref(Field(r1, f1)) =>
- getFieldNonRecordValue(r1, f1) orElse None
- case Deref(This) => Some(target)
- case Const(k) => Some(target)
- case _ => None
+
+ Some(getBinding(alias) match {
+ case Record(_, _) => derefAlias
+ case Deref(Field(r1, f1)) => getFieldNonRecordValue(r1, f1) getOrElse derefAlias
+ case Boxed(_) => derefAlias
+ case v => v
+ })
+ case Deref(Field(r1, f1)) => getFieldNonRecordValue(r1, f1)
+ case target @ Deref(This) => Some(target)
+ case target @ Const(k) => Some(target)
+ case _ => None
}
}
@@ -174,7 +156,7 @@ abstract class CopyPropagation {
val exceptionHandlerStack = Unknown :: Nil
def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem = {
- if (a eq bottom) b
+ if (a eq bottom) b
else if (b eq bottom) a
else if (a == b) a
else {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
index c1e5a0eac7..654acc7fe9 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
@@ -5,7 +5,8 @@
package scala.tools.nsc
-package backend.icode.analysis
+package backend.icode
+package analysis
import scala.collection.mutable.{HashMap, Map}
import scala.collection.immutable.{Set, ListSet}
@@ -24,13 +25,8 @@ abstract class Liveness {
object livenessLattice extends SemiLattice {
type Elem = Set[Local]
- val top: Elem = new ListSet[Local]() {
- override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
- }
-
- val bottom: Elem = new ListSet[Local]() {
- override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
- }
+ object top extends ListSet[Local] with ReferenceEquality
+ object bottom extends ListSet[Local] with ReferenceEquality
def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem = a ++ b
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
index e993a38dfa..c0de380b02 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
@@ -5,10 +5,12 @@
package scala.tools.nsc
-package backend.icode.analysis
+package backend.icode
+package analysis
-import scala.collection.immutable.{Set, ListSet, HashSet}
-import scala.collection.mutable.{HashMap, Map}
+import scala.collection.{ mutable, immutable }
+import immutable.ListSet
+import mutable.HashMap
/** Compute reaching definitions. We are only interested in reaching
* definitions for local variables, since values on the stack
@@ -29,12 +31,12 @@ abstract class ReachingDefinitions {
type StackPos = Set[(BasicBlock, Int)]
type Stack = List[StackPos]
- val top: Elem = IState(new ListSet[Definition](), Nil)
+ private def referenceEqualSet(name: String) = new ListSet[Definition] with ReferenceEquality {
+ override def toString = "<" + name + ">"
+ }
- val bottom: Elem = IState(new ListSet[Definition]() {
- override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
- override def toString = "<bottom>"
- }, Nil)
+ val top: Elem = IState(referenceEqualSet("top"), Nil)
+ val bottom: Elem = IState(referenceEqualSet("bottom"), Nil)
/** The least upper bound is set inclusion for locals, and pairwise set inclusion for stacks. */
def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem =
@@ -43,8 +45,8 @@ abstract class ReachingDefinitions {
else {
val locals = a.vars ++ b.vars
val stack =
- if (a.stack == Nil) b.stack
- else if (b.stack == Nil) a.stack
+ if (a.stack.isEmpty) b.stack
+ else if (b.stack.isEmpty) a.stack
else (a.stack, b.stack).zipped map (_ ++ _)
IState(locals, stack)
@@ -67,10 +69,10 @@ abstract class ReachingDefinitions {
var method: IMethod = _
- val gen: Map[BasicBlock, Set[Definition]] = new HashMap()
- val kill:Map[BasicBlock, Set[Local]] = new HashMap()
- val drops: Map[BasicBlock, Int] = new HashMap()
- val outStack: Map[BasicBlock, Stack] = new HashMap()
+ val gen: mutable.Map[BasicBlock, Set[Definition]] = new HashMap()
+ val kill: mutable.Map[BasicBlock, Set[Local]] = new HashMap()
+ val drops: mutable.Map[BasicBlock, Int] = new HashMap()
+ val outStack: mutable.Map[BasicBlock, Stack] = new HashMap()
def init(m: IMethod) {
this.method = m
@@ -102,8 +104,8 @@ abstract class ReachingDefinitions {
import opcodes._
def genAndKill(b: BasicBlock): (Set[Definition], Set[Local]) = {
- var genSet: Set[Definition] = new HashSet
- var killSet: Set[Local] = new HashSet
+ var genSet: Set[Definition] = new immutable.HashSet
+ var killSet: Set[Local] = new immutable.HashSet
for ((i, idx) <- b.toList.zipWithIndex) i match {
case STORE_LOCAL(local) =>
killSet = killSet + local
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/SemiLattice.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/SemiLattice.scala
index 10c03f4455..2b41f34967 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/SemiLattice.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/SemiLattice.scala
@@ -5,7 +5,8 @@
package scala.tools.nsc
-package backend.icode.analysis
+package backend.icode
+package analysis
/** A complete lattice.
*/
@@ -16,17 +17,18 @@ trait SemiLattice {
* equals method uses reference equality for top and bottom,
* and structural equality for other values.
*/
- case class IState[V, S](val vars: V, val stack: S) {
+ final case class IState[V, S](vars: V, stack: S) {
+ override def hashCode = vars.hashCode + stack.hashCode
override def equals(other: Any): Boolean = other match {
- case that: IState[_, _] =>
- if ((this eq bottom) || (that eq bottom)) this eq that
- else if ((this eq top) || (that eq top)) this eq that
- else (stack == that.stack && vars == that.vars)
- case _ => false
+ case x: IState[_, _] =>
+ if ((this eq bottom) || (this eq top) || (x eq bottom) || (x eq top)) this eq x
+ else stack == x.stack && vars == x.vars
+ case _ =>
+ false
}
}
- /** Return the least upper bound of <code>a</code> and <code>b</code> */
+ /** Return the least upper bound of a and b. */
def lub2(exceptional: Boolean)(a: Elem, b: Elem): Elem
/** Return the top element. */
@@ -36,11 +38,8 @@ trait SemiLattice {
def bottom: Elem
/** Compute the least upper bound of a list of elements. */
- def lub(xs: List[Elem], exceptional: Boolean): Elem = try {
- if (xs == Nil) bottom else xs reduceLeft lub2(exceptional)
- } catch {
- case e: LubException =>
- Console.println("Lub on blocks: " + xs)
- throw e
- }
+ def lub(xs: List[Elem], exceptional: Boolean): Elem =
+ if (xs.isEmpty) bottom
+ else try xs reduceLeft lub2(exceptional)
+ catch { case e: LubException => Console.println("Lub on blocks: " + xs) ; throw e }
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index fd38ae0ff4..b26b799f6d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -16,17 +16,15 @@ import scala.collection.{mutable, immutable}
abstract class TypeFlowAnalysis {
val global: Global
import global._
+ import definitions.{ ObjectClass, NothingClass, AnyRefClass, StringClass }
/** The lattice of ICode types.
*/
object typeLattice extends SemiLattice {
type Elem = icodes.TypeKind
- val Object = icodes.REFERENCE(global.definitions.ObjectClass)
- val All = icodes.REFERENCE(global.definitions.NothingClass)
-
- def top = Object
- def bottom = All
+ val top = icodes.REFERENCE(ObjectClass)
+ val bottom = icodes.REFERENCE(NothingClass)
def lub2(exceptional: Boolean)(a: Elem, b: Elem) =
if (a eq bottom) b
@@ -41,9 +39,9 @@ abstract class TypeFlowAnalysis {
import icodes._
type Elem = TypeStack
- override val top = new TypeStack
- override val bottom = new TypeStack
- val exceptionHandlerStack: TypeStack = new TypeStack(List(REFERENCE(definitions.AnyRefClass)))
+ val top = new TypeStack
+ val bottom = new TypeStack
+ val exceptionHandlerStack: TypeStack = new TypeStack(List(REFERENCE(AnyRefClass)))
def lub2(exceptional: Boolean)(s1: TypeStack, s2: TypeStack) = {
if (s1 eq bottom) s2
@@ -59,10 +57,7 @@ abstract class TypeFlowAnalysis {
/** A map which returns the bottom type for unfound elements */
class VarBinding extends mutable.HashMap[icodes.Local, icodes.TypeKind] {
- override def get(l: icodes.Local) = super.get(l) match {
- case Some(t) => Some(t)
- case None => Some(typeLattice.bottom)
- }
+ override def get(l: icodes.Local) = super.get(l) orElse Some(typeLattice.bottom)
def this(o: VarBinding) = {
this()
@@ -77,32 +72,25 @@ abstract class TypeFlowAnalysis {
import icodes._
type Elem = IState[VarBinding, icodes.TypeStack]
- override val top = new Elem(new VarBinding, typeStackLattice.top)
- override val bottom = new Elem(new VarBinding, typeStackLattice.bottom)
-
-// var lubs = 0
+ val top = new Elem(new VarBinding, typeStackLattice.top)
+ val bottom = new Elem(new VarBinding, typeStackLattice.bottom)
def lub2(exceptional: Boolean)(a: Elem, b: Elem) = {
- val IState(env1, s1) = a
- val IState(env2, s2) = b
-
-// lubs += 1
+ val IState(env1, _) = a
+ val IState(env2, _) = b
val resultingLocals = new VarBinding
-
- for (binding1 <- env1.iterator) {
- val tp2 = env2(binding1._1)
- resultingLocals += ((binding1._1, typeLattice.lub2(exceptional)(binding1._2, tp2)))
+ env1 foreach { case (k, v) =>
+ resultingLocals += ((k, typeLattice.lub2(exceptional)(v, env2(k))))
}
-
- for (binding2 <- env2.iterator if resultingLocals(binding2._1) eq typeLattice.bottom) {
- val tp1 = env1(binding2._1)
- resultingLocals += ((binding2._1, typeLattice.lub2(exceptional)(binding2._2, tp1)))
+ env2 collect { case (k, v) if resultingLocals(k) eq typeLattice.bottom =>
+ resultingLocals += ((k, typeLattice.lub2(exceptional)(v, env1(k))))
}
-
- IState(resultingLocals,
+ val stack =
if (exceptional) typeStackLattice.exceptionHandlerStack
- else typeStackLattice.lub2(exceptional)(a.stack, b.stack))
+ else typeStackLattice.lub2(exceptional)(a.stack, b.stack)
+
+ IState(resultingLocals, stack)
}
}
@@ -115,7 +103,7 @@ abstract class TypeFlowAnalysis {
type P = BasicBlock
val lattice = typeFlowLattice
- val STRING = icodes.REFERENCE(TypeFlowAnalysis.this.global.definitions.StringClass)
+ val STRING = icodes.REFERENCE(StringClass)
var method: IMethod = _
/** Initialize the in/out maps for the analysis of the given method. */
@@ -131,8 +119,7 @@ abstract class TypeFlowAnalysis {
}
// start block has var bindings for each of its parameters
- val entryBindings = new VarBinding
- m.params.foreach(p => entryBindings += ((p, p.kind)))
+ val entryBindings = new VarBinding ++= (m.params map (p => ((p, p.kind))))
in(m.code.startBlock) = lattice.IState(entryBindings, typeStackLattice.bottom)
m.exh foreach { e =>
@@ -143,7 +130,7 @@ abstract class TypeFlowAnalysis {
/** reinitialize the analysis, keeping around solutions from a previous run. */
def reinit(m: icodes.IMethod) {
- if ((this.method eq null) || (this.method.symbol != m.symbol))
+ if (this.method == null || this.method.symbol != m.symbol)
init(m)
else reinit {
for (b <- m.code.blocks; if !in.isDefinedAt(b)) {
@@ -154,12 +141,12 @@ abstract class TypeFlowAnalysis {
}
/* else
in(b) = typeFlowLattice.bottom
-*/ }
+*/ }
out(b) = typeFlowLattice.bottom
}
- for (exh <- m.exh; if !in.isDefinedAt(exh.startBlock)) {
- worklist += exh.startBlock
- in(exh.startBlock) = lattice.IState(in(exh.startBlock).vars, typeStackLattice.exceptionHandlerStack)
+ m.exh map (_.startBlock) filterNot (in contains _) foreach { start =>
+ worklist += start
+ in(start) = lattice.IState(in(start).vars, typeStackLattice.exceptionHandlerStack)
}
}
}
@@ -187,12 +174,12 @@ abstract class TypeFlowAnalysis {
def blockTransfer(b: BasicBlock, in: lattice.Elem): lattice.Elem = {
b.foldLeft(in)(interpret)
}
-
/** The flow function of a given basic block. */
- var flowFun: immutable.Map[BasicBlock, TransferFunction] = new immutable.HashMap
+ /* var flowFun: immutable.Map[BasicBlock, TransferFunction] = new immutable.HashMap */
/** Fill flowFun with a transfer function per basic block. */
-/* private def buildFlowFunctions(blocks: List[BasicBlock]) {
+/*
+ private def buildFlowFunctions(blocks: List[BasicBlock]) {
def transfer(b: BasicBlock): TransferFunction = {
var gens: List[Gen] = Nil
var consumed: Int = 0
@@ -487,25 +474,9 @@ abstract class TypeFlowAnalysis {
stack push ConcatClass
}
- case CALL_METHOD(method, style) => style match {
- case Dynamic | InvokeDynamic =>
- stack.pop(1 + method.info.paramTypes.length)
- stack.push(toTypeKind(method.info.resultType))
-
- case Static(onInstance) =>
- if (onInstance) {
- stack.pop(1 + method.info.paramTypes.length)
- if (!method.isConstructor)
- stack.push(toTypeKind(method.info.resultType));
- } else {
- stack.pop(method.info.paramTypes.length)
- stack.push(toTypeKind(method.info.resultType))
- }
-
- case SuperCall(mix) =>
- stack.pop(1 + method.info.paramTypes.length)
- stack.push(toTypeKind(method.info.resultType))
- }
+ case cm @ CALL_METHOD(_, _) =>
+ stack pop cm.consumed
+ cm.producedTypes foreach (stack push _)
case BOX(kind) =>
stack.pop
@@ -566,7 +537,7 @@ abstract class TypeFlowAnalysis {
case LOAD_EXCEPTION() =>
stack.pop(stack.length)
- stack.push(typeLattice.Object)
+ stack.push(typeLattice.top)
case _ =>
dump
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 2d2146d113..57e41d9867 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -29,6 +29,12 @@ abstract class GenJVM extends SubComponent {
import global._
import icodes._
import icodes.opcodes._
+ import definitions.{
+ NullClass, RuntimeNullClass, NothingClass, RuntimeNothingClass,
+ AnyClass, ObjectClass, ThrowsClass, ThrowableClass, ClassfileAnnotationClass,
+ DeprecatedAttr,
+ getPrimitiveCompanion
+ }
val phaseName = "jvm"
@@ -78,6 +84,10 @@ abstract class GenJVM extends SubComponent {
val MIN_SWITCH_DENSITY = 0.7
val INNER_CLASSES_FLAGS =
(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT)
+
+ val PublicStatic = ACC_PUBLIC | ACC_STATIC
+ val PublicStaticFinal = ACC_PUBLIC | ACC_STATIC | ACC_FINAL
+
val StringBuilderClass = definitions.getClass2("scala.StringBuilder", "scala.collection.mutable.StringBuilder").fullName
val BoxesRunTime = "scala.runtime.BoxesRunTime"
@@ -205,7 +215,7 @@ abstract class GenJVM extends SubComponent {
(parents contains ParcelableInterface.tpe)
if (parents.isEmpty)
- parents = definitions.ObjectClass.tpe :: parents;
+ parents = ObjectClass.tpe :: parents;
for (annot <- c.symbol.annotations) annot match {
case AnnotationInfo(tp, _, _) if tp.typeSymbol == SerializableAttr =>
@@ -249,7 +259,7 @@ abstract class GenJVM extends SubComponent {
}
}
else {
- if (c.containsStaticCtor) addStaticInit(jclass, c.lookupStaticCtor)
+ c.lookupStaticCtor foreach (constructor => addStaticInit(jclass, Some(constructor)))
// it must be a top level class (name contains no $s)
def isCandidateForForwarders(sym: Symbol): Boolean =
@@ -312,7 +322,7 @@ abstract class GenJVM extends SubComponent {
!m.symbol.isGetter &&
!m.symbol.isSetter) yield javaName(m.symbol)
- val constructor = beanInfoClass.addNewMethod(JAccessFlags.ACC_PUBLIC, "<init>", JType.VOID, javaTypes(Nil), javaNames(Nil))
+ val constructor = beanInfoClass.addNewMethod(ACC_PUBLIC, "<init>", JType.VOID, javaTypes(Nil), javaNames(Nil))
val jcode = constructor.getCode().asInstanceOf[JExtendedCode]
val strKind = new JObjectType(javaName(definitions.StringClass))
val stringArrayKind = new JArrayType(strKind)
@@ -371,7 +381,7 @@ abstract class GenJVM extends SubComponent {
// put some random value; the actual number is determined at the end
buf.putShort(0xbaba.toShort)
- for (AnnotationInfo(tp, List(exc), _) <- excs.distinct if tp.typeSymbol == definitions.ThrowsClass) {
+ for (AnnotationInfo(tp, List(exc), _) <- excs.distinct if tp.typeSymbol == ThrowsClass) {
val Literal(const) = exc
buf.putShort(
cpool.addClass(
@@ -389,7 +399,7 @@ abstract class GenJVM extends SubComponent {
*/
private def shouldEmitAnnotation(annot: AnnotationInfo) =
(annot.atp.typeSymbol.initialize.hasFlag(Flags.JAVA) &&
- annot.atp.typeSymbol.isNonBottomSubClass(definitions.ClassfileAnnotationClass) &&
+ annot.atp.typeSymbol.isNonBottomSubClass(ClassfileAnnotationClass) &&
annot.args.isEmpty)
private def emitJavaAnnotations(cpool: JConstantPool, buf: ByteBuffer, annotations: List[AnnotationInfo]): Int = {
@@ -515,7 +525,7 @@ abstract class GenJVM extends SubComponent {
jmember addAttribute attr
}
- val toEmit = annotations.filter(shouldEmitAnnotation(_))
+ val toEmit = annotations filter shouldEmitAnnotation
if (toEmit.isEmpty) return
val buf: ByteBuffer = ByteBuffer.allocate(2048)
@@ -524,8 +534,8 @@ abstract class GenJVM extends SubComponent {
}
def addParamAnnotations(jmethod: JMethod, pannotss: List[List[AnnotationInfo]]) {
- val annotations = pannotss map (annots => annots.filter(shouldEmitAnnotation(_)))
- if (annotations.forall(_.isEmpty)) return;
+ val annotations = pannotss map (_ filter shouldEmitAnnotation)
+ if (annotations forall (_.isEmpty)) return
val buf: ByteBuffer = ByteBuffer.allocate(2048)
@@ -553,10 +563,8 @@ abstract class GenJVM extends SubComponent {
}
def addInnerClasses(jclass: JClass) {
- def addOwnInnerClasses(cls: Symbol) {
- for (sym <- cls.info.decls.iterator if sym.isClass)
- innerClasses = innerClasses + sym;
- }
+ def addOwnInnerClasses(cls: Symbol): Unit =
+ innerClasses ++= (cls.info.decls filter (_.isClass))
// add inner classes which might not have been referenced yet
atPhase(currentRun.erasurePhase.next) {
@@ -572,10 +580,10 @@ abstract class GenJVM extends SubComponent {
var outerName = javaName(innerSym.rawowner)
// remove the trailing '$'
if (outerName.endsWith("$") && isTopLevelModule(innerSym.rawowner))
- outerName = outerName.substring(0, outerName.length - 1)
+ outerName = outerName dropRight 1
var flags = javaFlags(innerSym)
if (innerSym.rawowner.hasFlag(Flags.MODULE))
- flags |= JAccessFlags.ACC_STATIC
+ flags |= ACC_STATIC
innerClassesAttr.addEntry(javaName(innerSym),
outerName,
@@ -596,30 +604,29 @@ abstract class GenJVM extends SubComponent {
def genField(f: IField) {
if (settings.debug.value)
- log("Adding field: " + f.symbol.fullName);
- var attributes = 0
-
- f.symbol.annotations foreach { a => a match {
- case AnnotationInfo(tp, _, _) if tp.typeSymbol == TransientAtt =>
- attributes = attributes | JAccessFlags.ACC_TRANSIENT
- case AnnotationInfo(tp, _, _) if tp.typeSymbol == VolatileAttr =>
- attributes = attributes | JAccessFlags.ACC_VOLATILE
- case _ => ();
- }}
+ log("Adding field: " + f.symbol.fullName)
+
+ val attributes = f.symbol.annotations.map(_.atp.typeSymbol).foldLeft(0) {
+ case (res, TransientAtt) => res | ACC_TRANSIENT
+ case (res, VolatileAttr) => res | ACC_VOLATILE
+ case (res, _) => res
+ }
+
var flags = javaFlags(f.symbol)
- if (!f.symbol.hasFlag(Flags.MUTABLE))
- flags = flags | JAccessFlags.ACC_FINAL
+ if (!f.symbol.isMutable)
+ flags |= ACC_FINAL
val jfield =
jclass.addNewField(flags | attributes,
javaName(f.symbol),
- javaType(f.symbol.tpe));
+ javaType(f.symbol.tpe))
+
addGenericSignature(jfield, f.symbol, clasz.symbol)
addAnnotations(jfield, f.symbol.annotations)
}
def genMethod(m: IMethod) {
- if (m.isStaticCtor) return
+ if (m.symbol.isStaticConstructor) return
log("Generating method " + m.symbol.fullName)
method = m
@@ -632,11 +639,11 @@ abstract class GenJVM extends SubComponent {
var flags = javaFlags(m.symbol)
if (jclass.isInterface())
- flags = flags | JAccessFlags.ACC_ABSTRACT;
+ flags |= ACC_ABSTRACT
// native methods of objects are generated in mirror classes
if (method.native)
- flags = flags | JAccessFlags.ACC_NATIVE
+ flags |= ACC_NATIVE
jmethod = jclass.addNewMethod(flags,
javaName(m.symbol),
@@ -679,7 +686,7 @@ abstract class GenJVM extends SubComponent {
}
addGenericSignature(jmethod, m.symbol, clasz.symbol)
- val (excs, others) = splitAnnotations(m.symbol.annotations, definitions.ThrowsClass)
+ val (excs, others) = splitAnnotations(m.symbol.annotations, ThrowsClass)
addExceptionsAttribute(jmethod, excs)
addAnnotations(jmethod, others)
addParamAnnotations(jmethod, m.params.map(_.sym.annotations))
@@ -687,7 +694,7 @@ abstract class GenJVM extends SubComponent {
private def addRemoteException(jmethod: JMethod, meth: Symbol) {
def isRemoteThrows(ainfo: AnnotationInfo) = ainfo match {
- case AnnotationInfo(tp, List(arg), _) if tp.typeSymbol == definitions.ThrowsClass =>
+ case AnnotationInfo(tp, List(arg), _) if tp.typeSymbol == ThrowsClass =>
arg match {
case Literal(Constant(tpe: Type)) if tpe.typeSymbol == RemoteException.typeSymbol => true
case _ => false
@@ -698,7 +705,7 @@ abstract class GenJVM extends SubComponent {
if (isRemoteClass ||
(meth.hasAnnotation(RemoteAttr) && jmethod.isPublic())) {
val c = Constant(RemoteException)
- val ainfo = AnnotationInfo(definitions.ThrowsClass.tpe, List(Literal(c).setType(c.tpe)), List())
+ val ainfo = AnnotationInfo(ThrowsClass.tpe, List(Literal(c).setType(c.tpe)), List())
if (!meth.annotations.exists(isRemoteThrows)) {
meth addAnnotation ainfo
}
@@ -726,15 +733,13 @@ abstract class GenJVM extends SubComponent {
}
def addModuleInstanceField {
- import JAccessFlags._
- jclass.addNewField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC,
+ jclass.addNewField(PublicStaticFinal,
nme.MODULE_INSTANCE_FIELD.toString,
jclass.getType())
}
def addStaticInit(cls: JClass, mopt: Option[IMethod]) {
- import JAccessFlags._
- val clinitMethod = cls.addNewMethod(ACC_PUBLIC | ACC_STATIC,
+ val clinitMethod = cls.addNewMethod(PublicStatic,
"<clinit>",
JType.VOID,
JType.EMPTY_ARRAY,
@@ -809,10 +814,9 @@ abstract class GenJVM extends SubComponent {
serialVUID match {
case Some(value) =>
val fieldName = "serialVersionUID"
- jclass.addNewField(ACC_STATIC | ACC_PUBLIC | ACC_FINAL,
- fieldName,
- JType.LONG)
+ jclass.addNewField(PublicStaticFinal, fieldName, JType.LONG)
clinit emitPUSH value
+ clinit.emitPUSH(value)
clinit.emitPUTSTATIC(jclass.getName(), fieldName, JType.LONG)
case None => ()
}
@@ -858,8 +862,7 @@ abstract class GenJVM extends SubComponent {
def addForwarder(jclass: JClass, module: Symbol, m: Symbol) {
import JAccessFlags._
val moduleName = javaName(module) // + "$"
- val mirrorName = moduleName.substring(0, moduleName.length() - 1)
-
+ val mirrorName = moduleName dropRight 1
val methodInfo = module.thisType.memberInfo(m)
val paramJavaTypes = methodInfo.paramTypes map toTypeKind
@@ -868,7 +871,8 @@ abstract class GenJVM extends SubComponent {
for (i <- 0 until paramJavaTypes.length)
paramNames(i) = "x_" + i
- val mirrorMethod = jclass.addNewMethod(ACC_PUBLIC | ACC_FINAL | ACC_STATIC,
+ val mirrorMethod = jclass.addNewMethod(
+ PublicStaticFinal,
javaName(m),
javaType(methodInfo.resultType),
javaTypes(paramJavaTypes),
@@ -894,7 +898,7 @@ abstract class GenJVM extends SubComponent {
if (!m.hasFlag(Flags.DEFERRED))
addGenericSignature(mirrorMethod, m, module)
- val (throws, others) = splitAnnotations(m.annotations, definitions.ThrowsClass)
+ val (throws, others) = splitAnnotations(m.annotations, ThrowsClass)
addExceptionsAttribute(mirrorMethod, throws)
addAnnotations(mirrorMethod, others)
addParamAnnotations(mirrorMethod, m.info.params.map(_.annotations))
@@ -931,14 +935,14 @@ abstract class GenJVM extends SubComponent {
/** Should method `m' get a forwarder in the mirror class? */
def shouldForward(m: Symbol): Boolean =
atPhase(currentRun.picklerPhase) (
- m.owner != definitions.ObjectClass
+ m.owner != ObjectClass
&& m.isMethod
&& !m.hasFlag(Flags.CASE | Flags.PRIVATE | Flags.PROTECTED | Flags.DEFERRED | Flags.SPECIALIZED)
&& !m.isConstructor
&& !m.isStaticMember
- && !(m.owner == definitions.AnyClass)
+ && !(m.owner == AnyClass)
&& !module.isSubClass(module.companionClass)
- && !conflictsIn(definitions.ObjectClass, m.name)
+ && !conflictsIn(ObjectClass, m.name)
&& !conflictsInCommonParent(m.name)
&& !conflictsIn(module.companionClass, m.name)
)
@@ -960,7 +964,7 @@ abstract class GenJVM extends SubComponent {
def dumpMirrorClass(clasz: Symbol, sourceFile: String) {
import JAccessFlags._
val moduleName = javaName(clasz) // + "$"
- val mirrorName = moduleName.substring(0, moduleName.length() - 1)
+ val mirrorName = moduleName dropRight 1
val mirrorClass = fjbgContext.JClass(ACC_SUPER | ACC_PUBLIC | ACC_FINAL,
mirrorName,
"java.lang.Object",
@@ -1083,7 +1087,7 @@ abstract class GenJVM extends SubComponent {
if (settings.debug.value)
log("Adding exception handler " + e + "at block: " + e.startBlock + " for " + method +
" from: " + p._1 + " to: " + p._2 + " catching: " + e.cls);
- val cls = if (e.cls == NoSymbol || e.cls == definitions.ThrowableClass) null
+ val cls = if (e.cls == NoSymbol || e.cls == ThrowableClass) null
else javaName(e.cls)
jcode.addExceptionHandler(p._1, p._2,
labels(e.startBlock).getAnchor(),
@@ -1422,10 +1426,11 @@ abstract class GenJVM extends SubComponent {
lv.start = jcode.getPC()
case SCOPE_EXIT(lv) =>
- if (varsInBlock contains lv) {
+ if (varsInBlock(lv)) {
lv.ranges = (lv.start, jcode.getPC()) :: lv.ranges
varsInBlock -= lv
- } else if (b.varsInScope contains lv) {
+ }
+ else if (b.varsInScope(lv)) {
lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges
b.varsInScope -= lv
} else
@@ -1798,21 +1803,20 @@ abstract class GenJVM extends SubComponent {
def javaName(sym: Symbol): String = {
val suffix = moduleSuffix(sym)
- if (sym == definitions.NothingClass)
- return javaName(definitions.RuntimeNothingClass)
- else if (sym == definitions.NullClass)
- return javaName(definitions.RuntimeNullClass)
- else if (definitions.primitiveCompanions(sym.companionModule))
- return javaName(definitions.getModule("scala.runtime." + sym.name))
+ if (sym == NothingClass) javaName(RuntimeNothingClass)
+ else if (sym == NullClass) javaName(RuntimeNullClass)
+ else getPrimitiveCompanion(sym.companionModule) match {
+ case Some(sym) => javaName(sym)
+ case _ =>
+ if (sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass)
+ innerClasses = innerClasses + sym
- if (sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass) {
- innerClasses = innerClasses + sym;
- }
+ val prefix =
+ if (sym.isClass || (sym.isModule && !sym.isMethod)) sym.fullName('/')
+ else sym.simpleName.toString.trim()
- (if (sym.isClass || (sym.isModule && !sym.isMethod))
- sym.fullName('/')
- else
- sym.simpleName.toString.trim()) + suffix
+ prefix + suffix
+ }
}
def javaNames(syms: List[Symbol]): Array[String] = {
@@ -1879,7 +1883,7 @@ abstract class GenJVM extends SubComponent {
sym.hasFlag(Flags.INTERFACE) ||
(sym.hasFlag(Flags.JAVA) &&
- sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass))
+ sym.isNonBottomSubClass(ClassfileAnnotationClass))
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index fc824bb8cd..bc7c88fcb8 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -212,8 +212,7 @@ abstract class ClosureElimination extends SubComponent {
/** is field 'f' accessible from method 'm'? */
def accessible(f: Symbol, m: Symbol): Boolean =
- f.isPublic || (f.hasFlag(Flags.PROTECTED) && (f.enclosingPackageClass == m.enclosingPackageClass))
-
+ f.isPublic || (f.isProtected && (f.enclosingPackageClass == m.enclosingPackageClass))
} /* class ClosureElim */
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 4149ef2ab6..224893d60b 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -7,9 +7,8 @@
package scala.tools.nsc
package backend.opt
-import scala.collection._
-import scala.collection.immutable.{Map, HashMap, Set, HashSet}
-import scala.tools.nsc.symtab._
+import scala.collection.{ mutable, immutable }
+import symtab._
/**
*/
@@ -54,7 +53,7 @@ abstract class DeadCodeElimination extends SubComponent {
val rdef = new reachingDefinitions.ReachingDefinitionsAnalysis;
/** Use-def chain: give the reaching definitions at the beginning of given instruction. */
- var defs: Map[(BasicBlock, Int), Set[rdef.lattice.Definition]] = HashMap.empty
+ var defs: immutable.Map[(BasicBlock, Int), immutable.Set[rdef.lattice.Definition]] = immutable.HashMap.empty
/** Useful instructions which have not been scanned yet. */
val worklist: mutable.Set[(BasicBlock, Int)] = new mutable.LinkedHashSet
@@ -91,7 +90,7 @@ abstract class DeadCodeElimination extends SubComponent {
/** collect reaching definitions and initial useful instructions for this method. */
def collectRDef(m: IMethod): Unit = if (m.code ne null) {
- defs = HashMap.empty; worklist.clear; useful.clear;
+ defs = immutable.HashMap.empty; worklist.clear; useful.clear;
rdef.init(m);
rdef.run;
@@ -264,19 +263,11 @@ abstract class DeadCodeElimination extends SubComponent {
}
private def findInstruction(bb: BasicBlock, i: Instruction): (BasicBlock, Int) = {
- def find(bb: BasicBlock): Option[(BasicBlock, Int)] = {
- var xs = bb.toList
- xs.zipWithIndex find { hd => hd._1 eq i } match {
- case Some((_, idx)) => Some(bb, idx)
- case None => None
- }
+ for (b <- linearizer.linearizeAt(method, bb)) {
+ val idx = b.toList indexWhere (_ eq i)
+ if (idx != -1)
+ return (b, idx)
}
-
- for (b <- linearizer.linearizeAt(method, bb))
- find(b) match {
- case Some(p) => return p
- case None => ()
- }
abort("could not find init in: " + method)
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index f662a40a26..4005b4e5c9 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -325,7 +325,6 @@ abstract class Inliners extends SubComponent {
class CallerCalleeInfo(val caller: IMethodInfo, val inc: IMethodInfo) {
def isLargeSum = caller.length + inc.length - 1 > SMALL_METHOD_SIZE
-
/** Inline 'inc' into 'caller' at the given block and instruction.
* The instruction must be a CALL_METHOD.
*/
@@ -408,41 +407,19 @@ abstract class Inliners extends SubComponent {
def isInlined(l: Local) = inlinedLocals isDefinedAt l
val newInstr = i match {
- case THIS(clasz) =>
- LOAD_LOCAL(inlinedThis)
-
- case STORE_THIS(_) =>
- STORE_LOCAL(inlinedThis)
-
- case JUMP(whereto) =>
- JUMP(inlinedBlock(whereto))
-
- case CJUMP(success, failure, cond, kind) =>
- CJUMP(inlinedBlock(success), inlinedBlock(failure), cond, kind)
-
- case CZJUMP(success, failure, cond, kind) =>
- CZJUMP(inlinedBlock(success), inlinedBlock(failure), cond, kind)
-
- case SWITCH(tags, labels) =>
- SWITCH(tags, labels map inlinedBlock)
-
- case RETURN(kind) =>
- JUMP(afterBlock)
-
- case LOAD_LOCAL(l) if isInlined(l) =>
- LOAD_LOCAL(inlinedLocals(l))
-
- case STORE_LOCAL(l) if isInlined(l) =>
- STORE_LOCAL(inlinedLocals(l))
-
- case LOAD_LOCAL(l) => assertLocal(l)
- case STORE_LOCAL(l) => assertLocal(l)
-
- case SCOPE_ENTER(l) if isInlined(l) =>
- SCOPE_ENTER(inlinedLocals(l))
-
- case SCOPE_EXIT(l) if isInlined(l) =>
- SCOPE_EXIT(inlinedLocals(l))
+ case THIS(clasz) => LOAD_LOCAL(inlinedThis)
+ case STORE_THIS(_) => STORE_LOCAL(inlinedThis)
+ case JUMP(whereto) => JUMP(inlinedBlock(whereto))
+ case CJUMP(succ, fail, cond, kind) => CJUMP(inlinedBlock(succ), inlinedBlock(fail), cond, kind)
+ case CZJUMP(succ, fail, cond, kind) => CZJUMP(inlinedBlock(succ), inlinedBlock(fail), cond, kind)
+ case SWITCH(tags, labels) => SWITCH(tags, labels map inlinedBlock)
+ case RETURN(_) => JUMP(afterBlock)
+ case LOAD_LOCAL(l) if isInlined(l) => LOAD_LOCAL(inlinedLocals(l))
+ case STORE_LOCAL(l) if isInlined(l) => STORE_LOCAL(inlinedLocals(l))
+ case LOAD_LOCAL(l) => assertLocal(l)
+ case STORE_LOCAL(l) => assertLocal(l)
+ case SCOPE_ENTER(l) if isInlined(l) => SCOPE_ENTER(inlinedLocals(l))
+ case SCOPE_EXIT(l) if isInlined(l) => SCOPE_EXIT(inlinedLocals(l))
case nw @ NEW(sym) =>
val r = NEW(sym)
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 1d11e31a19..4b5632f7d8 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -589,9 +589,14 @@ trait Definitions extends reflect.generic.StandardDefinitions {
val boxedClass = new HashMap[Symbol, Symbol]
val boxedModule = new HashMap[Symbol, Symbol]
- val unboxMethod = new HashMap[Symbol, Symbol] // Type -> Method
- val boxMethod = new HashMap[Symbol, Symbol] // Type -> Method
- val primitiveCompanions = new HashSet[Symbol]
+ val unboxMethod = new HashMap[Symbol, Symbol] // Type -> Method
+ val boxMethod = new HashMap[Symbol, Symbol] // Type -> Method
+ val primitiveCompanions = new HashSet[Symbol] // AnyVal -> Companion
+
+ /** Maps a companion object like scala.Int to scala.runtime.Int. */
+ def getPrimitiveCompanion(sym: Symbol) =
+ if (primitiveCompanions(sym)) Some(getModule("scala.runtime." + sym.name))
+ else None
def isUnbox(m: Symbol) = unboxMethod.valuesIterator contains m
def isBox(m: Symbol) = boxMethod.valuesIterator contains m
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 44bfbc5d27..b5e3366893 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -538,6 +538,10 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
final def isStatic: Boolean =
hasFlag(STATIC) || isRoot || owner.isStaticOwner
+ /** Is this symbol a static constructor? */
+ final def isStaticConstructor: Boolean =
+ isStaticMember && isClassConstructor
+
/** Is this symbol a static member of its class? (i.e. needs to be implemented as a Java static?) */
final def isStaticMember: Boolean =
hasFlag(STATIC) || owner.isImplClass