summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-05-18 12:01:17 +0200
committerJason Zaugg <jzaugg@gmail.com>2014-05-18 12:04:27 +0200
commit0b432f9cd22b6e9770852e5b331a15f0534a312c (patch)
tree481b2a30ead8f171268d69f68b2506453eae9df8
parentee611cd76c29fedd416162e482c7ab3f15b831ca (diff)
downloadscala-0b432f9cd22b6e9770852e5b331a15f0534a312c.tar.gz
scala-0b432f9cd22b6e9770852e5b331a15f0534a312c.tar.bz2
scala-0b432f9cd22b6e9770852e5b331a15f0534a312c.zip
SI-8601 Avoid over-eager optimization of LOAD_FIELD
It can NPE or trigger static class initilization, we can't elimiate it without changing semantics.
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--test/files/run/t8601c.flags1
-rw-r--r--test/files/run/t8601c.scala12
4 files changed, 18 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index c49f23852f..0b943360de 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -56,11 +56,10 @@ abstract class ClosureElimination extends SubComponent {
case (BOX(t1), UNBOX(t2)) if (t1 == t2) =>
Some(Nil)
- case (LOAD_FIELD(sym, isStatic), DROP(_)) if !sym.hasAnnotation(definitions.VolatileAttr) =>
- if (isStatic)
- Some(Nil)
- else
- Some(DROP(REFERENCE(definitions.ObjectClass)) :: Nil)
+ // Can't eliminate (LOAD_FIELD, DROP) without eliding side effects:
+ // - static class initialization
+ // - NPE if the receiver is null
+ // We could replace the LOAD/DROP with a null check to preserve semantics.
case _ => None
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 3c983e6fdf..64aed19bf0 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -167,7 +167,7 @@ abstract class DeadCodeElimination extends SubComponent {
set += idx
localStores(key) = set
- case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) |
+ case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) | LOAD_FIELD(_, _) | // Why LOAD_FIELD? It can NPE!
THROW(_) | LOAD_ARRAY_ITEM(_) | STORE_ARRAY_ITEM(_) | SCOPE_ENTER(_) | SCOPE_EXIT(_) | STORE_THIS(_) |
LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() | CHECK_CAST(_) =>
moveToWorkList()
diff --git a/test/files/run/t8601c.flags b/test/files/run/t8601c.flags
new file mode 100644
index 0000000000..1182725e86
--- /dev/null
+++ b/test/files/run/t8601c.flags
@@ -0,0 +1 @@
+-optimize \ No newline at end of file
diff --git a/test/files/run/t8601c.scala b/test/files/run/t8601c.scala
new file mode 100644
index 0000000000..c487d6825e
--- /dev/null
+++ b/test/files/run/t8601c.scala
@@ -0,0 +1,12 @@
+object Test {
+ def loadField(x: scala.runtime.IntRef): Unit = x.elem
+ def storeField(x: scala.runtime.IntRef): Unit = x.elem = 42
+
+ def check(x: => Any) = try { x; sys.error("failed to throw NPE!") } catch { case _: NullPointerException => }
+
+ def main(args: Array[String]) {
+ check(loadField(null)) // bug: did not NPE under -Ydead-code
+ check(storeField(null))
+
+ }
+}