diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2008-10-28 17:58:19 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2008-10-28 17:58:19 +0000 |
commit | 4149421661d0b2401312515ac0c4f4e54a83b3c2 (patch) | |
tree | 6ff125ca3376fa361c59b6ae80482cc8df98be8b | |
parent | 0a14ec63938d84f1750611c3ea1acca2f38a033c (diff) | |
download | scala-4149421661d0b2401312515ac0c4f4e54a83b3c2.tar.gz scala-4149421661d0b2401312515ac0c4f4e54a83b3c2.tar.bz2 scala-4149421661d0b2401312515ac0c4f4e54a83b3c2.zip |
Propagated fixes for optimizer (fixed #1402 and...
Propagated fixes for optimizer (fixed #1402 and #1379)
10 files changed, 78 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index b50bb8aebc..d3ea32d8bc 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -412,7 +412,23 @@ trait BasicBlocks { method.exh.foreach { e: ExceptionHandler => if (e.covers(this)) res = e.startBlock :: res } - res + res ++ exceptionalSucc(this, res) + } + + /** 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)) List(h.startBlock) else Nil + } + ss ++ (ss flatMap findSucc) + } + + succs.flatMap(findSucc).removeDuplicates } /** Returns the precessors of this block, in the current 'code' chunk. @@ -468,6 +484,6 @@ object BBFlags { /** This block is closed. No new instructions can be added. */ final val CLOSED = 0x00000008 - /** This block has been changed, chached results are recomputed. */ + /** This block has been changed, cached results are recomputed. */ final val TOUCHED = 0x00000010 } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala index 46b5066e63..dc435bd2e9 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Checkers.scala @@ -67,10 +67,11 @@ abstract class Checkers { val STRING = REFERENCE(definitions.StringClass) val SCALA_ALL = REFERENCE(definitions.NothingClass) val SCALA_ALL_REF = REFERENCE(definitions.NullClass) -// val CASE_CLASS = REFERENCE(definitions.getClass("scala.CaseClass")) + val THROWABLE = REFERENCE(definitions.ThrowableClass) def checkICodes: Unit = { - Console.println("[[consistency check at beginning of phase " + globalPhase.name + "]]") + if (settings.verbose.value) + println("[[consistency check at the beginning of phase " + globalPhase.name + "]]") classes.values foreach check } @@ -554,6 +555,12 @@ abstract class Checkers { stack.pop stack.push(kind) + case LOAD_EXCEPTION() => + stack.push(THROWABLE) + + case SCOPE_ENTER(_) | SCOPE_EXIT(_) => + () + case _ => abort("Unknown instruction: " + instr) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala index 8c6d9a4490..94db998bff 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala @@ -7,8 +7,7 @@ package scala.tools.nsc.backend.icode; -import scala.collection.mutable.HashMap; -import scala.collection.mutable.HashSet; +import scala.collection._ /** * Exception handlers are pieces of code that `handle' exceptions on @@ -34,15 +33,15 @@ trait ExceptionHandlers { self: ICodes => def startBlock = _startBlock; /** The list of blocks that are covered by this exception handler */ - var covered: List[BasicBlock] = Nil; + var covered: immutable.Set[BasicBlock] = immutable.HashSet.empty[BasicBlock] def addCoveredBlock(b: BasicBlock): ExceptionHandler = { - covered = b :: covered; + covered = covered + b this } /** Is `b' covered by this exception handler? */ - def covers(b: BasicBlock): Boolean = covered.contains(b); + def covers(b: BasicBlock): Boolean = covered(b); /** The body of this exception handler. May contain 'dead' blocks (which will not * make it into generated code because linearizers may not include them) */ diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 5dcebe7ecf..a1fd3c7ae5 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -269,7 +269,7 @@ trait Members { self: ICodes => succ.toList foreach { i => bb.emit(i, i.pos) } code.removeBlock(succ) nextBlock -= bb - exh foreach { e => e.covered = e.covered.remove { b1 => b1 == succ } } + exh foreach { e => e.covered = e.covered - succ } } while (nextBlock.isDefinedAt(succ)) bb.close } else diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index e8d7b2a6c9..2bdb1eaa43 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -132,7 +132,7 @@ abstract class GenJVM extends SubComponent { } if (!(jclass.getName().endsWith("$") && sym.isModuleClass)) addScalaAttr(if (isTopLevelModule(sym)) sym.sourceModule else sym); - addInnerClasses + addInnerClasses(jclass) val outfile = getFile(jclass, ".class") val outstream = new DataOutputStream(outfile.output) @@ -405,7 +405,7 @@ abstract class GenJVM extends SubComponent { } def addGenericSignature(jmember: JMember, sym: Symbol) { - if (!sym.hasFlag(Flags.PRIVATE | Flags.EXPANDEDNAME | Flags.SYNTHETIC) && settings.target.value == "jvm-1.5") { + if (settings.target.value == "jvm-1.5") { erasure.javaSig(sym) match { case Some(sig) => val index = jmember.getConstantPool().addUtf8(sig).toShort @@ -465,11 +465,14 @@ abstract class GenJVM extends SubComponent { jmember.addAttribute(attr) } - def addInnerClasses { + def addInnerClasses(jclass: JClass) { + def addOwnInnerClasses(cls: Symbol) { + for (sym <- cls.info.decls.elements if sym.isClass) + innerClasses = innerClasses + sym; + } // add inner classes which might not have been referenced yet atPhase(currentRun.erasurePhase) { - for (sym <- clasz.symbol.info.decls.elements if sym.isClass) - innerClasses = innerClasses + sym; + addOwnInnerClasses(clasz.symbol) } if (!innerClasses.isEmpty) { @@ -479,13 +482,16 @@ abstract class GenJVM extends SubComponent { for (innerSym <- innerClasses.toList.sort(_.name.length < _.name.length)) { var outerName = javaName(innerSym.rawowner) // remove the trailing '$' - //if (outerName.endsWith("$")) - //outerName = outerName.substring(0, outerName.length - 1) + if (outerName.endsWith("$")) + outerName = outerName.substring(0, outerName.length - 1) + var flags = javaFlags(innerSym) + if (innerSym.rawowner.hasFlag(Flags.MODULE)) + flags |= JAccessFlags.ACC_STATIC innerClassesAttr.addEntry(javaName(innerSym), outerName, innerSym.rawname.toString, - javaFlags(innerSym)); + flags); } } } @@ -811,7 +817,7 @@ abstract class GenJVM extends SubComponent { start = labels(b).getAnchor() end = endPC(b) } - covered = covered remove b.== + covered = covered - b } }); diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index 4db90c9c3a..dbabae1387 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -991,8 +991,8 @@ abstract class GenMSIL extends SubComponent { }) // shorter try-catch-finally last (the ones contained in another) - affectedHandlers = affectedHandlers.sort({(h1, h2) => h1.covered.length > h2.covered.length}) - affectedHandlers = affectedHandlers.filter(h => {h.covered.length == affectedHandlers(0).covered.length}) + affectedHandlers = affectedHandlers.sort({(h1, h2) => h1.covered.size > h2.covered.size}) + affectedHandlers = affectedHandlers.filter(h => {h.covered.size == affectedHandlers(0).covered.size}) untreatedHandlers = untreatedHandlers -- affectedHandlers // more than one catch produces more than one exh, but we only need one @@ -1018,7 +1018,7 @@ abstract class GenMSIL extends SubComponent { val excBlock = currentBlock.addExceptionBlock(singleAffectedHandler) exceptionBlock = Some(excBlock) - val (tryBlocks, newBlock) = adaptBlocks(blocksToPut.intersect(singleAffectedHandler.covered), singleAffectedHandler) + val (tryBlocks, newBlock) = adaptBlocks(blocksToPut.intersect(singleAffectedHandler.covered.toList), singleAffectedHandler) newBlock match { case Some(block) => @@ -1068,7 +1068,7 @@ abstract class GenMSIL extends SubComponent { // some blocks may have been removed by linearization untreatedHandlers.foreach(h => { h.blocks = h.blocks.intersect(blocksToPut) - h.covered = h.covered.intersect(blocksToPut) + h.covered = h.covered.intersect(collection.immutable.HashSet.empty ++ blocksToPut) if (h.finalizer != null && h.finalizer != NoFinalizer) h.finalizer.blocks = h.finalizer.blocks.intersect(blocksToPut) }) diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 18fd09e0ba..11c3db13ee 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -365,10 +365,17 @@ trait Definitions { private def newCovariantPolyClass(owner: Symbol, name: Name, parent: Symbol => Type): Symbol = { val clazz = newClass(owner, name, List()) val tparam = newTypeParam(clazz, 0) setFlag COVARIANT + val p = parent(tparam) +/* p.typeSymbol.initialize + println(p.typeSymbol + " flags: " + Flags.flagsToString(p.typeSymbol.flags)) + val parents = /*if (p.typeSymbol.isTrait) + List(definitions.AnyRefClass.tpe, p) + else*/ List(p) + println("creating " + name + " with parents " + parents) */ clazz.setInfo( PolyType( List(tparam), - ClassInfoType(List(parent(tparam)), newClassScope(clazz), clazz))) + ClassInfoType(List(p), newClassScope(clazz), clazz))) } private def newAlias(owner: Symbol, name: Name, alias: Type): Symbol = { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index c52eda360a..80ee38f337 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -204,7 +204,11 @@ abstract class ClassfileParser { in.buf(start) != CONSTANT_METHODREF && in.buf(start) != CONSTANT_INTFMETHODREF) errorBadTag(start) val ownerTpe = getClassOrArrayType(in.getChar(start + 1)) + if (settings.debug.value) + log("getMemberSymbol(static: " + static + "): owner type: " + ownerTpe + " " + ownerTpe.typeSymbol.originalName) val (name, tpe) = getNameAndType(in.getChar(start + 3), ownerTpe) + if (settings.debug.value) + log("getMemberSymbol: name and tpe: " + name + ": " + tpe) if (name == nme.MODULE_INSTANCE_FIELD) { val index = in.getChar(start + 1) val name = getExternalName(in.getChar(starts(index) + 1)) @@ -377,8 +381,10 @@ abstract class ClassfileParser { val classInfo = ClassInfoType(parents, instanceDefs, clazz) val staticInfo = ClassInfoType(List(), staticDefs, statics) - if (!isScala && !isScalaRaw) + if (!isScala && !isScalaRaw) { + //println("Entering inner classes for " + clazz) enterOwnInnerClasses + } val curbp = in.bp skipMembers() // fields skipMembers() // methods @@ -386,7 +392,7 @@ abstract class ClassfileParser { clazz.setFlag(sflags) setPrivateWithin(clazz, jflags) setPrivateWithin(staticModule, jflags) - if (!hasMeta) { + if (!hasMeta || isScalaRaw) { clazz.setInfo(classInfo) } statics.setInfo(staticInfo) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 6606214970..09c2c75ef5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -51,13 +51,11 @@ abstract class ICodeReader extends ClassfileParser { if (entry ne null) { classFile = entry.classFile // if (isScalaModule) - //sym = cls.linkedClassOfModule +// sym = cls.linkedClassOfModule assert(classFile ne null, "No classfile for " + cls) // for (s <- cls.info.members) // Console.println("" + s + ": " + s.tpe) - this.instanceCode = new IClass(sym) - this.staticCode = new IClass(sym.linkedClassOfClass) parse(classFile, sym) } else log("Could not find: " + cls) @@ -75,13 +73,14 @@ abstract class ICodeReader extends ClassfileParser { } override def parseClass() { + this.instanceCode = new IClass(clazz) + this.staticCode = new IClass(staticModule) val jflags = in.nextChar val isAttribute = (jflags & JAVA_ACC_ANNOTATION) != 0 var sflags = transFlags(jflags, true) if ((sflags & DEFERRED) != 0) sflags = sflags & ~DEFERRED | ABSTRACT val c = pool.getClassSymbol(in.nextChar) -// if (c != clazz) -// throw new IOException("class file '" + in.file + "' contains " + c + "instead of " + clazz) + parseInnerClasses() in.skip(2) // super class @@ -643,7 +642,8 @@ abstract class ICodeReader extends ClassfileParser { * There are two possible classes, the static part and the instance part. */ def getCode(flags: Int): IClass = - if ((flags & JAVA_ACC_STATIC) != 0) staticCode else instanceCode + if (isScalaModule) staticCode + else if ((flags & JAVA_ACC_STATIC) != 0) staticCode else instanceCode class LinearCode { var instrs: ListBuffer[(Int, Instruction)] = new ListBuffer diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index ab020716d2..30f2c69372 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -677,12 +677,12 @@ abstract class Mixin extends InfoTransform { && !sym.isOuterAccessor) if (settings.debug.value) { - println("needsInitFlag(" + sym.fullNameString + "): " + res) - println("\tsym.isGetter: " + sym.isGetter) - println("\t!isInitializedToDefault: " + !sym.isInitializedToDefault + sym.hasFlag(DEFAULTINIT) + sym.hasFlag(ACCESSOR) + sym.isTerm) - println("\t!sym.hasFlag(PARAMACCESSOR): " + !sym.hasFlag(PARAMACCESSOR)) + log("needsInitFlag(" + sym.fullNameString + "): " + res) + log("\tsym.isGetter: " + sym.isGetter) + log("\t!isInitializedToDefault: " + !sym.isInitializedToDefault + sym.hasFlag(DEFAULTINIT) + sym.hasFlag(ACCESSOR) + sym.isTerm) + log("\t!sym.hasFlag(PARAMACCESSOR): " + !sym.hasFlag(PARAMACCESSOR)) //println("\t!sym.accessed.hasFlag(PRESUPER): " + !sym.accessed.hasFlag(PRESUPER)) - println("\t!sym.isOuterAccessor: " + !sym.isOuterAccessor) + log("\t!sym.isOuterAccessor: " + !sym.isOuterAccessor) } res |