summaryrefslogtreecommitdiff
path: root/test/files/run
diff options
context:
space:
mode:
authorJames Iry <jamesiry@gmail.com>2013-01-23 16:01:59 -0800
committerJames Iry <jamesiry@gmail.com>2013-01-28 21:47:54 -0800
commiteab288442931f01b5bad2dcfa244a6183db0f4b6 (patch)
tree0f0d655e29c134f621ff2bc97c2f873c4d215a6a /test/files/run
parentcc3b9a23ebb453b827197e5ab5cba46a9e770f0c (diff)
downloadscala-eab288442931f01b5bad2dcfa244a6183db0f4b6.tar.gz
scala-eab288442931f01b5bad2dcfa244a6183db0f4b6.tar.bz2
scala-eab288442931f01b5bad2dcfa244a6183db0f4b6.zip
SI-5313 Do not eliminate stores that potentially wipe referenes
Storing to local variables of reference or array type is indirectly observable because it potentially allows gc to collect an object. So this commit makes DeadCodeElimination mark a store necessary if it assigns to a local that potentially stored by a previous necessary store.
Diffstat (limited to 'test/files/run')
-rw-r--r--test/files/run/t5313.check8
-rw-r--r--test/files/run/t5313.scala42
2 files changed, 50 insertions, 0 deletions
diff --git a/test/files/run/t5313.check b/test/files/run/t5313.check
new file mode 100644
index 0000000000..dd8791f109
--- /dev/null
+++ b/test/files/run/t5313.check
@@ -0,0 +1,8 @@
+STORE_LOCAL(variable kept1)
+STORE_LOCAL(value result)
+STORE_LOCAL(variable kept1)
+STORE_LOCAL(variable kept2)
+STORE_LOCAL(value kept3)
+STORE_LOCAL(variable kept2)
+STORE_LOCAL(variable kept4)
+STORE_LOCAL(variable kept4)
diff --git a/test/files/run/t5313.scala b/test/files/run/t5313.scala
new file mode 100644
index 0000000000..b65311622a
--- /dev/null
+++ b/test/files/run/t5313.scala
@@ -0,0 +1,42 @@
+import scala.tools.partest.IcodeTest
+
+object Test extends IcodeTest {
+ override def printIcodeAfterPhase = "dce"
+
+ override def extraSettings: String = super.extraSettings + " -optimize"
+
+ override def code =
+ """class Foo {
+ def foo = true
+ def bar = {
+ var kept1 = new Object
+ val result = new java.lang.ref.WeakReference(kept1)
+ kept1 = null // we can't eliminate this assigment because result can observe
+ // when the object has no more references. See SI-5313
+ var erased2 = null // we can eliminate this store because it's never used
+ val erased3 = erased2 // and this
+ var erased4 = erased2 // and this
+ val erased5 = erased4 // and this
+ var kept2: Object = new Object // ultimately can't be eliminated
+ while(foo) {
+ val kept3 = kept2
+ kept2 = null // this can't, because it clobbers x, which is ultimately used
+ erased4 = null // safe to eliminate
+ println(kept3)
+ }
+ var kept4 = new Object // have to keep, it's used
+ try
+ println(kept4)
+ catch {
+ case _ : Throwable => kept4 = null // have to keep, it clobbers kept4 which is used
+ }
+ result
+ }
+ }""".stripMargin
+
+ override def show() {
+ val storeLocal = "STORE_LOCAL"
+ val lines1 = collectIcode("") filter (_ contains storeLocal) map (x => x.drop(x.indexOf(storeLocal)))
+ println(lines1 mkString "\n")
+ }
+}