diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2016-01-25 10:51:08 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-01-25 11:25:20 +0100 |
commit | 7b953e5a6c0239c7368b1b65364ab9cb96e012b3 (patch) | |
tree | b708b90fd6e8db5b6a293a44c8033222ee5f47a8 /test | |
parent | e49fda4fab463da13e084d1deeb6f1a58e0041d1 (diff) | |
download | scala-7b953e5a6c0239c7368b1b65364ab9cb96e012b3.tar.gz scala-7b953e5a6c0239c7368b1b65364ab9cb96e012b3.tar.bz2 scala-7b953e5a6c0239c7368b1b65364ab9cb96e012b3.zip |
Rewrite test for SI-5313
Diffstat (limited to 'test')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala | 93 | ||||
-rw-r--r-- | test/pending/run/t5313.check | 12 | ||||
-rw-r--r-- | test/pending/run/t5313.scala | 54 |
3 files changed, 92 insertions, 67 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 46e1cebfc4..49b9924e97 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -15,9 +15,10 @@ import CodeGenTools._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass +import scala.collection.convert.decorateAsScala._ object MethodLevelOptsTest extends ClearAfterClass.Clearable { - var methodOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:method") + var methodOptCompiler = newCompiler(extraArgs = "-Yopt:l:method") def clear(): Unit = { methodOptCompiler = null } } @@ -559,4 +560,94 @@ class MethodLevelOptsTest extends ClearAfterClass { getSingleMethod(c, "t").instructions.dropNonOp, List(VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN))) } + + @Test + def t5313(): Unit = { + val code = + """class C { + | def randomBoolean = scala.util.Random.nextInt % 2 == 0 + | + | // 3 stores to kept1 (slot 1), 1 store to result (slot 2) + | def t1 = { + | var kept1 = new Object + | val result = new java.lang.ref.WeakReference(kept1) + | kept1 = null // we can't eliminate this assignment because result can observe + | // when the object has no more references. See SI-5313 + | kept1 = new Object // could eliminate this one with a more elaborate analysis (we know it contains null) + | // however, such is not implemented: if a var is live, then stores are kept. + | result + | } + | + | // only two variables are live: kept2 and kept3. they end up on slots 1 and 2. + | // kept2 has 2 stores, kept3 has 1 store. + | def t2 = { + | 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(randomBoolean) { + | val kept3 = kept2 + | kept2 = null // this can't, because it clobbers kept2, which is used + | erased4 = null // safe to eliminate + | println(kept3) + | } + | 0 + | } + | + | def t3 = { + | 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 + | } + | 0 + | } + | + | def t4 = { + | var kept5 = new Object + | print(kept5) + | kept5 = null // can't eliminate it's a clobber and it's used + | print(kept5) + | kept5 = null // eliminated by nullness analysis (store null to a local that is known to be null) + | 0 + | } + | + | def t5 = { + | while(randomBoolean) { + | var kept6: AnyRef = null // not used, but have to keep because it clobbers the next used store + | // on the back edge of the loop + | kept6 = new Object // used + | println(kept6) + | } + | 0 + | } + |} + """.stripMargin + + val List(c) = compileClasses(methodOptCompiler)(code) + def locals(m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) + def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) + + assertEquals(locals("t1"), List(("this",0), ("kept1",1), ("result",2))) + assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t1"))) + + assertEquals(locals("t2"), List(("this",0), ("kept2",1), ("kept3",2))) + assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t2"))) + + assertEquals(locals("t3"), List(("this",0), ("kept4",1))) + assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t3"))) + + assertEquals(locals("t4"), List(("this",0), ("kept5",1))) + assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t4"))) + + assertEquals(locals("t5"), List(("this",0), ("kept6",1))) + assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t5"))) + } } diff --git a/test/pending/run/t5313.check b/test/pending/run/t5313.check deleted file mode 100644 index 7a48b2b711..0000000000 --- a/test/pending/run/t5313.check +++ /dev/null @@ -1,12 +0,0 @@ -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) -STORE_LOCAL(variable kept5) -STORE_LOCAL(variable kept5) -STORE_LOCAL(variable kept6) -STORE_LOCAL(variable kept6) diff --git a/test/pending/run/t5313.scala b/test/pending/run/t5313.scala deleted file mode 100644 index 4a5b076e6e..0000000000 --- a/test/pending/run/t5313.scala +++ /dev/null @@ -1,54 +0,0 @@ -import scala.tools.partest.IcodeComparison - -object Test extends IcodeComparison { - override def printIcodeAfterPhase = "dce" - - override def extraSettings: String = super.extraSettings + " -Yopt:l:classpath" - - override def code = - """class Foo { - def randomBoolean = scala.util.Random.nextInt % 2 == 0 - def bar = { - var kept1 = new Object - val result = new java.lang.ref.WeakReference(kept1) - kept1 = null // we can't eliminate this assignment because result can observe - // when the object has no more references. See SI-5313 - kept1 = new Object // but we can eliminate this one because kept1 has already been clobbered - 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(randomBoolean) { - val kept3 = kept2 - kept2 = null // this can't, because it clobbers kept2, which is 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 - } - var kept5 = new Object - print(kept5) - kept5 = null // can't eliminate it's a clobber and it's used - print(kept5) - kept5 = null // can eliminate because we don't care about clobbers of nulls - while(randomBoolean) { - var kept6: AnyRef = null // not used, but have to keep because it clobbers the next used store - // on the back edge of the loop - kept6 = new Object // used - println(kept6) - } - 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") - } -} |