summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-02-04 17:44:09 +0100
committerJason Zaugg <jzaugg@gmail.com>2014-02-05 08:44:45 +0100
commit9506d5273b4b10037c202f01e8556076998bd064 (patch)
treeeb2460ab4c122926e537d81e2fce03af37e3569e
parenteba3cc6a9e4bb091db3cc7d68dc64abb803f52c7 (diff)
downloadscala-9506d5273b4b10037c202f01e8556076998bd064.tar.gz
scala-9506d5273b4b10037c202f01e8556076998bd064.tar.bz2
scala-9506d5273b4b10037c202f01e8556076998bd064.zip
SI-8233 Fix regression in backend with boxed nulls
Regressed in SI-7015 / 1b6661b8. We do need to "unbox" the null (ie, drop a stack from and load a null) in general. The only time we can avoid this is if the tree we are adapting is a `Constant(Literal(null))`. I've added a test for both backends. Only GenICode exhibited the problem.
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala14
-rw-r--r--test/files/run/t8233-bcode.flags1
-rw-r--r--test/files/run/t8233-bcode.scala18
-rw-r--r--test/files/run/t8233.scala18
4 files changed, 49 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 1332d01dbd..9ba38b021d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1007,8 +1007,15 @@ abstract class GenICode extends SubComponent {
}
// emit conversion
- if (generatedType != expectedType)
- adapt(generatedType, expectedType, resCtx, tree.pos)
+ if (generatedType != expectedType) {
+ tree match {
+ case Literal(Constant(null)) if generatedType == NullReference =>
+ // literal null on the stack (as opposed to a boxed null, see SI-8233),
+ // we can bypass `adapt` which would otherwise emitt a redundant [DROP, CONSTANT(null)]
+ case _ =>
+ adapt(generatedType, expectedType, resCtx, tree.pos)
+ }
+ }
resCtx
}
@@ -1058,6 +1065,9 @@ abstract class GenICode extends SubComponent {
case (NothingReference, _) =>
ctx.bb.emit(THROW(ThrowableClass))
ctx.bb.enterIgnoreMode()
+ case (NullReference, REFERENCE(_)) =>
+ // SI-8223 we can't assume that the stack contains a `null`, it might contain a Null$
+ ctx.bb.emit(Seq(DROP(from), CONSTANT(Constant(null))))
case _ if from isAssignabledTo to =>
()
case (_, UNIT) =>
diff --git a/test/files/run/t8233-bcode.flags b/test/files/run/t8233-bcode.flags
new file mode 100644
index 0000000000..c30091d3de
--- /dev/null
+++ b/test/files/run/t8233-bcode.flags
@@ -0,0 +1 @@
+-Ybackend:GenBCode
diff --git a/test/files/run/t8233-bcode.scala b/test/files/run/t8233-bcode.scala
new file mode 100644
index 0000000000..fae1c2b702
--- /dev/null
+++ b/test/files/run/t8233-bcode.scala
@@ -0,0 +1,18 @@
+object Test {
+ def bar(s: String) = s;
+ val o: Option[Null] = None
+ def nullReference {
+ val a: Null = o.get
+ bar(a) // Was: VerifyError under GenICode
+ }
+
+ def literal {
+ val a: Null = null
+ bar(a)
+ }
+
+ def main(args: Array[String]) = {
+ try { nullReference } catch { case _: NoSuchElementException => }
+ literal
+ }
+}
diff --git a/test/files/run/t8233.scala b/test/files/run/t8233.scala
new file mode 100644
index 0000000000..fae1c2b702
--- /dev/null
+++ b/test/files/run/t8233.scala
@@ -0,0 +1,18 @@
+object Test {
+ def bar(s: String) = s;
+ val o: Option[Null] = None
+ def nullReference {
+ val a: Null = o.get
+ bar(a) // Was: VerifyError under GenICode
+ }
+
+ def literal {
+ val a: Null = null
+ bar(a)
+ }
+
+ def main(args: Array[String]) = {
+ try { nullReference } catch { case _: NoSuchElementException => }
+ literal
+ }
+}