summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--test/files/run/exceptions-2.check14
-rw-r--r--test/files/run/exceptions-2.scala39
8 files changed, 118 insertions, 14 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)) {
diff --git a/test/files/run/exceptions-2.check b/test/files/run/exceptions-2.check
index 3ec0dfcc1c..e67f147506 100644
--- a/test/files/run/exceptions-2.check
+++ b/test/files/run/exceptions-2.check
@@ -17,11 +17,17 @@ method3:
Exception occurred with stack trace:
java.lang.NullPointerException
at Test$.method3(exceptions-2.scala:108)
- at Test$$anonfun$5.apply(exceptions-2.scala:151)
- at Test$$anonfun$5.apply(exceptions-2.scala:151)
- at Test$.execute(exceptions-2.scala:128)
- at Test$.main(exceptions-2.scala:151)
+ at Test$$anonfun$5.apply(exceptions-2.scala:180)
+ at Test$$anonfun$5.apply(exceptions-2.scala:180)
+ at Test$.execute(exceptions-2.scala:157)
+ at Test$.main(exceptions-2.scala:180)
at Test.main(exceptions-2.scala)
+tryFinallyTry:
+Silently ignore exception in finally
+valInFinally:
+Abc
+tryAndValInFinally
+Abc
=================
NoExcep.method2:
Hello, world
diff --git a/test/files/run/exceptions-2.scala b/test/files/run/exceptions-2.scala
index 2583542747..e006bc053d 100644
--- a/test/files/run/exceptions-2.scala
+++ b/test/files/run/exceptions-2.scala
@@ -1,7 +1,7 @@
/*
* Try exception handling and finally blocks.
*
- * $Id: $
+ * $Id$
*/
@@ -124,6 +124,35 @@ object Test {
Console.println(x);
}
+ def tryFinallyTry: Unit = {
+ try {
+ ()
+ } finally {
+ try {
+ error("a");
+ } catch {
+ case _ => Console.println("Silently ignore exception in finally");
+ }
+ }
+ }
+
+ def valInFinally: Unit =
+ try {
+ } finally {
+ val fin = "Abc";
+ Console.println(fin);
+ };
+
+ def tryAndValInFinally: Unit =
+ try {
+ } finally {
+ val fin = "Abc";
+ try {
+ Console.println(fin);
+ } catch { case _ => () }
+ };
+
+
def execute(f: => Unit) = try {
f;
} catch {
@@ -150,6 +179,14 @@ object Test {
Console.println("method3:");
execute(method3);
+ Console.println("tryFinallyTry:");
+ execute(tryFinallyTry);
+
+ Console.println("valInFinally:");
+ execute(valInFinally);
+ Console.println("tryAndValInFinally");
+ execute(tryAndValInFinally);
+
Console.println("=================");
Console.println("NoExcep.method2:");