summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-08-03 01:20:37 +0000
committerPaul Phillips <paulp@improving.org>2011-08-03 01:20:37 +0000
commit39ebbf6743d0b861096051286d7608ffc9736888 (patch)
tree4b538f0302203ac2eb4466cec98dfc0eaa5bca8e
parent254ad276ca07c20a2782678a234c75ea1e7b9e83 (diff)
downloadscala-39ebbf6743d0b861096051286d7608ffc9736888.tar.gz
scala-39ebbf6743d0b861096051286d7608ffc9736888.tar.bz2
scala-39ebbf6743d0b861096051286d7608ffc9736888.zip
Finished up some backend cleanups I'd had lying...
Finished up some backend cleanups I'd had lying around since scala days. No review.
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala50
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala64
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala118
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala30
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala42
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala63
11 files changed, 172 insertions, 225 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index ff10268591..6c1245dd46 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -11,6 +11,7 @@ import mutable.{ Buffer, ArrayBuffer, ListBuffer }
import scala.util.control.ControlThrowable
import scala.tools.nsc.util.{SourceFile,CharArrayReader}
import scala.xml.{ Text, TextBuffer }
+import scala.xml.parsing.MarkupParserCommon
import scala.xml.Utility.{ isNameStart, isNameChar, isSpace }
import scala.reflect.internal.Chars.{ SU, LF }
@@ -47,7 +48,7 @@ trait MarkupParsers {
import global._
- class MarkupParser(parser: SourceFileParser, final val preserveWS: Boolean) extends scala.xml.parsing.MarkupParserCommon {
+ class MarkupParser(parser: SourceFileParser, final val preserveWS: Boolean) extends MarkupParserCommon {
import Tokens.{ EMPTY, LBRACE, RBRACE }
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 6b9f7bf79e..68651fc1c9 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -42,31 +42,33 @@ trait ParsersCommon extends ScannersCommon {
* will be called, so a parse error will still result. If the grouping is
* optional, in.token should be tested before calling these methods.
*/
- def inParens[T](body: => T): T = {
+ @inline final def inParens[T](body: => T): T = {
accept(LPAREN)
val ret = body
accept(RPAREN)
ret
}
- def inParensOrError[T](body: => T, alt: T): T =
+ @inline final def inParensOrError[T](body: => T, alt: T): T =
if (in.token == LPAREN) inParens(body)
else { accept(LPAREN) ; alt }
- def inParensOrUnit[T](body: => Tree): Tree = inParensOrError(body, Literal(Constant()))
- def inParensOrNil[T](body: => List[T]): List[T] = inParensOrError(body, Nil)
- def inBraces[T](body: => T): T = {
+ @inline final def inParensOrUnit[T](body: => Tree): Tree = inParensOrError(body, Literal(Constant()))
+ @inline final def inParensOrNil[T](body: => List[T]): List[T] = inParensOrError(body, Nil)
+
+ @inline final def inBraces[T](body: => T): T = {
accept(LBRACE)
val ret = body
accept(RBRACE)
ret
}
- def inBracesOrError[T](body: => T, alt: T): T =
+ @inline final def inBracesOrError[T](body: => T, alt: T): T =
if (in.token == LBRACE) inBraces(body)
else { accept(LBRACE) ; alt }
- def inBracesOrNil[T](body: => List[T]): List[T] = inBracesOrError(body, Nil)
- def inBracesOrUnit[T](body: => Tree): Tree = inBracesOrError(body, Literal(Constant()))
- def inBrackets[T](body: => T): T = {
+ @inline final def inBracesOrNil[T](body: => List[T]): List[T] = inBracesOrError(body, Nil)
+ @inline final def inBracesOrUnit[T](body: => Tree): Tree = inBracesOrError(body, Literal(Constant()))
+
+ @inline final def inBrackets[T](body: => T): T = {
accept(LBRACKET)
val ret = body
accept(RBRACKET)
@@ -75,7 +77,7 @@ trait ParsersCommon extends ScannersCommon {
/** Creates an actual Parens node (only used during parsing.)
*/
- def makeParens(body: => List[Tree]): Parens =
+ @inline final def makeParens(body: => List[Tree]): Parens =
Parens(inParens(if (in.token == RPAREN) Nil else body))
}
}
@@ -206,13 +208,11 @@ self =>
}
private var smartParsing = false
- private def withSmartParsing[T](body: => T): T = {
+ @inline private def withSmartParsing[T](body: => T): T = {
val saved = smartParsing
- try {
- smartParsing = true
- body
- }
- finally smartParsing = saved // false
+ smartParsing = true
+ try body
+ finally smartParsing = saved
}
val syntaxErrors = new ListBuffer[(Int, String)]
@@ -275,7 +275,7 @@ self =>
/** The types of the context bounds of type parameters of the surrounding class
*/
private var classContextBounds: List[Tree] = Nil
- private def savingClassContextBounds[T](op: => T): T = {
+ @inline private def savingClassContextBounds[T](op: => T): T = {
val saved = classContextBounds
try op
finally classContextBounds = saved
@@ -462,12 +462,10 @@ self =>
var assumedClosingParens = collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0)
private var inFunReturnType = false
- private def fromWithinReturnType[T](body: => T): T = {
+ @inline private def fromWithinReturnType[T](body: => T): T = {
val saved = inFunReturnType
- try {
- inFunReturnType = true
- body
- }
+ inFunReturnType = true
+ try body
finally inFunReturnType = saved
}
@@ -719,7 +717,7 @@ self =>
}
/** {{{ part { `sep` part } }}},or if sepFirst is true, {{{ { `sep` part } }}}. */
- def tokenSeparated[T](separator: Int, sepFirst: Boolean, part: => T): List[T] = {
+ final def tokenSeparated[T](separator: Int, sepFirst: Boolean, part: => T): List[T] = {
val ts = new ListBuffer[T]
if (!sepFirst)
ts += part
@@ -730,9 +728,9 @@ self =>
}
ts.toList
}
- def commaSeparated[T](part: => T): List[T] = tokenSeparated(COMMA, false, part)
- def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, true, part)
- def readAnnots[T](part: => T): List[T] = tokenSeparated(AT, true, part)
+ @inline final def commaSeparated[T](part: => T): List[T] = tokenSeparated(COMMA, false, part)
+ @inline final def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, true, part)
+ @inline final def readAnnots[T](part: => T): List[T] = tokenSeparated(AT, true, part)
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index dc7c494c7f..03f08dbddd 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -89,7 +89,6 @@ trait BasicBlocks {
private var instructionList: List[Instruction] = Nil
private var instrs: Array[Instruction] = _
-
override def toList: List[Instruction] =
if (closed) instrs.toList else instructionList.reverse
@@ -99,7 +98,7 @@ trait BasicBlocks {
/** return the underlying array of instructions */
def getArray: Array[Instruction] = {
- assert(closed)
+ assert(closed, this)
instrs
}
@@ -113,17 +112,18 @@ trait BasicBlocks {
* Returns -1 if not found.
*/
def indexOf(inst: Instruction): Int = {
- assert(closed)
+ assert(closed, this)
instrs indexWhere (_ eq inst)
}
/** Apply a function to all the instructions of the block. */
override def foreach[U](f: Instruction => U) = {
- if (!closed) {
- method.dump
- global.abort("Traversing an open block!: " + label + " in " + method)
- }
- instrs foreach f
+ // !!! This appears to change behavior if I try to avoid the implicit
+ // conversion and traverse the array directly, which presumably means it
+ // is dependent on some mutation which is taking place during traversal.
+ // Please eliminate this if humanly possible.
+ if (!closed) dumpMethodAndAbort(method, this)
+ else instrs foreach f
}
/** The number of instructions in this basic block so far. */
@@ -198,7 +198,7 @@ trait BasicBlocks {
* @param positions ...
*/
def removeInstructionsAt(positions: Int*) {
- assert(closed)
+ assert(closed, this)
instrs = instrs.indices.toArray filterNot positions.toSet map instrs
code.touched = true
}
@@ -248,7 +248,7 @@ trait BasicBlocks {
print()
Console.println("trying to emit: " + instr)
} */
- assert(!closed || ignore, "BasicBlock closed")
+ assert(!closed || ignore, this)
if (ignore) {
if (settings.debug.value) {
@@ -268,8 +268,8 @@ trait BasicBlocks {
}
}
- def emit(instrs: Seq[Instruction]) {
- instrs foreach (i => emit(i, i.pos))
+ def emit(is: Seq[Instruction]) {
+ is foreach (i => emit(i, i.pos))
}
/** The semantics of this are a little odd but it's designed to work
@@ -280,30 +280,30 @@ trait BasicBlocks {
* calling setPos on any instruction using the two arg version which
* I wanted to include in a call to emitOnly.
*/
- def emitOnly(instrs: Instruction*) {
- instrs foreach (i => if (i.pos == NoPosition) emit(i) else emit(i, i.pos))
- this.close
+ def emitOnly(is: Instruction*) {
+ is foreach (i => if (i.pos == NoPosition) emit(i) else emit(i, i.pos))
+ this.close()
}
/** do nothing if block is already closed */
def closeWith(instr: Instruction) {
- if (closed) () else {
+ if (!closed) {
emit(instr)
- close
+ close()
}
}
def closeWith(instr: Instruction, pos: Position) {
- if (closed) () else {
+ if (!closed) {
emit(instr, pos)
- close
+ close()
}
}
/** Close the block */
def close() {
- assert(!closed || ignore)
- assert(instructionList.nonEmpty, "Empty block.")
+ assert(!closed || ignore, this)
+ assert(instructionList.nonEmpty, "Empty block: " + this)
closed = true
setFlag(DIRTYSUCCS)
instructionList = instructionList.reverse
@@ -311,7 +311,7 @@ trait BasicBlocks {
}
def open() {
- assert(closed)
+ assert(closed, this)
closed = false
ignore = false
touched = true
@@ -324,7 +324,7 @@ trait BasicBlocks {
preds = null
}
- override def isEmpty: Boolean = instructionList.isEmpty
+ override def isEmpty = instructionList.isEmpty
/** Enter ignore mode: new 'emit'ted instructions will not be
* added to this basic block. It makes the generation of THROW
@@ -335,7 +335,7 @@ trait BasicBlocks {
}
def exitIgnoreMode() {
- assert(ignore, "Exit ignore mode when not in ignore mode.")
+ assert(ignore, "Exit ignore mode when not in ignore mode: " + this)
ignore = false
}
@@ -374,10 +374,8 @@ trait BasicBlocks {
case RETURN(_) => Nil
case THROW(_) => Nil
case _ =>
- if (closed) {
- dump
- global.abort("The last instruction is not a control flow instruction: " + lastInstruction)
- }
+ if (closed)
+ dumpClassesAndAbort("The last instruction is not a control flow instruction: " + lastInstruction)
else Nil
}
@@ -440,11 +438,11 @@ trait BasicBlocks {
object BBFlags {
val flagMap = Map[Int, String](
LOOP_HEADER -> "loopheader",
- IGNORING -> "ignore",
- EX_HEADER -> "exheader",
- CLOSED -> "closed",
- DIRTYSUCCS -> "dirtysuccs",
- DIRTYPREDS -> "dirtypreds"
+ IGNORING -> "ignore",
+ EX_HEADER -> "exheader",
+ CLOSED -> "closed",
+ DIRTYSUCCS -> "dirtysuccs",
+ DIRTYPREDS -> "dirtypreds"
)
def flagsToString(flags: Int) = {
flagMap collect { case (bit, name) if (bit & flags) != 0 => "<" + name + ">" } mkString " "
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 4d997b44fd..76af2a7a03 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -39,6 +39,11 @@ abstract class GenICode extends SubComponent {
override def newPhase(prev: Phase) = new ICodePhase(prev)
+ @inline private def debugassert(cond: => Boolean, msg: => Any) {
+ if (settings.debug.value)
+ assert(cond, msg)
+ }
+
class ICodePhase(prev: Phase) extends StdPhase(prev) {
override def description = "Generate ICode from the AST"
@@ -190,13 +195,11 @@ abstract class GenICode extends SubComponent {
var ctx1 = ctx
var resKind = toTypeKind(larg.tpe)
- if (settings.debug.value) {
- assert(args.length <= 1,
+ debugassert(args.length <= 1,
"Too many arguments for primitive function: " + fun.symbol)
- assert(resKind.isNumericType | resKind == BOOL,
+ debugassert(resKind.isNumericType | resKind == BOOL,
resKind.toString() + " is not a numeric or boolean type " +
"[operation: " + fun.symbol + "]")
- }
args match {
// unary operation
@@ -267,16 +270,14 @@ abstract class GenICode extends SubComponent {
if (scalaPrimitives.isArrayGet(code)) {
// load argument on stack
- if (settings.debug.value)
- assert(args.length == 1,
+ debugassert(args.length == 1,
"Too many arguments for array get operation: " + tree);
ctx1 = genLoad(args.head, ctx1, INT)
generatedType = elem
ctx1.bb.emit(LOAD_ARRAY_ITEM(elementType), tree.pos)
}
else if (scalaPrimitives.isArraySet(code)) {
- if (settings.debug.value)
- assert(args.length == 2,
+ debugassert(args.length == 2,
"Too many arguments for array set operation: " + tree);
ctx1 = genLoad(args.head, ctx1, INT)
ctx1 = genLoad(args.tail.head, ctx1, toTypeKind(args.tail.head.tpe))
@@ -369,7 +370,7 @@ abstract class GenICode extends SubComponent {
thenCtx = genLoad(thenp, thenCtx, resKind)
elseCtx = genLoad(elsep, elseCtx, resKind)
- assert(!settings.debug.value || !(hasUnitBranch && expectedType != UNIT),
+ debugassert(!hasUnitBranch || expectedType == UNIT,
"I produce UNIT in a context where " + expectedType + " is expected!")
// alternatives may be already closed by a tail-recursive jump
@@ -431,9 +432,8 @@ abstract class GenICode extends SubComponent {
else if (isArrayOp(code))
genArrayOp(tree, ctx, code, expectedType)
else if (isLogicalOp(code) || isComparisonOp(code)) {
- val trueCtx = ctx.newBlock
- val falseCtx = ctx.newBlock
- val afterCtx = ctx.newBlock
+ val trueCtx, falseCtx, afterCtx = ctx.newBlock
+
genCond(tree, ctx, trueCtx, falseCtx)
trueCtx.bb.emitOnly(
CONSTANT(Constant(true)) setPos tree.pos,
@@ -452,35 +452,25 @@ abstract class GenICode extends SubComponent {
genCoercion(tree, ctx1, code)
(ctx1, scalaPrimitives.generatedKind(code))
}
- else abort("Primitive operation not handled yet: " + sym.fullName + "(" +
- fun.symbol.simpleName + ") " + " at: " + (tree.pos))
+ else abort(
+ "Primitive operation not handled yet: " + sym.fullName + "(" +
+ fun.symbol.simpleName + ") " + " at: " + (tree.pos)
+ )
}
/**
* forMSIL
*/
- private def msil_IsValuetypeInstMethod(msym: Symbol) = {
- val mMSILOpt = loaders.clrTypes.methods.get(msym)
- if (mMSILOpt.isEmpty) false
- else {
- val mMSIL = mMSILOpt.get
- val res = mMSIL.IsInstance && mMSIL.DeclaringType.IsValueType
- res
- }
- }
-
- /**
- * forMSIL
- */
- private def msil_IsValuetypeInstField(fsym: Symbol) = {
- val fMSILOpt = loaders.clrTypes.fields.get(fsym)
- if (fMSILOpt.isEmpty) false
- else {
- val fMSIL = fMSILOpt.get
- val res = !fMSIL.IsStatic && fMSIL.DeclaringType.IsValueType
- res
- }
- }
+ private def msil_IsValuetypeInstMethod(msym: Symbol) = (
+ loaders.clrTypes.methods get msym exists (mMSIL =>
+ mMSIL.IsInstance && mMSIL.DeclaringType.IsValueType
+ )
+ )
+ private def msil_IsValuetypeInstField(fsym: Symbol) = (
+ loaders.clrTypes.fields get fsym exists (fMSIL =>
+ !fMSIL.IsStatic && fMSIL.DeclaringType.IsValueType
+ )
+ )
/**
* forMSIL: Adds a local var, the emitted code requires one more slot on the stack as on entry
@@ -553,8 +543,7 @@ abstract class GenICode extends SubComponent {
if (scalaPrimitives.isArrayGet(code)) {
var ctx1 = genLoad(arrayObj, ctx, k)
// load argument on stack
- if (settings.debug.value)
- assert(args.length == 1, "Too many arguments for array get operation: " + tree);
+ debugassert(args.length == 1, "Too many arguments for array get operation: " + tree)
ctx1 = genLoad(args.head, ctx1, INT)
generatedType = elementType // actually "managed pointer to element type" but the callsite is aware of this
ctx1.bb.emit(CIL_LOAD_ARRAY_ITEM_ADDRESS(elementType), tree.pos)
@@ -576,7 +565,7 @@ abstract class GenICode extends SubComponent {
Even if it's not, the code below to handler !addressTaken below. */
}
- if(!addressTaken) {
+ if (!addressTaken) {
resCtx = genLoad(tree, ctx, expectedType)
if (!butRawValueIsAlsoGoodEnough) {
// raw value on stack (must be an intermediate result, e.g. returned by method call), take address
@@ -666,7 +655,7 @@ abstract class GenICode extends SubComponent {
var ctx1 = genLoad(expr, ctx, returnedKind)
lazy val tmp = ctx1.makeLocal(tree.pos, expr.tpe, "tmp")
val saved = savingCleanups(ctx1) {
- var saved = false
+ var savedFinalizer = false
ctx1.cleanups foreach {
case MonitorRelease(m) =>
debuglog("removing " + m + " from cleanups: " + ctx1.cleanups)
@@ -675,11 +664,10 @@ abstract class GenICode extends SubComponent {
case Finalizer(f, finalizerCtx) =>
debuglog("removing " + f + " from cleanups: " + ctx1.cleanups)
-
if (returnedKind != UNIT && mayCleanStack(f)) {
log("Emitting STORE_LOCAL for " + tmp + " to save finalizer.")
ctx1.bb.emit(STORE_LOCAL(tmp))
- saved = true
+ savedFinalizer = true
}
// duplicate finalizer (takes care of anchored labels)
@@ -692,7 +680,7 @@ abstract class GenICode extends SubComponent {
ctx1.bb.closeWith(JUMP(fctx.bb))
ctx1 = genLoad(f1, fctx, UNIT)
}
- saved
+ savedFinalizer
}
if (saved) {
@@ -705,7 +693,7 @@ abstract class GenICode extends SubComponent {
generatedType = expectedType
ctx1
- case t @ Try(_, _, _) => genLoadTry(t, ctx, (x: TypeKind) => generatedType = x)
+ case t @ Try(_, _, _) => genLoadTry(t, ctx, generatedType = _)
case Throw(expr) =>
val (ctx1, expectedType) = genThrow(expr, ctx)
@@ -778,13 +766,11 @@ abstract class GenICode extends SubComponent {
// instance (on JVM, <init> methods return VOID).
case Apply(fun @ Select(New(tpt), nme.CONSTRUCTOR), args) =>
val ctor = fun.symbol
- if (settings.debug.value)
- assert(ctor.isClassConstructor,
+ debugassert(ctor.isClassConstructor,
"'new' call to non-constructor: " + ctor.name)
generatedType = toTypeKind(tpt.tpe)
- if (settings.debug.value)
- assert(generatedType.isReferenceType || generatedType.isArrayType,
+ debugassert(generatedType.isReferenceType || generatedType.isArrayType,
"Non reference type cannot be instantiated: " + generatedType)
generatedType match {
@@ -801,8 +787,7 @@ abstract class GenICode extends SubComponent {
ctx1
case rt @ REFERENCE(cls) =>
- if (settings.debug.value)
- assert(ctor.owner == cls,
+ debugassert(ctor.owner == cls,
"Symbol " + ctor.owner.fullName + " is different than " + tpt)
val ctx2 = if (forMSIL && loaders.clrTypes.isNonEnumValuetype(cls)) {
@@ -960,13 +945,12 @@ abstract class GenICode extends SubComponent {
ctx
case Select(Ident(nme.EMPTY_PACKAGE_NAME), module) =>
- if (settings.debug.value) {
- assert(tree.symbol.isModule,
- "Selection of non-module from empty package: " + tree.toString() +
- " sym: " + tree.symbol +
- " at: " + (tree.pos))
- log("LOAD_MODULE from Select(<emptypackage>): " + tree.symbol);
- }
+ debugassert(tree.symbol.isModule,
+ "Selection of non-module from empty package: " + tree +
+ " sym: " + tree.symbol + " at: " + (tree.pos)
+ )
+ debuglog("LOAD_MODULE from Select(<emptypackage>): " + tree.symbol)
+
assert(!tree.symbol.isPackageClass, "Cannot use package as value: " + tree)
genLoadModule(ctx, tree.symbol, tree.pos)
ctx
@@ -1121,10 +1105,7 @@ abstract class GenICode extends SubComponent {
debuglog("Dropped an " + from);
case _ =>
- if (settings.debug.value) {
- assert(from != UNIT,
- "Can't convert from UNIT to " + to + " at: " + pos)
- }
+ debugassert(from != UNIT, "Can't convert from UNIT to " + to + " at: " + pos)
assert(!from.isReferenceType && !to.isReferenceType,
"type error: can't convert from " + from + " to " + to +" in unit " + unit.source + " at " + pos)
@@ -1169,11 +1150,10 @@ 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) {
- assert(args.length == label.params.length,
- "Wrong number of arguments in call to label " + label.symbol)
- }
-
+ debugassert(
+ args.length == label.params.length,
+ "Wrong number of arguments in call to label " + label.symbol
+ )
var ctx1 = ctx
def isTrivial(kv: (Tree, Symbol)) = kv match {
@@ -1623,8 +1603,7 @@ abstract class GenICode extends SubComponent {
* class.
*/
private def addClassFields(ctx: Context, cls: Symbol) {
- if (settings.debug.value)
- assert(ctx.clazz.symbol eq cls,
+ debugassert(ctx.clazz.symbol eq cls,
"Classes are not the same: " + ctx.clazz.symbol + ", " + cls)
/** Non-method term members are fields, except for module members. Module
@@ -1718,8 +1697,7 @@ abstract class GenICode extends SubComponent {
case JUMP(b) if (b == block) =>
debuglog("Pruning empty JMP branch.");
val replaced = p.replaceInstruction(p.lastInstruction, JUMP(cont))
- if (settings.debug.value)
- assert(replaced, "Didn't find p.lastInstruction")
+ debugassert(replaced, "Didn't find p.lastInstruction")
case SWITCH(tags, labels) if (labels contains block) =>
debuglog("Pruning empty SWITCH branch.");
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index 06c3ee2a9e..7a0017944b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -53,6 +53,9 @@ abstract class ICodes extends AnyRef
case x => global.abort("Unknown linearizer: " + x)
}
+ def newTextPrinter() =
+ new TextPrinter(new PrintWriter(Console.out, true), new DumpLinearizer)
+
/** Have to be careful because dump calls around, possibly
* re-entering methods which initiated the dump (like foreach
* in BasicBlocks) which leads to the icode output olympics.
@@ -61,20 +64,27 @@ abstract class ICodes extends AnyRef
/** Print all classes and basic blocks. Used for debugging. */
- def dump() {
- if (alreadyDumping) return
+ def dumpClassesAndAbort(msg: String): Nothing = {
+ if (alreadyDumping) global.abort(msg)
else alreadyDumping = true
- val printer = new TextPrinter(new PrintWriter(Console.out, true),
- new DumpLinearizer)
-
+ Console.println(msg)
+ val printer = newTextPrinter()
classes.values foreach printer.printClass
+ global.abort(msg)
+ }
+
+ def dumpMethodAndAbort(m: IMethod, msg: String): Nothing = {
+ Console.println("Fatal bug in inlinerwhile traversing " + m + ": " + msg)
+ m.dump()
+ global.abort("" + m)
}
+ def dumpMethodAndAbort(m: IMethod, b: BasicBlock): Nothing =
+ dumpMethodAndAbort(m, "found open block " + b + " " + b.flagsString)
def checkValid(m: IMethod) {
- // always dicey to iterate over mutable structures
+ // always slightly dicey to iterate over mutable structures
val bs = m.code.blocks.toList
-
for (b <- bs ; if !b.closed) {
// Something is leaving open/empty blocks around (see SI-4840) so
// let's not kill the deal unless it's nonempty.
@@ -82,11 +92,7 @@ abstract class ICodes extends AnyRef
log("!!! Found open but empty block while inlining " + m + ": removing from block list.")
m.code removeBlock b
}
- else {
- Console.println("Fatal bug in inliner: found open block when inlining " + m)
- m.dump
- global.abort("Open block was: " + b + " " + b.flagsString)
- }
+ else dumpMethodAndAbort(m, b)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 47da7c2e31..4e02371a7e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -254,9 +254,8 @@ trait Members { self: ICodes =>
}
def dump() {
- val printer = new TextPrinter(new PrintWriter(Console.out, true),
- new DumpLinearizer)
- printer.printMethod(this)
+ Console.println("dumping IMethod(" + symbol + ")")
+ newTextPrinter() printMethod this
}
}
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 66acb8e4fe..16cba38f9a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -233,12 +233,7 @@ abstract class CopyPropagation {
/** Abstract interpretation for one instruction. */
def interpret(in: copyLattice.Elem, i: Instruction): copyLattice.Elem = {
var out = in.dup
-
- if (settings.debug.value) {
- log("- " + i)
- log("in: " + in)
- log("\n")
- }
+ debuglog("- " + i + "\nin: " + in + "\n")
i match {
case THIS(_) =>
@@ -421,8 +416,7 @@ abstract class CopyPropagation {
out.stack = Unknown :: Nil
case _ =>
- dump
- abort("Unknown instruction: " + i)
+ dumpClassesAndAbort("Unknown instruction: " + i)
}
out
} /* def interpret */
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 3d556c04ab..c2994c66a5 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -358,9 +358,7 @@ abstract class TypeFlowAnalysis {
stack.push(typeLattice.Object)
case _ =>
- dump
- abort("Unknown instruction: " + i)
-
+ dumpClassesAndAbort("Unknown instruction: " + i)
}
new TransferFunction(consumed, gens)
@@ -542,9 +540,7 @@ abstract class TypeFlowAnalysis {
stack.push(typeLattice.top)
case _ =>
- dump
- abort("Unknown instruction: " + i)
-
+ dumpClassesAndAbort("Unknown instruction: " + i)
}
out
} // interpret
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 2acd343ac1..baee596f5f 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -191,7 +191,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val versionPickle = {
val vp = new PickleBuffer(new Array[Byte](16), -1, 0)
- assert(vp.writeIndex == 0)
+ assert(vp.writeIndex == 0, vp)
vp writeNat PickleFormat.MajorVersion
vp writeNat PickleFormat.MinorVersion
vp writeNat 0
@@ -324,7 +324,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (isTopLevelModule(c.symbol)) {
if (c.symbol.companionClass == NoSymbol)
- dumpMirrorClass(c.symbol, c.cunit.source.toString)
+ generateMirrorClass(c.symbol, c.cunit.source.toString)
else
log("No mirror class for module with linked class: " +
c.symbol.fullName)
@@ -388,7 +388,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
)
} else if (clazz.isAnonymousClass) {
val enclClass = clazz.rawowner
- assert(enclClass.isClass, "" + enclClass)
+ assert(enclClass.isClass, enclClass)
val sym = enclClass.primaryConstructor
if (sym == NoSymbol)
log("Ran out of room looking for an enclosing method for %s: no constructor here.".format(
@@ -497,7 +497,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
nattr += 1
}
- assert(nattr > 0)
+ assert(nattr > 0, nattr)
buf.putShort(0, nattr.toShort)
addAttribute(jmethod, tpnme.ExceptionsATTR, buf)
}
@@ -579,7 +579,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val AnnotationInfo(typ, args, assocs) = annotInfo
val jtype = javaType(typ)
buf putShort cpool.addUtf8(jtype.getSignature()).toShort
- assert(args.isEmpty, args.toString)
+ assert(args.isEmpty, args)
buf putShort assocs.length.toShort
for ((name, value) <- assocs) {
buf putShort cpool.addUtf8(name.toString).toShort
@@ -1061,7 +1061,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* object: method signature is not taken into account.
*/
def addForwarders(jclass: JClass, moduleClass: Symbol) {
- assert(moduleClass.isModuleClass)
+ assert(moduleClass.isModuleClass, moduleClass)
debuglog("Dumping mirror class for object: " + moduleClass)
val className = jclass.getName
@@ -1096,13 +1096,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
}
- /** Dump a mirror class for a top-level module. A mirror class is a class
+ /** Generate a mirror class for a top-level module. A mirror class is a class
* containing only static methods that forward to the corresponding method
* on the MODULE instance of the given Scala object. It will only be
* generated if there is no companion class: if there is, an attempt will
* instead be made to add the forwarder methods to the companion class.
*/
- def dumpMirrorClass(clasz: Symbol, sourceFile: String) {
+ def generateMirrorClass(clasz: Symbol, sourceFile: String) {
import JAccessFlags._
val moduleName = javaName(clasz) // + "$"
val mirrorName = moduleName.substring(0, moduleName.length() - 1)
@@ -1216,18 +1216,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
varsInBlock.clear()
for (instr <- b) {
- class CompilationException(msg: String) extends Exception(msg) {
- override def toString: String = {
- msg +
- "\nCurrent method: " + method +
- "\nCurrent block: " + b +
- "\nCurrent instruction: " + instr +
- "\n---------------------" +
- method.dump
- }
- }
- def assert(cond: Boolean, msg: String) =
- if (!cond) throw new CompilationException(msg)
instr match {
case THIS(clasz) =>
@@ -1539,8 +1527,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
else if (b.varsInScope(lv)) {
lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges
b.varsInScope -= lv
- } else
- assert(false, "Illegal local var nesting: " + method)
+ }
+ else dumpMethodAndAbort(method, "Illegal local var nesting")
case LOAD_EXCEPTION(_) =>
()
@@ -1832,8 +1820,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
def indexOf(local: Local): Int = {
- assert(local.index >= 0,
- "Invalid index for: " + local + "{" + local.## + "}: ")
+ assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ")
local.index
}
@@ -1876,13 +1863,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
case ((s1, e1) :: rest, (s2, e2)) if (e1 == s2) => (s1, e2) :: rest
case _ => p :: collapsed
}}).reverse
-
- def assert(cond: Boolean, msg: => String) = if (!cond) {
- method.dump
- abort(msg + "\nMethod: " + method)
- }
-
- def assert(cond: Boolean) { assert(cond, "Assertion failed.") }
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 84f73223d5..2f49b3b747 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -494,7 +494,7 @@ abstract class GenMSIL extends SubComponent {
if (isTopLevelModule(sym)) {
if (sym.companionClass == NoSymbol)
- dumpMirrorClass(sym)
+ generateMirrorClass(sym)
else
log("No mirror class for module with linked class: " +
sym.fullName)
@@ -2048,7 +2048,7 @@ abstract class GenMSIL extends SubComponent {
sicode.Emit(OpCodes.Ret)
}
- private def dumpMirrorClass(sym: Symbol) {
+ private def generateMirrorClass(sym: Symbol) {
val tBuilder = getType(sym)
assert(sym.isModuleClass, "Can't generate Mirror-Class for the Non-Module class " + sym)
debuglog("Dumping mirror class for object: " + sym)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 94a67bf375..cbc394f94c 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -191,15 +191,15 @@ abstract class ICodeReader extends ClassfileParser {
log("forcing " + iface.owner + " at phase: " + phase + " impl: " + iface.implClass)
iface.owner.info // force the mixin type-transformer
definitions.getClass(name)
- } else if (name.endsWith(nme.MODULE_SUFFIX_STRING)) {
- val sym = forceMangledName(name.subName(0, name.length -1).decode, true)
-// println("classNameToSymbol: " + name + " sym: " + sym)
- if (name.toString == "scala.collection.immutable.Stream$$hash$colon$colon$")
- print("")
- if (sym == NoSymbol)
- definitions.getModule(name.subName(0, name.length - 1))
+ }
+ else if (nme.isModuleName(name)) {
+ val strippedName = nme.stripModuleSuffix(name)
+ val sym = forceMangledName(strippedName.decode, true)
+
+ if (sym == NoSymbol) definitions.getModule(strippedName)
else sym
- } else {
+ }
+ else {
forceMangledName(name, false)
atPhase(currentRun.flattenPhase.next)(definitions.getClass(name))
}
@@ -632,10 +632,12 @@ abstract class ICodeReader extends ClassfileParser {
assert(method.code ne null)
// reverse parameters, as they were prepended during code generation
method.params = method.params.reverse
- if (code.containsDUPX) {
- code.resolveDups
- }
- if (code.containsNEW) code.resolveNEWs
+
+ if (code.containsDUPX)
+ code.resolveDups()
+
+ if (code.containsNEW)
+ code.resolveNEWs()
}
/** Note: these methods are different from the methods of the same name found
@@ -922,33 +924,28 @@ abstract class ICodeReader extends ClassfileParser {
/** Recover def-use chains for NEW and initializers. */
def resolveNEWs() {
import opcodes._
-
val rdef = new reachingDefinitions.ReachingDefinitionsAnalysis
rdef.init(method)
rdef.run
- for (bb <- method.code.blocks) {
- var info = rdef.in(bb)
- for ((i, idx) <- bb.toList.zipWithIndex) i match {
- case CALL_METHOD(m, Static(true)) if m.isClassConstructor =>
- val defs = rdef.findDefs(bb, idx, 1, m.info.paramTypes.length)
- debuglog("ctor: " + i + " found defs: " + defs)
- assert(defs.length == 1, "wrong defs at bb " + bb + "\n" + method.dump + rdef)
- val (bb1, idx1) = defs.head
- var producer = bb1(idx1)
- while (producer.isInstanceOf[DUP]) {
- val (bb2, idx2) = rdef.findDefs(bb1, idx1, 1).head
- producer = bb2(idx2)
- }
- producer match {
- case nw: NEW => nw.init = i.asInstanceOf[CALL_METHOD]
- case _: THIS => () // super constructor call
- case _ => assert(false, producer + "\n" + method.dump)
+ for (bb <- method.code.blocks ; (i, idx) <- bb.toList.zipWithIndex) i match {
+ case cm @ CALL_METHOD(m, Static(true)) if m.isClassConstructor =>
+ def loop(bb0: BasicBlock, idx0: Int, depth: Int = 0): Unit = {
+ rdef.findDefs(bb0, idx0, 1, depth) match {
+ case ((bb1, idx1)) :: _ =>
+ bb1(idx1) match {
+ case _: DUP => loop(bb1, idx1, 0)
+ case x: NEW => x.init = cm
+ case _: THIS => () // super constructor call
+ case producer => dumpMethodAndAbort(method, "producer: " + producer)
+ }
+ case _ => ()
}
- case _ =>
- }
- }
+ }
+ loop(bb, idx, m.info.paramTypes.length)
+ case _ => ()
+ }
}
/** Return the local at given index, with the given type. */