summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala94
-rw-r--r--test/files/run/finally.check3
-rw-r--r--test/files/run/finally.scala22
3 files changed, 69 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b9d74ab686..e68663b942 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -511,40 +511,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")
- }
- def duplicateFinalizer =
- (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)
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(duplicateFinalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(duplicateFinalizer, ctx1, UNIT);
+ genLoad(body, ctx, kind);
})
case Ident(nme.WILDCARD) => (ThrowableClass, kind, {
ctx: Context =>
ctx.bb.emit(DROP(REFERENCE(ThrowableClass)))
- val ctx1 = genLoad(body, ctx, kind)
- if (guardResult) {
- ctx1.bb.emit(STORE_LOCAL(tmp))
- val ctx2 = genLoad(duplicateFinalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(duplicateFinalizer, ctx1, UNIT)
+ genLoad(body, ctx, kind)
})
case Bind(name, _) =>
@@ -553,32 +532,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(duplicateFinalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(duplicateFinalizer, ctx1, UNIT);
+ genLoad(body, ctx, kind);
})
}
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(duplicateFinalizer, ctx1, UNIT)
- ctx2.bb.emit(LOAD_LOCAL(tmp))
- ctx2
- } else
- genLoad(duplicateFinalizer, ctx1, UNIT)
+ genLoad(block, bodyCtx, generatedType);
},
handlers,
- finalizer)
+ finalizer,
+ tree)
case Throw(expr) =>
val ctx1 = genLoad(expr, ctx, THROWABLE)
@@ -804,7 +769,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);
@@ -1734,6 +1699,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
@@ -1964,10 +1931,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
@@ -1989,23 +1980,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)
+ }
+}