diff options
author | Paul Phillips <paulp@improving.org> | 2011-08-03 01:20:37 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-08-03 01:20:37 +0000 |
commit | 39ebbf6743d0b861096051286d7608ffc9736888 (patch) | |
tree | 4b538f0302203ac2eb4466cec98dfc0eaa5bca8e /src | |
parent | 254ad276ca07c20a2782678a234c75ea1e7b9e83 (diff) | |
download | scala-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.
Diffstat (limited to 'src')
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. */ |