diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-05-18 12:01:17 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-05-19 22:27:50 +0200 |
commit | ccc5eef051c8588c1fe4029e832d5b6387976aa6 (patch) | |
tree | 8bb35044f3f935e82c6db343252f970a3cf8953c /test/files/run | |
parent | 5b1d43d8ffda4b5881df7ce6634a7adebbb02f21 (diff) | |
download | scala-ccc5eef051c8588c1fe4029e832d5b6387976aa6.tar.gz scala-ccc5eef051c8588c1fe4029e832d5b6387976aa6.tar.bz2 scala-ccc5eef051c8588c1fe4029e832d5b6387976aa6.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.
To make sure we don't thwart closure elimination, I've allowed DCE
to eliminate a non-static LOAD_FIELD of a member of a closure class.
It would be more general to track nullity of the reciever (e.g, `this`
or `new Foo` cannot be null), but that would require more
infrastructure in this phase.
I've added a test for closure inlining based on a a suggestion by
@dragos. This actually passes if we remove the (LOAD_FIELD, DROP)
peephole optimization for `closelim` altogether. But I chose to
adapt that optimization (only allow it for non-static, closure
fields), rather then remove it alogether, in the interests of
treading lightly.
Diffstat (limited to 'test/files/run')
-rw-r--r-- | test/files/run/t8601-closure-elim.flags | 1 | ||||
-rw-r--r-- | test/files/run/t8601-closure-elim.scala | 26 | ||||
-rw-r--r-- | test/files/run/t8601c.flags | 1 | ||||
-rw-r--r-- | test/files/run/t8601c.scala | 12 |
4 files changed, 40 insertions, 0 deletions
diff --git a/test/files/run/t8601-closure-elim.flags b/test/files/run/t8601-closure-elim.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/run/t8601-closure-elim.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/run/t8601-closure-elim.scala b/test/files/run/t8601-closure-elim.scala new file mode 100644 index 0000000000..2c5b03af77 --- /dev/null +++ b/test/files/run/t8601-closure-elim.scala @@ -0,0 +1,26 @@ +import scala.tools.partest.BytecodeTest +import scala.tools.asm +import scala.tools.asm.util._ +import scala.collection.JavaConverters._ + +object Test extends BytecodeTest { + val nullChecks = Set(asm.Opcodes.NEW) + + def show: Unit = { + def test(methodName: String) { + val classNode = loadClassNode("Foo") + val methodNode = getMethod(classNode, "b") + val ops = methodNode.instructions.iterator.asScala.map(_.getOpcode).toList + assert(!ops.contains(asm.Opcodes.NEW), ops)// should be allocation free if the closure is eliminiated + } + test("b") + } +} + +class Foo { + @inline final def a(x: Int => Int) = x(1) + final def b { + val delta = 0 + a(x => delta + 1) + } +} 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)) + + } +} |