summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2006-05-19 14:55:15 +0000
committerIulian Dragos <jaguarul@gmail.com>2006-05-19 14:55:15 +0000
commitef2de304b1cafdf7bc4f0230f73ed084455fa450 (patch)
treec8d6717966d3c4c955201cc9c591648776bfc7c4 /src
parentf746ce36d86a08c8456f5fae04459addcdd2c62d (diff)
downloadscala-ef2de304b1cafdf7bc4f0230f73ed084455fa450.tar.gz
scala-ef2de304b1cafdf7bc4f0230f73ed084455fa450.tar.bz2
scala-ef2de304b1cafdf7bc4f0230f73ed084455fa450.zip
Fixed two try-finally bugs.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala33
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala12
6 files changed, 70 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c6569088d0..3002f34b58 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -571,7 +571,8 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable
private def writeICode(): Unit = {
val printer = new icodePrinter.TextPrinter(null, icodes.linearizer);
icodes.classes.values.foreach((cls) => {
- var file = getFile(cls.symbol, ".icode");
+ val suffix = if (cls.symbol.hasFlag(Flags.MODULE)) "$.icode" else ".icode";
+ var file = getFile(cls.symbol, suffix);
// if (file.exists())
// file = new File(file.getParentFile(), file.getName() + "1");
try {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 8f694ea764..5209fde3cb 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -53,6 +53,11 @@ trait BasicBlocks requires ICodes {
instructionList
}
+ def fromList(is: List[Instruction]): Unit = {
+ instrs = toInstructionArray(is);
+ closed = true;
+ }
+
// public:
/** Compute an hashCode for the block */
@@ -133,7 +138,7 @@ trait BasicBlocks requires ICodes {
newInstrs(j) = x;
j = j + 1;
}
- if (i + 1 < instrs.length - 1)
+ if (i + 1 < instrs.length)
System.arraycopy(instrs, i + 1, newInstrs, j, instrs.length - i - 1)
instrs = newInstrs;
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
index c22cfa26eb..172c90cf7a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
@@ -34,6 +34,8 @@ trait ExceptionHandlers requires ICodes {
var covered: List[BasicBlock] = Nil;
+ def covers(b: BasicBlock): Boolean = covered.contains(b);
+
override def toString() = "exh_" + label + "(" + cls.simpleName + ")";
def this(other: ExceptionHandler) = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 4f79ae3f30..b130ddb9a7 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -364,8 +364,8 @@ abstract class GenICode extends SubComponent {
case ValDef(_, _, _, rhs) =>
val sym = tree.symbol;
- val local = new Local(sym, toTypeKind(sym.info), false);
- ctx.method.addLocal(local);
+ var local = new Local(sym, toTypeKind(sym.info), false);
+ local = ctx.method.addLocal(local);
if (rhs == EmptyTree) {
if (settings.debug.value)
@@ -461,7 +461,13 @@ abstract class GenICode extends SubComponent {
if (finalizer != EmptyTree)
handlers = Pair(NoSymbol, {
ctx: Context =>
+ val exception = new Local(ctx.method.symbol.newVariable(finalizer.pos, unit.fresh.newName("exc"))
+ .setInfo(definitions.ThrowableClass.tpe),
+ REFERENCE(definitions.ThrowableClass), false);
+ ctx.method.addLocal(exception);
+ ctx.bb.emit(STORE_LOCAL(exception));
val ctx1 = genLoad(finalizer, ctx, UNIT);
+ ctx1.bb.emit(LOAD_LOCAL(exception));
ctx1.bb.emit(THROW());
ctx1.bb.enterIgnoreMode;
ctx1
@@ -471,7 +477,16 @@ abstract class GenICode extends SubComponent {
bodyCtx => {
generatedType = kind; //toTypeKind(block.tpe);
val ctx1 = genLoad(block, bodyCtx, generatedType);
- genLoad(finalizer, ctx1, UNIT)
+ if (kind != UNIT && mayCleanStack(finalizer)) {
+ val tmp = new Local(ctx.method.symbol.newVariable(tree.pos, unit.fresh.newName("tmp")).setInfo(tree.tpe),
+ kind, false);
+ ctx1.method.addLocal(tmp);
+ ctx1.bb.emit(STORE_LOCAL(tmp));
+ val ctx2 = genLoad(finalizer, ctx1, UNIT)
+ ctx2.bb.emit(LOAD_LOCAL(tmp));
+ ctx2
+ } else
+ genLoad(finalizer, ctx1, UNIT)
},
handlers)
@@ -1286,6 +1301,18 @@ abstract class GenICode extends SubComponent {
abort("Malformed parameter list: " + vparamss);
}
+ /** 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
+ }
+
/**
* If the block consists of a single unconditional jump, prune
* it by replacing the instructions in the predecessor to jump
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index a49eb80eef..9863b54417 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -55,6 +55,28 @@ abstract class ICodes extends AnyRef
printer.printMethod(m);
}
+ /** Merge together blocks that have a single successor which has a
+ * single predecessor. Exception handlers are taken into account (they
+ * might force to break a block of straight line code like that).
+ *
+ * This method should be most effective after heavy inlining.
+ */
+ def normalize(m: IMethod): Unit = if (m.code ne null) {
+ Console.println("Method " + m);
+ val mergeablePairs =
+ for (val b <- m.code.blocks.toList;
+ b.successors.length == 1;
+ val succ = b.successors.head;
+ succ.predecessors.length == 1;
+ succ.predecessors.head == b
+/* !(m.exh.contains { (e: ExceptionHandler) => e.covers(b) && !e.covers(succ) }) */) {
+ Console.println("Block " + b + ".lastInstruction" + b.lastInstruction);
+ Console.println(" has successors: " + b.successors + " and succ has pred: " + succ.predecessors);
+ //yield Pair(b, succ)
+ }
+// Console.println("Mergeable: " + mergeablePairs.mkString("", "\n", ""));
+ ()
+ }
def init = { }
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 62ce35732e..20d948b6ab 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -173,12 +173,16 @@ trait Members requires ICodes {
this
}
- def addLocal(l: Local): Unit =
- if (!(locals contains l))
- locals = l :: locals;
+ def addLocal(l: Local): Local =
+ locals find (l.==) match {
+ case Some(loc) => loc
+ case None =>
+ locals = l :: locals;
+ l
+ }
def addLocals(ls: List[Local]): Unit =
- ls foreach addLocal;
+ ls foreach { l => addLocal(l); };
def addParam(p: Local): Unit =
if (!(params contains p)) {