summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sources/scala/tools/nsc/backend/icode/BasicBlocks.scala1
-rw-r--r--sources/scala/tools/nsc/backend/icode/Checkers.scala4
-rw-r--r--sources/scala/tools/nsc/backend/icode/GenICode.scala173
-rw-r--r--sources/scala/tools/nsc/backend/icode/Linearizers.scala2
-rw-r--r--sources/scala/tools/nsc/backend/icode/Members.scala4
-rw-r--r--sources/scala/tools/nsc/backend/icode/Opcodes.scala28
-rw-r--r--sources/scala/tools/nsc/backend/icode/Printers.scala1
-rw-r--r--sources/scala/tools/nsc/backend/jvm/GenJVM.scala42
8 files changed, 77 insertions, 178 deletions
diff --git a/sources/scala/tools/nsc/backend/icode/BasicBlocks.scala b/sources/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 772bd5ef0b..43b0199702 100644
--- a/sources/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/sources/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -195,7 +195,6 @@ trait BasicBlocks: ICodes {
case SWITCH(_,labels) => labels;
case RETURN(_) => Nil;
case THROW() => Nil;
- case LEAVE_FINALIZER(_) => Nil;
case _ =>
global.abort("The last instruction is not a control flow instruction: " + lastInstruction);
}
diff --git a/sources/scala/tools/nsc/backend/icode/Checkers.scala b/sources/scala/tools/nsc/backend/icode/Checkers.scala
index 73a681ac0c..8aba76fa97 100644
--- a/sources/scala/tools/nsc/backend/icode/Checkers.scala
+++ b/sources/scala/tools/nsc/backend/icode/Checkers.scala
@@ -304,7 +304,9 @@ abstract class Checkers {
checkStack(1);
val actualType = stack.pop;
- if (!(actualType <:< local.kind) && actualType != CASE_CLASS)
+ if (!(actualType <:< local.kind) &&
+ actualType != CASE_CLASS &&
+ local.kind != SCALA_ALL_REF)
typeError(local.kind, actualType);
case STORE_FIELD(field, isStatic) =>
diff --git a/sources/scala/tools/nsc/backend/icode/GenICode.scala b/sources/scala/tools/nsc/backend/icode/GenICode.scala
index 331689c558..1dc5b47389 100644
--- a/sources/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/sources/scala/tools/nsc/backend/icode/GenICode.scala
@@ -413,72 +413,49 @@ abstract class GenICode extends SubComponent {
ctx1
case Try(block, catches, finalizer) =>
- val outerCtx = ctx.dup;
-
- var bodyCtx: Context = null;
- var afterCtx: Context = outerCtx.newBlock;
- var finalHandler: Finalizer = null;
- if (finalizer != EmptyTree)
- finalHandler = ctx.newFinalizer;
- else
- finalHandler = NoFinalizer;
-
-
- def genHandler = genExceptionHandler(ctx, outerCtx, afterCtx, finalHandler);
-
- val handlers = for (val CaseDef(pat, _, body) <- catches)
+ var handlers = for (val CaseDef(pat, _, body) <- catches)
yield pat match {
- case Typed(Ident(nme.WILDCARD), tpt) =>
- genHandler(body, tpt.tpe.symbol, expectedType);
-
- case Ident(nme.WILDCARD) =>
- genHandler(body, definitions.ThrowableClass, expectedType);
+ case Typed(Ident(nme.WILDCARD), tpt) => Pair(tpt.tpe.symbol, {
+ ctx: Context =>
+ ctx.bb.emit(DROP(REFERENCE(tpt.tpe.symbol)));
+ val ctx1 = genLoad(finalizer, ctx, UNIT);
+ genLoad(body, ctx1, toTypeKind(body.tpe))
+ })
+
+ case Ident(nme.WILDCARD) => Pair(definitions.ThrowableClass, {
+ ctx: Context =>
+ ctx.bb.emit(DROP(REFERENCE(definitions.ThrowableClass)));
+ val ctx1 = genLoad(finalizer, ctx, UNIT);
+ genLoad(body, ctx1, toTypeKind(body.tpe))
+ })
case Bind(name, _) =>
val exception = new Local(pat.symbol, toTypeKind(pat.symbol.tpe));
ctx.method.addLocal(exception);
- val exh = ctx.newHandler(pat.symbol.tpe.symbol);
-
- val exhCtx = outerCtx.enterHandler(exh);
- exhCtx.bb.emit(STORE_LOCAL(exception, false), pat.pos);
- val ctx1 = genLoad(body, exhCtx, expectedType); // toTypeKind(body.tpe));
- if (finalHandler != NoFinalizer)
- ctx1.bb.emit(CALL_FINALIZER(finalHandler));
- ctx1.bb.emit(JUMP(afterCtx.bb));
- ctx1.bb.close;
- exh
-
- case _ =>
- abort("Unknown exception case: " + pat + " at: " + unit.position(pat.pos));
+ Pair(pat.symbol.tpe.symbol, {
+ ctx: Context =>
+ ctx.bb.emit(STORE_LOCAL(exception, false), pat.pos);
+ val ctx1 = genLoad(finalizer, ctx, UNIT);
+ genLoad(body, ctx1, toTypeKind(body.tpe))
+ })
}
- if (finalizer != EmptyTree) {
- val finalizerCtx = outerCtx.enterHandler(finalHandler);
- finalizerCtx.bb.emit(ENTER_FINALIZER(finalHandler));
- val ctx1 = genLoad(finalizer, finalizerCtx, UNIT);
- ctx1.bb.emit(LEAVE_FINALIZER(finalHandler));
- ctx1.bb.close;
- }
-
- bodyCtx = ctx.newBlock;
- outerCtx.bb.emit(JUMP(bodyCtx.bb), tree.pos);
- outerCtx.bb.close;
-
- generatedType = toTypeKind(block.tpe);
- val ctxfinal = genLoad(block, bodyCtx, generatedType);
-
- handlers.reverse foreach (ex => { ex.finalizer = finalHandler; ctxfinal exitHandler ex });
- ctxfinal.exitFinalizer(finalHandler);
-// if (generatedType != SCALA_ALL)
- adapt(generatedType, expectedType, ctxfinal, tree);
-
- if (finalHandler != NoFinalizer)
- ctxfinal.bb.emit(CALL_FINALIZER(finalHandler));
- ctxfinal.bb.emit(JUMP(afterCtx.bb));
- ctxfinal.bb.close;
- generatedType = expectedType;
- afterCtx
+ if (finalizer != EmptyTree)
+ handlers = Pair(NoSymbol, {
+ ctx: Context =>
+ val ctx1 = genLoad(finalizer, ctx, UNIT);
+ ctx1.bb.emit(THROW());
+ ctx1
+ }) :: handlers;
+
+ ctx.Try(
+ bodyCtx => {
+ generatedType = toTypeKind(block.tpe);
+ val ctx1 = genLoad(block, bodyCtx, generatedType);
+ genLoad(finalizer, ctx1, UNIT)
+ },
+ handlers)
case Throw(expr) =>
val ctx1 = genLoad(expr, ctx, THROWABLE);
@@ -644,19 +621,19 @@ abstract class GenICode extends SubComponent {
if (settings.debug.value)
log("synchronized block start");
- ctx1 = ctx1.Try(NoSymbol,
+ ctx1 = ctx1.Try(
bodyCtx => {
val ctx1 = genLoad(args.head, bodyCtx, toTypeKind(tree.tpe.resultType));
ctx1.bb.emit(LOAD_LOCAL(monitor, false));
ctx1.bb.emit(MONITOR_EXIT(), tree.pos);
ctx1
- },
- exhCtx => {
+ }, List(
+ Pair(NoSymbol, exhCtx => {
exhCtx.bb.emit(LOAD_LOCAL(monitor, false));
exhCtx.bb.emit(MONITOR_EXIT(), tree.pos);
exhCtx.bb.emit(THROW());
exhCtx
- });
+ })));
if (settings.debug.value)
log("synchronized block end with block " + ctx1.bb + " closed=" + ctx1.bb.isClosed);
} else if (scalaPrimitives.isCoercion(code)) {
@@ -859,20 +836,6 @@ abstract class GenICode extends SubComponent {
}
}
- private def genExceptionHandler(ctx: Context, outerCtx: Context, afterCtx: Context, finalHandler: Finalizer)
- (body: Tree, sym: Symbol, pt: TypeKind): ExceptionHandler = {
- val exh = ctx.newHandler(sym);
-
- var ctx1 = outerCtx.enterHandler(exh);
- ctx1.bb.emit(DROP(REFERENCE(sym)));
- ctx1 = genLoad(body, ctx1, toTypeKind(body.tpe));
- if (finalHandler != NoFinalizer)
- ctx1.bb.emit(CALL_FINALIZER(finalHandler));
- ctx1.bb.emit(JUMP(afterCtx.bb));
- ctx1.bb.close;
- exh
- }
-
/** Load the qualifier of `tree' on top of the stack. */
private def genLoadQualifier(tree: Tree, ctx: Context): Context =
tree match {
@@ -1322,8 +1285,6 @@ abstract class GenICode extends SubComponent {
/** current exception handlers */
var handlers: List[ExceptionHandler] = Nil;
- var finalizers: List[Finalizer] = Nil;
-
var handlerCount = 0;
override def toString(): String = {
@@ -1334,7 +1295,6 @@ 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("\tfinalizers: ").append(finalizers).append('\n');
buf.toString()
}
@@ -1348,7 +1308,6 @@ abstract class GenICode extends SubComponent {
this.labels = other.labels;
this.defdef = other.defdef;
this.handlers = other.handlers;
- this.finalizers = other.finalizers;
this.handlerCount = other.handlerCount;
}
@@ -1386,7 +1345,6 @@ abstract class GenICode extends SubComponent {
def newBlock: Context = {
val block = method.code.newBlock;
handlers foreach (h => h addBlock block);
- finalizers foreach (.addBlock(block));
new Context(this) setBasicBlock block;
}
@@ -1398,14 +1356,9 @@ abstract class GenICode extends SubComponent {
val exh = new ExceptionHandler(method, "" + handlerCount, cls);
method.addHandler(exh);
handlers = exh :: handlers;
- exh
- }
+ if (settings.debug.value)
+ log("added handler: " + exh);
- def newFinalizer: Finalizer = {
- handlerCount = handlerCount + 1;
- val exh = new Finalizer(method, "" + handlerCount);
- method.addFinalizer(exh);
- finalizers = exh :: finalizers;
exh
}
@@ -1423,34 +1376,52 @@ abstract class GenICode extends SubComponent {
"Wrong nesting of exception handlers." + this + " for " + exh);
handlerCount = handlerCount - 1;
handlers = handlers.tail;
- }
+ if (settings.debug.value)
+ log("removed handler: " + exh);
- def exitFinalizer(f: Finalizer): Unit = if (f != NoFinalizer) {
- assert(handlerCount > 0 && finalizers.head == f,
- "Wrong nesting of exception handlers." + this + " for " + f);
- handlerCount = handlerCount - 1;
- finalizers = finalizers.tail;
}
/** Clone the current context */
def dup: Context = new Context(this);
- def Try(catched: Symbol, body: Context => Context, handler: Context => Context) = {
+ /**
+ * Generate exception handlers for the body. Body is evaluated
+ * with a context where all the handlers are active. Handlers are
+ * evaluated in the 'outer' context.
+ *
+ * It returns the resulting context, with the same active handlers as
+ * before the call. Use it like:
+ *
+ * <code> ctx.Try( ctx => {
+ * ctx.bb.emit(...) // protected block
+ * }, Pair(definitions.ThrowableClass,
+ * ctx => {
+ * ctx.bb.emit(...); // exception handler
+ * }), Pair(AnotherExceptionClass,
+ * ctx => {...
+ * } ))</code>
+ */
+ def Try(body: Context => Context,
+ handlers: List[Pair[Symbol, (Context => Context)]]) = {
val outerCtx = this.dup;
val afterCtx = outerCtx.newBlock;
- val exh = this.newHandler(catched);
-
- val ctx1 = handler(outerCtx.enterHandler(exh));
- ctx1.bb.emit(JUMP(afterCtx.bb));
- ctx1.bb.close;
+ val exhs = handlers.map { handler =>
+ val exh = this.newHandler(handler._1);
+ val ctx1 = handler._2(outerCtx.enterHandler(exh));
+ ctx1.bb.emit(JUMP(afterCtx.bb));
+ ctx1.bb.close;
+ exh
+ }
val bodyCtx = this.newBlock;
+
val finalCtx = body(bodyCtx);
outerCtx.bb.emit(JUMP(bodyCtx.bb));
outerCtx.bb.close;
- finalCtx.exitHandler(exh);
+ exhs.reverse foreach finalCtx.exitHandler;
+
finalCtx.bb.emit(JUMP(afterCtx.bb));
finalCtx.bb.close;
diff --git a/sources/scala/tools/nsc/backend/icode/Linearizers.scala b/sources/scala/tools/nsc/backend/icode/Linearizers.scala
index baffccef77..7a0b77f6fa 100644
--- a/sources/scala/tools/nsc/backend/icode/Linearizers.scala
+++ b/sources/scala/tools/nsc/backend/icode/Linearizers.scala
@@ -38,7 +38,6 @@ trait Linearizers: ICodes {
run {
worklist ++= (m.exh map (.startBlock));
- worklist ++= (m.finalizers map (.startBlock));
worklist.push(b);
}
@@ -68,7 +67,6 @@ trait Linearizers: ICodes {
add(labels);
case RETURN(_) => ();
case THROW() => ();
- case LEAVE_FINALIZER(_) => ();
}
}
diff --git a/sources/scala/tools/nsc/backend/icode/Members.scala b/sources/scala/tools/nsc/backend/icode/Members.scala
index 50dd3afb5f..1a8c15aa05 100644
--- a/sources/scala/tools/nsc/backend/icode/Members.scala
+++ b/sources/scala/tools/nsc/backend/icode/Members.scala
@@ -163,7 +163,6 @@ trait Members: ICodes {
class IMethod(val symbol: Symbol) {
var code: Code = null;
var exh: List[ExceptionHandler] = Nil;
- var finalizers: List[Finalizer] = Nil;
var sourceFile: String = _;
var returnType: TypeKind = _;
@@ -203,9 +202,6 @@ trait Members: ICodes {
def addHandler(e: ExceptionHandler): Unit =
exh = e :: exh;
- def addFinalizer(e: Finalizer): Unit =
- finalizers = e :: finalizers;
-
/** Is this method deferred ('abstract' in Java sense) */
def isDeferred =
symbol.hasFlag(Flags.DEFERRED) ||
diff --git a/sources/scala/tools/nsc/backend/icode/Opcodes.scala b/sources/scala/tools/nsc/backend/icode/Opcodes.scala
index b9f462a49d..c7f2a8d709 100644
--- a/sources/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/sources/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -25,9 +25,6 @@ import scala.tools.nsc.util.Position;
case STORE_FIELD(field, isStatic) =>
case CALL_PRIMITIVE(primitive) =>
case CALL_METHOD(method, style) =>
- case CALL_FINALIZER(finalizer) =>
- case ENTER_FINALIZER(finalizer) =>
- case LEAVE_FINALIZER(finalizer) =>
case NEW(kind) =>
case CREATE_ARRAY(elem) =>
case IS_INSTANCE(tpe) =>
@@ -237,31 +234,6 @@ import scala.tools.nsc.util.Position;
override def produced = 1;
}
- case class CALL_FINALIZER(finalizer: Finalizer) extends Instruction {
- assert(finalizer != NoFinalizer, "CALL_FINALIZER cannot call NoFinalizer");
- override def toString(): String =
- "CALL_FINALIZER " + finalizer;
-
- override def consumed = 0;
- override def produced = 0;
- }
-
- case class ENTER_FINALIZER(finalizer: Finalizer) extends Instruction {
- override def toString(): String =
- "ENTER_FINALIZER " + finalizer;
-
- override def consumed = 1;
- override def produced = 0;
- }
-
- case class LEAVE_FINALIZER(finalizer: Finalizer) extends Instruction {
- override def toString(): String =
- "LEAVE_FINALIZER " + finalizer;
-
- override def consumed = 0;
- override def produced = 0;
- }
-
/** Create a new instance of a class through the specified constructor
* Stack: ...:arg1:arg2:...:argn
* ->: ...:ref
diff --git a/sources/scala/tools/nsc/backend/icode/Printers.scala b/sources/scala/tools/nsc/backend/icode/Printers.scala
index 13afc83da8..63ad1e4ed6 100644
--- a/sources/scala/tools/nsc/backend/icode/Printers.scala
+++ b/sources/scala/tools/nsc/backend/icode/Printers.scala
@@ -91,7 +91,6 @@ abstract class Printers {
indent;println("Exception handlers: ");
m.exh foreach printExceptionHandler;
- m.finalizers foreach printExceptionHandler;
undent;println;
} else
println;
diff --git a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
index 7cd3b875bf..203f2186a5 100644
--- a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -230,8 +230,6 @@ abstract class GenJVM extends SubComponent {
var isModuleInitialized = false;
def genCode(m: IMethod): Unit = {
labels.clear;
- retAddress.clear;
- anyHandler.clear;
isModuleInitialized = false;
code = m.code;
@@ -239,7 +237,7 @@ abstract class GenJVM extends SubComponent {
makeLabels(linearization);
genBlocks(linearization);
- if (this.method.exh != Nil || this.method.finalizers != Nil)
+ if (this.method.exh != Nil)
genExceptionHandlers;
}
@@ -252,9 +250,6 @@ abstract class GenJVM extends SubComponent {
}
- /** Map from finalizer to the code area where its 'any' exception handler was generated. */
- val anyHandler: HashMap[Finalizer, Pair[Int, Int]] = new HashMap();
-
/** Generate exception handlers for the current method. */
def genExceptionHandlers: Unit = {
@@ -307,28 +302,6 @@ abstract class GenJVM extends SubComponent {
else javaName(e.cls))
})
});
- this.method.finalizers foreach ((f) => {
- val targetPC = jcode.getPC();
- val exceptionLocal = jmethod.addNewLocalVariable(JObjectType.JAVA_LANG_OBJECT, clasz.cunit.fresh.newName("exception"));
- jcode.emitSTORE(exceptionLocal);
- jcode.emitJSR(labels(f.startBlock));
- jcode.emitLOAD(exceptionLocal);
- jcode.emitATHROW();
-
- log("Finalizer: " + f + " coveres: " + f.covered);
- anyHandler.foreach((of: Finalizer, r: Pair[Int, Int]) =>
- if (f.covered.contains(of.startBlock))
- jcode.addFinallyHandler(r._1, r._2, targetPC));
-
- anyHandler += f -> Pair(targetPC, jcode.getPC());
-
- ranges(f) foreach ((p) => {
- log("Adding finalizer handler " + f + "at: " + targetPC + " for " + method +
- " from: " + p._1 + " to: " + p._2);
- jcode.addFinallyHandler(p._1, p._2, targetPC);
- });
-
- });
}
def genBlock(b: BasicBlock): Unit = {
@@ -462,16 +435,6 @@ abstract class GenJVM extends SubComponent {
}
- case CALL_FINALIZER(finalizer) =>
- jcode.emitJSR(labels(finalizer.startBlock));
-
- case ENTER_FINALIZER(finalizer) =>
- retAddress(finalizer) = jmethod.addNewLocalVariable(JType.ADDRESS, clasz.cunit.fresh.newName("ret"));
- jcode.emitSTORE(retAddress(finalizer));
-
- case LEAVE_FINALIZER(finalizer) =>
- jcode.emitRET(retAddress(finalizer));
-
case NEW(REFERENCE(cls)) =>
val className = javaName(cls);
jcode.emitNEW(className);
@@ -592,7 +555,7 @@ abstract class GenJVM extends SubComponent {
}
crtPC = jcode.getPC();
- val crtLine = Position.line(instr.pos);
+ val crtLine = instr.pos; //clasz.cunit.position(instr.pos).line;
if (crtLine != lastLineNr &&
crtPC > lastMappedPC) {
jcode.completeLineNumber(lastMappedPC, crtPC, crtLine);
@@ -765,7 +728,6 @@ abstract class GenJVM extends SubComponent {
val endPC: HashMap[BasicBlock, Int] = new HashMap();
val labels: HashMap[BasicBlock, JCode$Label] = new HashMap();
val conds: HashMap[TestOp, Int] = new HashMap();
- val retAddress: HashMap[Finalizer, JLocalVariable] = new HashMap();
conds += EQ -> JExtendedCode.COND_EQ;
conds += NE -> JExtendedCode.COND_NE;