diff options
author | Paul Phillips <paulp@improving.org> | 2010-11-08 18:13:08 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-11-08 18:13:08 +0000 |
commit | 942bf86c7bb28c7d9aeae82204ae060ae330d9b6 (patch) | |
tree | b88f130c5294617439949d77858b3e4538eb223f /src/compiler/scala/tools/nsc/backend/icode/ICodes.scala | |
parent | 8009f723b905509e9dfa22d8746787ebb0cd11a2 (diff) | |
download | scala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.tar.gz scala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.tar.bz2 scala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.zip |
This is work on -Ycheck:icode.
distribution can now be built with that option, with or without
optimization, and almost all tests cases can. (Those which can't are due
to different -Ycheck: issues.)
Major changes of interest are as follows:
* LOAD_EXCEPTION and THROW are parameterized on the throwable symbol.
* Does not squash all traits down to AnyRef, but instead deals with
issues as they arise. By observation the cases where one needs a "Foo
with Product" to manifest as both a "Foo" and a "Product" at different
places are quite rare, so we need not throw out the whole baby. *
Exception handlers now have positions. * The remaining checker failures
removed, such as CALL_METHOD wanting to pop a value off the stack
after calling a constructor. * Many multiply defined values such as
REFERENCE(ObjectClass) put in one place (ICodes.scala) and reused. *
-Ycheck:icode output (if also given -Ydebug) worthy of Michelangelo.
Here is a class and the -Ycheck:icode -Ydebug output for f's block.
class A {
def f(x: Int, y: String) =
try println(x + y.length)
catch { case x: NullPointerException => () }
}
** Checking Block 4 [S: 3, 2] [P: 1] <closed>
1-> REF(singleton class Predef) 3 + LOAD_MODULE object Predef
2-> INT 3 + LOAD_LOCAL(value x)
3-> REF(class String) 3 + LOAD_LOCAL(value y)
2<- REF(class String) 3 - CALL_METHOD java.lang.String.length (dynamic)
3-> INT 3 + CALL_METHOD java.lang.String.length (dynamic)
2<- INT 3 - CALL_PRIMITIVE(Arithmetic(ADD,INT))
1<- INT 3 - """
2-> INT 3 + CALL_PRIMITIVE(Arithmetic(ADD,INT))
1<- INT 3 - BOX INT
2-> REF(class Integer) 3 + BOX INT
1<- REF(class Integer) 3 - CALL_METHOD scala.Predef.println (dynamic)
0<- REF(singleton class Predef) 3 - CALL_METHOD scala.Predef.println (dynamic)
Review by dragos (I marked the specific spots I thought of interest with
"PP to ID" which makes it sound like I'm talking to my primal self. Next
week on programmer theater: "PP to SUPEREGO.")
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/icode/ICodes.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/ICodes.scala | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 65b558b230..dc31edc569 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -14,9 +14,9 @@ package icode import java.io.PrintWriter -import scala.collection.mutable.HashMap +import scala.collection.{ mutable, immutable, generic } import scala.tools.nsc.symtab._ -import analysis.{Liveness, ReachingDefinitions} +import analysis.{ Liveness, ReachingDefinitions } import scala.tools.nsc.symtab.classfile.ICodeReader /** Glue together ICode parts. @@ -36,26 +36,23 @@ abstract class ICodes extends AnyRef with Repository { val global: Global + import global.{ definitions, settings } /** The ICode representation of classes */ - var classes: HashMap[global.Symbol, IClass] = new HashMap() + val classes = new mutable.HashMap[global.Symbol, IClass] /** Debugging flag */ - var isCheckerDebug: Boolean = global.settings.checkDebug.value - def checkerDebug(msg: String) = if (isCheckerDebug) println(msg) + def shouldCheckIcode = settings.check contains global.genicode.phaseName + def checkerDebug(msg: String) = if (shouldCheckIcode && global.opt.debug) println(msg) /** The ICode linearizer. */ - val linearizer: Linearizer = - if (global.settings.Xlinearizer.value == "rpo") - new ReversePostOrderLinearizer() - else if (global.settings.Xlinearizer.value == "dfs") - new DepthFirstLinerizer() - else if (global.settings.Xlinearizer.value == "normal") - new NormalLinearizer(); - else if (global.settings.Xlinearizer.value == "dump") - new DumpLinearizer() - else - global.abort("Unknown linearizer: " + global.settings.Xlinearizer.value) + val linearizer: Linearizer = settings.Xlinearizer.value match { + case "rpo" => new ReversePostOrderLinearizer() + case "dfs" => new DepthFirstLinerizer() + case "normal" => new NormalLinearizer() + case "dump" => new DumpLinearizer() + case x => global.abort("Unknown linearizer: " + x) + } /** Have to be careful because dump calls around, possibly * re-entering methods which initiated the dump (like foreach @@ -79,7 +76,7 @@ abstract class ICodes extends AnyRef for (b <- m.code.blocks) if (!b.closed) { m.dump - global.abort("Open block: " + b.flagsString) + global.abort("Open block: " + b + " " + b.flagsString) } } @@ -91,9 +88,13 @@ abstract class ICodes extends AnyRef val global: ICodes.this.global.type = ICodes.this.global } - lazy val ObjectReference: TypeKind = REFERENCE(global.definitions.ObjectClass) - lazy val ThrowableReference: TypeKind = REFERENCE(global.definitions.ThrowableClass) - lazy val AnyRefReference: TypeKind = REFERENCE(global.definitions.AnyRefClass) + lazy val AnyRefReference: TypeKind = REFERENCE(definitions.AnyRefClass) + lazy val BoxedUnitReference: TypeKind = REFERENCE(definitions.BoxedUnitClass) + lazy val NothingReference: TypeKind = REFERENCE(definitions.NothingClass) + lazy val NullReference: TypeKind = REFERENCE(definitions.NullClass) + lazy val ObjectReference: TypeKind = REFERENCE(definitions.ObjectClass) + lazy val StringReference: TypeKind = REFERENCE(definitions.StringClass) + lazy val ThrowableReference: TypeKind = REFERENCE(definitions.ThrowableClass) object icodeReader extends ICodeReader { lazy val global: ICodes.this.global.type = ICodes.this.global @@ -102,10 +103,8 @@ abstract class ICodes extends AnyRef /** A phase which works on icode. */ abstract class ICodePhase(prev: Phase) extends global.GlobalPhase(prev) { override def erasedTypes = true - - override def apply(unit: global.CompilationUnit) { - unit.icode foreach { c => apply(c) } - } + override def apply(unit: global.CompilationUnit): Unit = + unit.icode foreach apply def apply(cls: global.icodes.IClass): Unit } |