diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2006-03-20 11:49:03 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2006-03-20 11:49:03 +0000 |
commit | 4ddf81c21818dadb435a4a43b91ae69688d8bc1d (patch) | |
tree | 1f99239923c7141e7fe37af70d041b441fb00a7c /src | |
parent | 7e4339ca7063beb63a83d8327c303ac094c69cb3 (diff) | |
download | scala-4ddf81c21818dadb435a4a43b91ae69688d8bc1d.tar.gz scala-4ddf81c21818dadb435a4a43b91ae69688d8bc1d.tar.bz2 scala-4ddf81c21818dadb435a4a43b91ae69688d8bc1d.zip |
Fixed returns from synchronized blocks.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 497ed3d5d7..30c6283a45 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -416,6 +416,10 @@ abstract class GenICode extends SubComponent { case Return(expr) => val returnedKind = toTypeKind(expr.tpe); val ctx1 = genLoad(expr, ctx, returnedKind); + for (val m <- ctx1.monitors) { + ctx1.bb.emit(LOAD_LOCAL(m, false)); + ctx1.bb.emit(MONITOR_EXIT()); + } ctx1.bb.emit(RETURN(returnedKind), tree.pos); ctx1.bb.enterIgnoreMode; generatedType = expectedType; @@ -456,6 +460,7 @@ abstract class GenICode extends SubComponent { ctx: Context => val ctx1 = genLoad(finalizer, ctx, UNIT); ctx1.bb.emit(THROW()); + ctx1.bb.enterIgnoreMode; ctx1 }) :: handlers; @@ -635,6 +640,7 @@ abstract class GenICode extends SubComponent { ctx1.bb.emit(DUP(ANY_REF_CLASS)); ctx1.bb.emit(STORE_LOCAL(monitor, false)); ctx1.bb.emit(MONITOR_ENTER(), tree.pos); + ctx1.enterSynchronized(monitor); if (settings.debug.value) log("synchronized block start"); @@ -654,6 +660,7 @@ abstract class GenICode extends SubComponent { }))); if (settings.debug.value) log("synchronized block end with block " + ctx1.bb + " closed=" + ctx1.bb.isClosed); + ctx1.exitSynchronized(monitor); } else if (scalaPrimitives.isCoercion(code)) { ctx1 = genLoad(receiver, ctx1, toTypeKind(receiver.tpe)); genCoercion(tree, ctx1, code); @@ -1410,6 +1417,9 @@ abstract class GenICode extends SubComponent { /** current exception handlers */ var handlers: List[ExceptionHandler] = Nil; + /** The current monitors, if inside synchronized blocks. */ + var monitors: List[Local] = Nil; + var handlerCount = 0; override def toString(): String = { @@ -1420,6 +1430,7 @@ abstract class GenICode extends SubComponent { buf.append("\tbb: ").append(bb).append('\n'); buf.append("\tlabels: ").append(labels).append('\n'); buf.append("\texception handlers: ").append(handlers).append('\n'); + buf.append("\tmonitors: ").append(monitors).append('\n'); buf.toString() } @@ -1434,6 +1445,7 @@ abstract class GenICode extends SubComponent { this.defdef = other.defdef; this.handlers = other.handlers; this.handlerCount = other.handlerCount; + this.monitors = other.monitors; } def setPackage(p: Name): this.type = { @@ -1456,6 +1468,17 @@ abstract class GenICode extends SubComponent { this } + def enterSynchronized(monitor: Local): this.type = { + monitors = monitor :: monitors; + this + } + + def exitSynchronized(monitor: Local): this.type = { + assert(monitors.head == monitor, + "Bad nesting of monitors: " + monitors + " trying to exit from: " + monitor); + this + } + /** Prepare a new context upon entry into a method */ def enterMethod(m: IMethod, d: DefDef): Context = { val ctx1 = new Context(this) setMethod(m); @@ -1660,6 +1683,7 @@ abstract class GenICode extends SubComponent { case class PCJUMP(success: Label, failure: Label, cond: TestOp, kind: TypeKind) extends PseudoJUMP(success) { + override def toString(): String ="PCJUMP (" + kind + ") " + success.symbol.simpleName + " : " + failure.symbol.simpleName; if (!failure.anchored) failure.addCallingInstruction(this); @@ -1667,6 +1691,7 @@ abstract class GenICode extends SubComponent { case class PCZJUMP(success: Label, failure: Label, cond: TestOp, kind: TypeKind) extends PseudoJUMP(success) { + override def toString(): String ="PCZJUMP (" + kind + ") " + success.symbol.simpleName + " : " + failure.symbol.simpleName; if (!failure.anchored) failure.addCallingInstruction(this); |