summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala7
2 files changed, 17 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 68c4ac03f6..4f3b0bf951 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -386,10 +386,16 @@ trait BasicBlocks {
def close() {
assert(!closed || ignore, this)
assert(instructionList.nonEmpty, "Empty block: " + this)
- closed = true
- setFlag(DIRTYSUCCS)
- instructionList = instructionList.reverse
- instrs = instructionList.toArray
+ if (ignore && closed) { // redundant `ignore &&` for clarity -- we should never be in state `!ignore && closed`
+ // not doing anything to this block is important...
+ // because the else branch reverses innocent blocks, which is wrong when they're in ignore mode (and closed)
+ // reversing the instructions when (closed && ignore) wreaks havoc for nested label jumps (see comments in genLoad)
+ } else {
+ closed = true
+ setFlag(DIRTYSUCCS)
+ instructionList = instructionList.reverse
+ instrs = instructionList.toArray
+ }
}
def open() {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 9e801e3ea8..41d9d93e7a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -868,6 +868,13 @@ abstract class GenICode extends SubComponent {
abort("Unknown label target: " + sym + " at: " + (fun.pos) + ": ctx: " + ctx)
}
})
+ // note: when one of the args to genLoadLabelArguments is a jump to a label,
+ // it will call back into genLoad and arrive at this case, which will then set ctx1.bb.ignore to true,
+ // this is okay, since we're jumping unconditionally, so the loads and jumps emitted by the outer
+ // call to genLoad (by calling genLoadLabelArguments and emitOnly) can safely be ignored,
+ // however, as emitOnly will close the block, which reverses its instructions (when it's still open),
+ // we better not reverse when the block has already been closed but is in ignore mode
+ // (if it's not in ignore mode, double-closing is an error)
val ctx1 = genLoadLabelArguments(args, label, ctx)
ctx1.bb.emitOnly(if (label.anchored) JUMP(label.block) else PJUMP(label))
ctx1.bb.enterIgnoreMode