summaryrefslogtreecommitdiff
path: root/test/files/run/dead-code-elimination.scala
diff options
context:
space:
mode:
authorVlad Ureche <vlad.ureche@gmail.com>2012-08-14 22:53:31 +0200
committerVlad Ureche <vlad.ureche@gmail.com>2012-08-15 13:10:33 +0200
commit41bf9c3c35472fda8bb06db717850886c4270379 (patch)
tree4f0cfd078d4b79cd29a723f619451d33e62041cc /test/files/run/dead-code-elimination.scala
parentd66c7a4fea537d142e42da91bfe87f4aaecc1821 (diff)
downloadscala-41bf9c3c35472fda8bb06db717850886c4270379.tar.gz
scala-41bf9c3c35472fda8bb06db717850886c4270379.tar.bz2
scala-41bf9c3c35472fda8bb06db717850886c4270379.zip
Fixes backend crash due to incorrect consumedTypes
This started out as a compiler crash after Greg copied the comprehension methods to List and made them final. The culprit was the dead code elimination phase, which after sweeping pieces of code was unable to restore the stack to its original state, thus causing the ASM backend to crash notifying the resulting bytecode is incorrect. The dead code elimination phase uses the icode Instructions' consumedTypes to determine what needs to be dropped from the stack when an instruction is eliminated, but the consumedTypes were only defined for a handful of instructions. So dce encountered a DUP instruction for which it did not have consumedTypes defined and did not restore the stack correctly. The consumedTypes/producedTypes for icode instructions are redundantly defined in 3 separate places: - Opcodes.scala (consumedTypes/producedTypes) - ICodeCheckers.scala (for checking icode) - TypeFlowAnalysis.scala (for computing types on the stack at each program point) Since the Opcodes types are the only ones visible outside, I suggest we use them in ICodeCheckers.scala and TypeFlowAnalysis.scala too. But we should make such changes after the release, as we're chilling out by the lake with a glass of good wine: SI-6234 The relevant discussion around it can be found at: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/qcyTjk8euUI[1-25] Many thanks to Paul for his help! Review by @magarciaEPFL or @paulp.
Diffstat (limited to 'test/files/run/dead-code-elimination.scala')
-rw-r--r--test/files/run/dead-code-elimination.scala33
1 files changed, 33 insertions, 0 deletions
diff --git a/test/files/run/dead-code-elimination.scala b/test/files/run/dead-code-elimination.scala
new file mode 100644
index 0000000000..1af17c936b
--- /dev/null
+++ b/test/files/run/dead-code-elimination.scala
@@ -0,0 +1,33 @@
+
+// This testcase is a snippet that did not compile correctly under
+// pre-release 2.10.x. The relevant discussion around it can be
+// found at:
+// https://groups.google.com/forum/?fromgroups#!topic/scala-internals/qcyTjk8euUI[1-25]
+//
+// The reason it did not compile is related to the fact that ICode
+// ops did not correctly define the stack entries they consumed and
+// the dead code elimination phase was unable to correctly reconstruct
+// the stack after code elimination.
+//
+// Originally, this did not compile, but I included it in the run
+// tests because this was ASM-dependand and did not happen for GenJVM.
+//
+// Thus, we run the code and force the loading of class B -- if the
+// bytecode is incorrect, it will fail the test.
+
+final class A {
+ def f1 = true
+ def f2 = true
+ @inline def f3 = f1 || f2
+ class B {
+ def f() = 1 to 10 foreach (_ => f3)
+ }
+ def f = (new B).f()
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ // force the loading of B
+ (new A).f
+ }
+}