summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2008-02-26 08:12:56 +0000
committerIulian Dragos <jaguarul@gmail.com>2008-02-26 08:12:56 +0000
commitbcbeab74566f835219dabf0bbb172fd028a8a032 (patch)
treeb83d917d906ec690efbb01f2fdf80e32312c3de4
parent0c6ab69119308a4248e416ce325d1a9e1c649516 (diff)
downloadscala-bcbeab74566f835219dabf0bbb172fd028a8a032.tar.gz
scala-bcbeab74566f835219dabf0bbb172fd028a8a032.tar.bz2
scala-bcbeab74566f835219dabf0bbb172fd028a8a032.zip
Fixed #466.
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala54
-rw-r--r--test/files/run/exceptions-2.check4
-rw-r--r--test/files/run/exceptions-2.scala18
3 files changed, 46 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 4b510100e6..0797a8c723 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -9,6 +9,7 @@ package scala.tools.nsc.backend.icode
import scala.collection.mutable.{Map, HashMap, ListBuffer, Buffer, HashSet}
import scala.tools.nsc.symtab._
+import scala.tools.nsc.util.Position
/** This class ...
@@ -464,6 +465,9 @@ abstract class GenICode extends SubComponent {
val returnedKind = toTypeKind(expr.tpe)
var ctx1 = genLoad(expr, ctx, returnedKind)
val oldcleanups = ctx1.cleanups
+ lazy val tmp = ctx1.makeLocal(tree.pos, expr.tpe, "tmp")
+ var saved = false
+
for (op <- ctx1.cleanups) op match {
case MonitorRelease(m) =>
if (settings.debug.value) log("removing " + m + " from cleanups: " + ctx1.cleanups)
@@ -472,6 +476,10 @@ abstract class GenICode extends SubComponent {
ctx1.exitSynchronized(m)
case Finalizer(f) =>
if (settings.debug.value) log("removing " + f + " from cleanups: " + ctx1.cleanups)
+ if (returnedKind != UNIT && mayCleanStack(f) && !saved) {
+ ctx1.bb.emit(STORE_LOCAL(tmp))
+ saved = true
+ }
// we have to run this without the same finalizer in
// the list, otherwise infinite recursion happens for
// finalizers that contain 'return'
@@ -479,6 +487,7 @@ abstract class GenICode extends SubComponent {
}
ctx1.cleanups = oldcleanups
+ if (saved) ctx1.bb.emit(LOAD_LOCAL(tmp))
ctx1.bb.emit(RETURN(returnedKind), tree.pos)
ctx1.bb.enterIgnoreMode
generatedType = expectedType
@@ -489,9 +498,7 @@ abstract class GenICode extends SubComponent {
var tmp: Local = null
val guardResult = kind != UNIT && mayCleanStack(finalizer)
if (guardResult) {
- tmp = ctx.method.addLocal(
- new Local(ctx.method.symbol.newVariable(tree.pos, unit.fresh.newName("tmp")).setInfo(tree.tpe).setFlag(Flags.SYNTHETIC),
- kind, false))
+ tmp = ctx.makeLocal(tree.pos, tree.tpe, "tmp")
}
var handlers = for (CaseDef(pat, _, body) <- catches.reverse)
@@ -547,9 +554,7 @@ abstract class GenICode extends SubComponent {
generatedType = kind; //toTypeKind(block.tpe);
val ctx1 = genLoad(block, bodyCtx, generatedType);
if (guardResult) {
- val tmp = ctx1.method.addLocal(
- new Local(ctx.method.symbol.newVariable(tree.pos, unit.fresh.newName("tmp")).setInfo(tree.tpe).setFlag(Flags.SYNTHETIC),
- kind, false))
+ val tmp = ctx1.makeLocal(tree.pos, tree.tpe, "tmp")
ctx1.bb.emit(STORE_LOCAL(tmp))
val ctx2 = genLoad(duppedFinalizer, ctx1, UNIT)
ctx2.bb.emit(LOAD_LOCAL(tmp))
@@ -687,13 +692,7 @@ abstract class GenICode extends SubComponent {
// we store this boxed value to a local, even if not really needed.
// boxing optimization might use it, and dead code elimination will
// take care of unnecessary stores
- var loc1 = new Local(ctx.method.symbol.newVariable(
- tree.pos,
- unit.fresh.newName("boxed"))
- .setInfo(expr.tpe)
- .setFlag(Flags.SYNTHETIC),
- nativeKind, false)
- loc1 = ctx.method.addLocal(loc1)
+ var loc1 = ctx.makeLocal(tree.pos, expr.tpe, "boxed")
ctx1.bb.emit(STORE_LOCAL(loc1))
ctx1.bb.emit(LOAD_LOCAL(loc1))
}
@@ -767,14 +766,7 @@ abstract class GenICode extends SubComponent {
generatedType = BOOL
ctx1 = afterCtx
} else if (code == scalaPrimitives.SYNCHRONIZED) {
- var monitor = new Local(ctx.method.symbol.newVariable(
- tree.pos,
- unit.fresh.newName("monitor"))
- .setInfo(definitions.ObjectClass.tpe)
- .setFlag(Flags.SYNTHETIC),
- ANY_REF_CLASS, false)
- monitor = ctx.method.addLocal(monitor)
-
+ val monitor = ctx.makeLocal(tree.pos, definitions.ObjectClass.tpe, "monitor")
ctx1 = genLoadQualifier(fun, ctx1)
ctx1.bb.emit(DUP(ANY_REF_CLASS))
ctx1.bb.emit(STORE_LOCAL(monitor))
@@ -1426,10 +1418,7 @@ abstract class GenICode extends SubComponent {
def getTempLocal: Local = ctx.method.lookupLocal(eqEqTempName) match {
case Some(local) => local
case None =>
- val eqEqTempVar =
- ctx.method.symbol.newVariable(l.pos, eqEqTempName).setFlag(Flags.SYNTHETIC)
- eqEqTempVar.setInfo(definitions.AnyRefClass.typeConstructor)
- val local = ctx.method.addLocal(new Local(eqEqTempVar, REFERENCE(definitions.AnyRefClass), false))
+ val local = ctx.makeLocal(l.pos, definitions.AnyRefClass.typeConstructor, eqEqTempName.toString)
assert(l.pos.source.get == unit.source)
assert(r.pos.source.get == unit.source)
local.start = (l.pos).line.get
@@ -1944,6 +1933,15 @@ abstract class GenICode extends SubComponent {
/** Clone the current context */
def dup: Context = new Context(this)
+ /** Make a fresh local variable. It ensures the 'name' is unique. */
+ def makeLocal(pos: Position, tpe: Type, name: String): Local = {
+ val sym = method.symbol.newVariable(pos, unit.fresh.newName(name))
+ .setInfo(tpe)
+ .setFlag(Flags.SYNTHETIC)
+ this.method.addLocal(new Local(sym, toTypeKind(tpe), false))
+ }
+
+
/**
* Generate exception handlers for the body. Body is evaluated
* with a context where all the handlers are active. Handlers are
@@ -1972,11 +1970,7 @@ abstract class GenICode extends SubComponent {
val exh = outerCtx.newHandler(NoSymbol, toTypeKind(finalizer.tpe)) // finalizer covers exception handlers
this.addActiveHandler(exh) // .. and body aswell
val ctx = finalizerCtx.enterHandler(exh)
- val exception = ctx.method.addLocal(new Local(ctx.method.symbol
- .newVariable(finalizer.pos, unit.fresh.newName("exc"))
- .setFlag(Flags.SYNTHETIC)
- .setInfo(definitions.ThrowableClass.tpe),
- REFERENCE(definitions.ThrowableClass), false));
+ val exception = ctx.makeLocal(finalizer.pos, definitions.ThrowableClass.tpe, "exc")
if (settings.Xdce.value) ctx.bb.emit(LOAD_EXCEPTION())
ctx.bb.emit(STORE_LOCAL(exception));
val ctx1 = genLoad(finalizer, ctx, UNIT);
diff --git a/test/files/run/exceptions-2.check b/test/files/run/exceptions-2.check
index 6f6af38e29..86fc91b2a2 100644
--- a/test/files/run/exceptions-2.check
+++ b/test/files/run/exceptions-2.check
@@ -50,3 +50,7 @@ finally inside finally
Outer finally
Throw in catch and finally:
ABC
+Return with finally clause that cleans the stack
+Normal execution...
+inner finally
+Outer finally
diff --git a/test/files/run/exceptions-2.scala b/test/files/run/exceptions-2.scala
index 1c6245b891..91d294c8d7 100644
--- a/test/files/run/exceptions-2.scala
+++ b/test/files/run/exceptions-2.scala
@@ -255,6 +255,21 @@ object Test {
}
+ def returnWithFinallyClean: Int = try {
+ try {
+ Console.println("Normal execution...");
+ return 10
+ Console.println("non reachable code");
+ 11
+ } finally {
+ Console.println("inner finally");
+ }
+ } finally {
+ Console.println("Outer finally");
+ try { 1 } catch { case e: java.io.IOException => () }
+ }
+
+
def main(args: Array[String]): Unit = {
Console.println("nested1: ");
execute(nested1);
@@ -310,5 +325,8 @@ object Test {
Console.println("Throw in catch and finally:");
execute(tryThrowFinally);
+
+ Console.println("Return with finally clause that cleans the stack")
+ returnWithFinallyClean
}
}