summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2009-10-01 13:22:18 +0000
committerIulian Dragos <jaguarul@gmail.com>2009-10-01 13:22:18 +0000
commite5b199ebb9636a0033e1b7fd56a1920e5ffffc29 (patch)
tree7e798c695ea2b9d23973a01083c85caff921dd02
parent51771ed4641111662d32900a1ac84264dbdad0e7 (diff)
downloadscala-e5b199ebb9636a0033e1b7fd56a1920e5ffffc29.tar.gz
scala-e5b199ebb9636a0033e1b7fd56a1920e5ffffc29.tar.bz2
scala-e5b199ebb9636a0033e1b7fd56a1920e5ffffc29.zip
Fixed #2392
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala95
-rw-r--r--test/files/run/finally.check3
-rw-r--r--test/files/run/finally.scala22
3 files changed, 69 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 278ce6079b..33508ebf58 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -501,38 +501,19 @@ abstract class GenICode extends SubComponent {
case Try(block, catches, finalizer) =>
val kind = toTypeKind(tree.tpe)
- var tmp: Local = null
- val guardResult = kind != UNIT && mayCleanStack(finalizer)
- if (guardResult) {
- tmp = ctx.makeLocal(tree.pos, tree.tpe, "tmp")
- }
var handlers = for (CaseDef(pat, _, body) <- catches.reverse)
yield pat match {
case Typed(Ident(nme.WILDCARD), tpt) => (tpt.tpe.typeSymbol, kind, {
ctx: Context =>
ctx.bb.emit(DROP(REFERENCE(tpt.tpe.typeSymbol)));
- val ctx1 = genLoad(body, ctx, kind);
- if (guardResult) {
- ctx1.bb.emit(STORE_LOCAL(tmp))
- val ctx2 = genLoad(finalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(finalizer, ctx1, UNIT);
+ genLoad(body, ctx, kind);
})
case Ident(nme.WILDCARD) => (definitions.ThrowableClass, kind, {
ctx: Context =>
ctx.bb.emit(DROP(REFERENCE(definitions.ThrowableClass)))
- val ctx1 = genLoad(body, ctx, kind)
- if (guardResult) {
- ctx1.bb.emit(STORE_LOCAL(tmp))
- val ctx2 = genLoad(finalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(finalizer, ctx1, UNIT)
+ genLoad(body, ctx, kind)
})
case Bind(name, _) =>
@@ -541,35 +522,18 @@ abstract class GenICode extends SubComponent {
(pat.symbol.tpe.typeSymbol, kind, {
ctx: Context =>
ctx.bb.emit(STORE_LOCAL(exception), pat.pos);
- val ctx1 = genLoad(body, ctx, kind);
- if (guardResult) {
- ctx1.bb.emit(STORE_LOCAL(tmp))
- val ctx2 = genLoad(finalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(finalizer, ctx1, UNIT);
+ genLoad(body, ctx, kind);
})
}
- val duppedFinalizer = (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)
- if (settings.debug.value)
- log("Duplicated finalizer: " + duppedFinalizer)
ctx.Try(
bodyCtx => {
generatedType = kind; //toTypeKind(block.tpe);
- val ctx1 = genLoad(block, bodyCtx, generatedType);
- if (guardResult) {
- 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))
- ctx2
- } else
- genLoad(duppedFinalizer, ctx1, UNIT)
+ genLoad(block, bodyCtx, generatedType);
},
handlers,
- finalizer)
+ finalizer,
+ tree)
case Throw(expr) =>
val ctx1 = genLoad(expr, ctx, THROWABLE)
@@ -796,7 +760,7 @@ abstract class GenICode extends SubComponent {
exhCtx.bb.emit(THROW())
exhCtx.bb.enterIgnoreMode
exhCtx
- })), EmptyTree);
+ })), EmptyTree, tree);
if (settings.debug.value)
log("synchronized block end with block " + ctx1.bb +
" closed=" + ctx1.bb.closed);
@@ -1730,6 +1694,8 @@ abstract class GenICode extends SubComponent {
override def equals(other: Any) = f == other;
}
+ def duplicateFinalizer(ctx: Context, finalizer: Tree) =
+ (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)
/**
* The Context class keeps information relative to the current state
@@ -1960,10 +1926,34 @@ abstract class GenICode extends SubComponent {
*/
def Try(body: Context => Context,
handlers: List[(Symbol, TypeKind, (Context => Context))],
- finalizer: Tree) = {
+ finalizer: Tree,
+ tree: Tree) = {
+
val outerCtx = this.dup // context for generating exception handlers, covered by finalizer
val finalizerCtx = this.dup // context for generating finalizer handler
val afterCtx = outerCtx.newBlock
+ var tmp: Local = null
+ val kind = toTypeKind(tree.tpe)
+ val guardResult = kind != UNIT && mayCleanStack(finalizer)
+
+ if (guardResult) {
+ tmp = this.makeLocal(tree.pos, tree.tpe, "tmp")
+ }
+
+ def emitFinalizer(ctx: Context): Context = if (!finalizer.isEmpty) {
+ val ctx1 = finalizerCtx.dup.newBlock
+ ctx.bb.emit(JUMP(ctx1.bb))
+ ctx.bb.close
+
+ if (guardResult) {
+ ctx1.bb.emit(STORE_LOCAL(tmp))
+ val ctx2 = genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT)
+ ctx2.bb.emit(LOAD_LOCAL(tmp))
+ ctx2
+ } else
+ genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT)
+ } else ctx
+
val finalizerExh = if (finalizer != EmptyTree) Some({
val exh = outerCtx.newHandler(NoSymbol, toTypeKind(finalizer.tpe)) // finalizer covers exception handlers
@@ -1985,23 +1975,26 @@ abstract class GenICode extends SubComponent {
var ctx1 = outerCtx.enterHandler(exh)
if (settings.Xdce.value) ctx1.bb.emit(LOAD_EXCEPTION())
ctx1 = handler._3(ctx1)
- ctx1.bb.emit(JUMP(afterCtx.bb))
- ctx1.bb.close
+ // emit finalizer
+ val ctx2 = emitFinalizer(ctx1)
+ ctx2.bb.emit(JUMP(afterCtx.bb))
+ ctx2.bb.close
exh
}
val bodyCtx = this.newBlock
if (finalizer != EmptyTree)
bodyCtx.addFinalizer(finalizer)
- val finalCtx = body(bodyCtx)
+ var finalCtx = body(bodyCtx)
+ finalCtx = emitFinalizer(finalCtx)
outerCtx.bb.emit(JUMP(bodyCtx.bb))
outerCtx.bb.close
- exhs.reverse foreach finalCtx.removeHandler
- if (finalizer != EmptyTree) {
- finalCtx.removeFinalizer(finalizer)
- }
+// exhs.reverse foreach finalCtx.removeHandler
+// if (finalizer != EmptyTree) {
+// finalCtx.removeFinalizer(finalizer)
+// }
finalCtx.bb.emit(JUMP(afterCtx.bb))
finalCtx.bb.close
diff --git a/test/files/run/finally.check b/test/files/run/finally.check
new file mode 100644
index 0000000000..4e66e2b5cb
--- /dev/null
+++ b/test/files/run/finally.check
@@ -0,0 +1,3 @@
+hi
+In Finally
+java.lang.RuntimeException: ouch
diff --git a/test/files/run/finally.scala b/test/files/run/finally.scala
new file mode 100644
index 0000000000..6d8d360d30
--- /dev/null
+++ b/test/files/run/finally.scala
@@ -0,0 +1,22 @@
+
+// test that finally is not covered by any exception handlers.
+object Test extends Application {
+ def bar {
+ try {
+ println("hi")
+ }
+ catch {
+ case e => println("GOT HERE")
+ }
+ finally {
+ println("In Finally")
+ throw new RuntimeException("ouch")
+ }
+ }
+
+ try {
+ bar
+ } catch {
+ case e => println(e)
+ }
+}