diff options
author | Paul Phillips <paulp@improving.org> | 2011-07-27 00:52:47 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-07-27 00:52:47 +0000 |
commit | 401baad565218da34558318ebd1f65edb31b39c8 (patch) | |
tree | 6177a99518fe598e51dd3d02aa9666c4fd27bacb | |
parent | 68031b3af11a2f79b186607f44d5c327051d19bd (diff) | |
download | scala-401baad565218da34558318ebd1f65edb31b39c8.tar.gz scala-401baad565218da34558318ebd1f65edb31b39c8.tar.bz2 scala-401baad565218da34558318ebd1f65edb31b39c8.zip |
Fix/workaround for inliner bug uncovered by fin...
Fix/workaround for inliner bug uncovered by finalizing Option methods.
Something in the backend is leaving open but empty blocks in the
worklist. Rather than freaking out at the merest mention of an empty
block, I quietly remove the empty ones. A proper fix will involve not
leaving empty blocks lying around but we're on a schedule here people.
Review by dragos.
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/ICodes.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala | 7 | ||||
-rw-r--r-- | test/files/pos/bug4840.flags | 1 | ||||
-rw-r--r-- | test/files/pos/bug4840.scala | 13 | ||||
-rw-r--r-- | test/files/run/run-bug4840.check | 2 | ||||
-rw-r--r-- | test/files/run/run-bug4840.flags | 1 | ||||
-rw-r--r-- | test/files/run/run-bug4840.scala | 30 |
7 files changed, 68 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 9553d5cf9b..06c3ee2a9e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -35,7 +35,7 @@ abstract class ICodes extends AnyRef with Repository { val global: Global - import global.{ definitions, settings, perRunCaches } + import global.{ log, definitions, settings, perRunCaches } /** The ICode representation of classes */ val classes = perRunCaches.newMap[global.Symbol, IClass]() @@ -72,11 +72,22 @@ abstract class ICodes extends AnyRef } def checkValid(m: IMethod) { - for (b <- m.code.blocks) - if (!b.closed) { + // always dicey to iterate over mutable structures + val bs = m.code.blocks.toList + + for (b <- bs ; if !b.closed) { + // Something is leaving open/empty blocks around (see SI-4840) so + // let's not kill the deal unless it's nonempty. + if (b.isEmpty) { + log("!!! Found open but empty block while inlining " + m + ": removing from block list.") + m.code removeBlock b + } + else { + Console.println("Fatal bug in inliner: found open block when inlining " + m) m.dump - global.abort("Open block: " + b + " " + b.flagsString) + global.abort("Open block was: " + b + " " + b.flagsString) } + } } object liveness extends Liveness { diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index 9f22a6de90..8130c99978 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -14,6 +14,8 @@ import mutable.ListBuffer trait Linearizers { self: ICodes => + + import global.debuglog import opcodes._ abstract class Linearizer { @@ -178,11 +180,14 @@ trait Linearizers { * Prepend b to the list, if not already scheduled. * @return Returns true if the block was added. */ - def add(b: BasicBlock) = + def add(b: BasicBlock) = { + debuglog("Linearizer adding block " + b.label) + if (!added(b.label)) { added += b.label blocks = b :: blocks; } + } } /** A 'dump' of the blocks in this method, which does not diff --git a/test/files/pos/bug4840.flags b/test/files/pos/bug4840.flags new file mode 100644 index 0000000000..eb4d19bcb9 --- /dev/null +++ b/test/files/pos/bug4840.flags @@ -0,0 +1 @@ +-optimise
\ No newline at end of file diff --git a/test/files/pos/bug4840.scala b/test/files/pos/bug4840.scala new file mode 100644 index 0000000000..bf44f71d7a --- /dev/null +++ b/test/files/pos/bug4840.scala @@ -0,0 +1,13 @@ +class Crashy { + def g(): Option[Any] = None + + def crashy() = { + for (_ <- g()) { + (null: Any) match { + case Some(_) => 5 + case None => sys.error("") + } + } + } +} + diff --git a/test/files/run/run-bug4840.check b/test/files/run/run-bug4840.check new file mode 100644 index 0000000000..cdfc1f911f --- /dev/null +++ b/test/files/run/run-bug4840.check @@ -0,0 +1,2 @@ +Some(5) +Some(Some(Some(5))) diff --git a/test/files/run/run-bug4840.flags b/test/files/run/run-bug4840.flags new file mode 100644 index 0000000000..eb4d19bcb9 --- /dev/null +++ b/test/files/run/run-bug4840.flags @@ -0,0 +1 @@ +-optimise
\ No newline at end of file diff --git a/test/files/run/run-bug4840.scala b/test/files/run/run-bug4840.scala new file mode 100644 index 0000000000..dda280fd17 --- /dev/null +++ b/test/files/run/run-bug4840.scala @@ -0,0 +1,30 @@ +object Test { + def g(x: Boolean): Option[String] = if (x) Some("booya") else None + + def f1() = { + for (x <- g(true)) yield { + g(false) match { + case Some(_) => sys.error("") + case None => 5 + } + } + } + + def f2() = { + for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield { + for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield { + g(true) map { _ => + (null: Any) match { + case Some(x: Int) => x + case _ => 5 + } + } + } + } + } + + def main(args: Array[String]): Unit = { + println(f1()) + println(f2()) + } +} |