summaryrefslogtreecommitdiff
path: root/test/pending
diff options
context:
space:
mode:
authorSimon Ochsenreither <simon@ochsenreither.de>2015-09-16 17:31:02 +0200
committerSimon Ochsenreither <simon@ochsenreither.de>2015-10-27 15:43:08 +0100
commit1a8daa2d6cbf46a7cdd9180c11c641adabcf6d92 (patch)
treeb7014fdfe397864c621322bfe00ff3307df5017e /test/pending
parent4321ea458ad1258f273ee22a4c6a7606ab054501 (diff)
downloadscala-1a8daa2d6cbf46a7cdd9180c11c641adabcf6d92.tar.gz
scala-1a8daa2d6cbf46a7cdd9180c11c641adabcf6d92.tar.bz2
scala-1a8daa2d6cbf46a7cdd9180c11c641adabcf6d92.zip
Remove GenASM, merge remaining common code snippets
With GenBCode being the default and only supported backend for Java 8, we can get rid of GenASM. This commit also fixes/migrates/moves to pending/deletes tests which depended on GenASM before.
Diffstat (limited to 'test/pending')
-rw-r--r--test/pending/jvm/constant-optimization/Foo_1.flags1
-rw-r--r--test/pending/jvm/constant-optimization/Foo_1.scala9
-rw-r--r--test/pending/jvm/constant-optimization/Test.scala27
-rw-r--r--test/pending/jvm/patmat_opt_ignore_underscore.check1
-rw-r--r--test/pending/jvm/patmat_opt_ignore_underscore.flags1
-rw-r--r--test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala29
-rw-r--r--test/pending/jvm/patmat_opt_ignore_underscore/test.scala18
-rw-r--r--test/pending/jvm/patmat_opt_no_nullcheck.check1
-rw-r--r--test/pending/jvm/patmat_opt_no_nullcheck.flags1
-rw-r--r--test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala24
-rw-r--r--test/pending/jvm/patmat_opt_no_nullcheck/test.scala14
-rw-r--r--test/pending/jvm/patmat_opt_primitive_typetest.check1
-rw-r--r--test/pending/jvm/patmat_opt_primitive_typetest.flags1
-rw-r--r--test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala24
-rw-r--r--test/pending/jvm/patmat_opt_primitive_typetest/test.scala8
-rw-r--r--test/pending/jvm/t7006.check29
-rw-r--r--test/pending/jvm/t7006/Foo_1.flags1
-rw-r--r--test/pending/jvm/t7006/Foo_1.scala10
-rw-r--r--test/pending/jvm/t7006/Test.scala21
-rw-r--r--test/pending/pos/inliner2.flags35
-rw-r--r--test/pending/pos/inliner2.scala57
-rw-r--r--test/pending/pos/sealed-final.flags41
-rw-r--r--test/pending/pos/sealed-final.scala14
-rw-r--r--test/pending/run/inline-ex-handlers.check491
-rw-r--r--test/pending/run/inline-ex-handlers.scala329
-rw-r--r--test/pending/run/t5313.check12
-rw-r--r--test/pending/run/t5313.scala54
-rw-r--r--test/pending/run/t6955.scala33
-rw-r--r--test/pending/run/t6956.scala31
-rw-r--r--test/pending/run/test-cpp.check81
-rw-r--r--test/pending/run/test-cpp.scala104
31 files changed, 1503 insertions, 0 deletions
diff --git a/test/pending/jvm/constant-optimization/Foo_1.flags b/test/pending/jvm/constant-optimization/Foo_1.flags
new file mode 100644
index 0000000000..9691c0985d
--- /dev/null
+++ b/test/pending/jvm/constant-optimization/Foo_1.flags
@@ -0,0 +1 @@
+// constant otimization not there yet, -Yopt:nullness-tracking not enough.
diff --git a/test/pending/jvm/constant-optimization/Foo_1.scala b/test/pending/jvm/constant-optimization/Foo_1.scala
new file mode 100644
index 0000000000..6f408044d7
--- /dev/null
+++ b/test/pending/jvm/constant-optimization/Foo_1.scala
@@ -0,0 +1,9 @@
+class Foo_1 {
+ def foo() {
+ // constant optimization should eliminate all branches
+ val i = 1
+ val x = if (i != 1) null else "good"
+ val y = if (x == null) "good" else x + ""
+ println(y)
+ }
+} \ No newline at end of file
diff --git a/test/pending/jvm/constant-optimization/Test.scala b/test/pending/jvm/constant-optimization/Test.scala
new file mode 100644
index 0000000000..dc0f8f6103
--- /dev/null
+++ b/test/pending/jvm/constant-optimization/Test.scala
@@ -0,0 +1,27 @@
+
+import scala.tools.partest.BytecodeTest
+import scala.tools.asm
+import asm.tree.InsnList
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ val comparisons = Set(asm.Opcodes.IF_ACMPEQ, asm.Opcodes.IF_ACMPNE, asm.Opcodes.IF_ICMPEQ, asm.Opcodes.IF_ICMPGE, asm.Opcodes.IF_ICMPGT, asm.Opcodes.IF_ICMPLE,
+ asm.Opcodes.IF_ICMPLT, asm.Opcodes.IF_ICMPNE, asm.Opcodes.IFEQ, asm.Opcodes.IFGE, asm.Opcodes.IFGT, asm.Opcodes.IFLE, asm.Opcodes.IFLT,
+ asm.Opcodes.IFNE, asm.Opcodes.IFNONNULL, asm.Opcodes.IFNULL)
+
+ def show: Unit = {
+ val classNode = loadClassNode("Foo_1")
+ val methodNode = getMethod(classNode, "foo")
+ // after optimization there should be no comparisons left
+ val expected = 0
+
+ val got = countComparisons(methodNode.instructions)
+ assert(got == expected, s"expected $expected but got $got comparisons")
+ }
+
+ def countComparisons(insnList: InsnList): Int = {
+ def isComparison(node: asm.tree.AbstractInsnNode): Boolean =
+ (comparisons contains node.getOpcode)
+ insnList.iterator.asScala count isComparison
+ }
+} \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_ignore_underscore.check b/test/pending/jvm/patmat_opt_ignore_underscore.check
new file mode 100644
index 0000000000..43f53aba12
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_ignore_underscore.check
@@ -0,0 +1 @@
+bytecode identical
diff --git a/test/pending/jvm/patmat_opt_ignore_underscore.flags b/test/pending/jvm/patmat_opt_ignore_underscore.flags
new file mode 100644
index 0000000000..453b6b7895
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_ignore_underscore.flags
@@ -0,0 +1 @@
+-Yopt:l:project \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala b/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala
new file mode 100644
index 0000000000..b0506018f6
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala
@@ -0,0 +1,29 @@
+// this class's bytecode, compiled under -optimize is analyzed by the test
+// method a's bytecode should be identical to method b's bytecode
+// this is not the best test for shielding against regressing on this particular issue,
+// but it sets the stage for checking the bytecode emitted by the pattern matcher and
+// comparing it to manually tuned code using if/then/else etc.
+class SameBytecode {
+ case class Foo(x: Any, y: String)
+
+ def a =
+ Foo(1, "a") match {
+ case Foo(_: String, y) => y
+ }
+
+ // this method's body holds the tree that should be generated by the pattern matcher for method a (-Xprint:patmat)
+ // the test checks that bytecode for a and b is identical (modulo line numbers)
+ // we can't diff trees as they are quite different (patmat uses jumps to labels that cannot be expressed in source, for example)
+ // note that the actual tree is quite bad: we do an unnecessary null check, isInstanceOf and local val (x3)
+ // some of these will be fixed soon (the initial null check is for the scrutinee, which is harder to fix in patmat)
+ def b: String = {
+ val x1 = Foo(1, "a")
+ if (x1.ne(null)) {
+ if (x1.x.isInstanceOf[String]) {
+ return x1.y
+ }
+ }
+
+ throw new MatchError(x1)
+ }
+} \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_ignore_underscore/test.scala b/test/pending/jvm/patmat_opt_ignore_underscore/test.scala
new file mode 100644
index 0000000000..d6630e80a0
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_ignore_underscore/test.scala
@@ -0,0 +1,18 @@
+/*
+ * filter: inliner warning; re-run with
+ */
+import scala.tools.partest.BytecodeTest
+
+import scala.tools.nsc.util.JavaClassPath
+import java.io.InputStream
+import scala.tools.asm
+import asm.ClassReader
+import asm.tree.{ClassNode, InsnList}
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ def show: Unit = {
+ val classNode = loadClassNode("SameBytecode")
+ sameBytecode(getMethod(classNode, "a"), getMethod(classNode, "b"))
+ }
+}
diff --git a/test/pending/jvm/patmat_opt_no_nullcheck.check b/test/pending/jvm/patmat_opt_no_nullcheck.check
new file mode 100644
index 0000000000..43f53aba12
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_no_nullcheck.check
@@ -0,0 +1 @@
+bytecode identical
diff --git a/test/pending/jvm/patmat_opt_no_nullcheck.flags b/test/pending/jvm/patmat_opt_no_nullcheck.flags
new file mode 100644
index 0000000000..453b6b7895
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_no_nullcheck.flags
@@ -0,0 +1 @@
+-Yopt:l:project \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala b/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala
new file mode 100644
index 0000000000..1e4d564cdf
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala
@@ -0,0 +1,24 @@
+// this class's bytecode, compiled under -optimize is analyzed by the test
+// method a's bytecode should be identical to method b's bytecode
+case class Foo(x: Any)
+
+class SameBytecode {
+ def a =
+ (Foo(1): Any) match {
+ case Foo(_: String) =>
+ }
+
+ // there's no null check
+ def b: Unit = {
+ val x1: Any = Foo(1)
+ if (x1.isInstanceOf[Foo]) {
+ val x3 = x1.asInstanceOf[Foo]
+ if (x3.x.isInstanceOf[String]) {
+ val x = ()
+ return
+ }
+ }
+
+ throw new MatchError(x1)
+ }
+} \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_no_nullcheck/test.scala b/test/pending/jvm/patmat_opt_no_nullcheck/test.scala
new file mode 100644
index 0000000000..5a4a398b67
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_no_nullcheck/test.scala
@@ -0,0 +1,14 @@
+/*
+ * filter: inliner warning; re-run with
+ */
+import scala.tools.partest.{ BytecodeTest, ASMConverters }
+
+object Test extends BytecodeTest {
+ def show: Unit = {
+ val classNode = loadClassNode("SameBytecode")
+ // ASM and GenBCode assign variable slots slightly differently
+ val instrsA = ASMConverters.instructionsFromMethod(getMethod(classNode, "a"))
+ val instrsB = ASMConverters.instructionsFromMethod(getMethod(classNode, "b"))
+ assert(ASMConverters.equivalentBytecode(instrsA, instrsB), diffInstructions(instrsA, instrsB)) // doesn't work
+ }
+}
diff --git a/test/pending/jvm/patmat_opt_primitive_typetest.check b/test/pending/jvm/patmat_opt_primitive_typetest.check
new file mode 100644
index 0000000000..43f53aba12
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_primitive_typetest.check
@@ -0,0 +1 @@
+bytecode identical
diff --git a/test/pending/jvm/patmat_opt_primitive_typetest.flags b/test/pending/jvm/patmat_opt_primitive_typetest.flags
new file mode 100644
index 0000000000..19c578e4ad
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_primitive_typetest.flags
@@ -0,0 +1 @@
+-Yopt:l:project
diff --git a/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala b/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala
new file mode 100644
index 0000000000..c961082fa7
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala
@@ -0,0 +1,24 @@
+// this class's bytecode, compiled under -optimize is analyzed by the test
+// method a's bytecode should be identical to method b's bytecode
+class SameBytecode {
+ case class Foo(x: Int, y: String)
+
+ def a =
+ Foo(1, "a") match {
+ case Foo(_: Int, y) => y
+ }
+
+ // this method's body holds the tree that should be generated by the pattern matcher for method a (-Xprint:patmat)
+ // the test checks that bytecode for a and b is identical (modulo line numbers)
+ // we can't diff trees as they are quite different (patmat uses jumps to labels that cannot be expressed in source, for example)
+ // note that the actual tree is quite bad: we do an unnecessary null check, and local val (x3)
+ // some of these will be fixed soon (the initial null check is for the scrutinee, which is harder to fix in patmat)
+ def b: String = {
+ val x1 = Foo(1, "a")
+ if (x1.ne(null)) {
+ return x1.y
+ }
+
+ throw new MatchError(x1)
+ }
+} \ No newline at end of file
diff --git a/test/pending/jvm/patmat_opt_primitive_typetest/test.scala b/test/pending/jvm/patmat_opt_primitive_typetest/test.scala
new file mode 100644
index 0000000000..2927e763d5
--- /dev/null
+++ b/test/pending/jvm/patmat_opt_primitive_typetest/test.scala
@@ -0,0 +1,8 @@
+import scala.tools.partest.BytecodeTest
+
+object Test extends BytecodeTest {
+ def show: Unit = {
+ val classNode = loadClassNode("SameBytecode")
+ sameBytecode(getMethod(classNode, "a"), getMethod(classNode, "b"))
+ }
+}
diff --git a/test/pending/jvm/t7006.check b/test/pending/jvm/t7006.check
new file mode 100644
index 0000000000..6294b14d62
--- /dev/null
+++ b/test/pending/jvm/t7006.check
@@ -0,0 +1,29 @@
+[running phase parser on Foo_1.scala]
+[running phase namer on Foo_1.scala]
+[running phase packageobjects on Foo_1.scala]
+[running phase typer on Foo_1.scala]
+[running phase patmat on Foo_1.scala]
+[running phase superaccessors on Foo_1.scala]
+[running phase extmethods on Foo_1.scala]
+[running phase pickler on Foo_1.scala]
+[running phase refchecks on Foo_1.scala]
+[running phase uncurry on Foo_1.scala]
+[running phase tailcalls on Foo_1.scala]
+[running phase specialize on Foo_1.scala]
+[running phase explicitouter on Foo_1.scala]
+[running phase erasure on Foo_1.scala]
+[running phase posterasure on Foo_1.scala]
+[running phase lazyvals on Foo_1.scala]
+[running phase lambdalift on Foo_1.scala]
+[running phase constructors on Foo_1.scala]
+[running phase flatten on Foo_1.scala]
+[running phase mixin on Foo_1.scala]
+[running phase cleanup on Foo_1.scala]
+[running phase delambdafy on Foo_1.scala]
+[running phase icode on Foo_1.scala]
+[running phase inliner on Foo_1.scala]
+[running phase inlinehandlers on Foo_1.scala]
+[running phase closelim on Foo_1.scala]
+[running phase constopt on Foo_1.scala]
+[running phase dce on Foo_1.scala]
+[running phase jvm on icode]
diff --git a/test/pending/jvm/t7006/Foo_1.flags b/test/pending/jvm/t7006/Foo_1.flags
new file mode 100644
index 0000000000..5d1b6b2644
--- /dev/null
+++ b/test/pending/jvm/t7006/Foo_1.flags
@@ -0,0 +1 @@
+-Yopt:l:project -Ydebug -Xfatal-warnings
diff --git a/test/pending/jvm/t7006/Foo_1.scala b/test/pending/jvm/t7006/Foo_1.scala
new file mode 100644
index 0000000000..3985557d9f
--- /dev/null
+++ b/test/pending/jvm/t7006/Foo_1.scala
@@ -0,0 +1,10 @@
+class Foo_1 {
+ def foo {
+ try {
+ val x = 3 // this will be optimized away, leaving a useless jump only block
+ } finally {
+ print("hello")
+ }
+ while(true){} // ensure infinite loop doesn't break the algorithm
+ }
+}
diff --git a/test/pending/jvm/t7006/Test.scala b/test/pending/jvm/t7006/Test.scala
new file mode 100644
index 0000000000..7b4a8c45fb
--- /dev/null
+++ b/test/pending/jvm/t7006/Test.scala
@@ -0,0 +1,21 @@
+import scala.tools.partest.BytecodeTest
+import scala.tools.asm
+import asm.tree.InsnList
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ def show: Unit = {
+ val classNode = loadClassNode("Foo_1")
+ val methodNode = getMethod(classNode, "foo")
+ val nopCount = count(methodNode.instructions, asm.Opcodes.NOP)
+ val gotoCount = count(methodNode.instructions, asm.Opcodes.GOTO)
+ assert(nopCount == 0, s"NOPs expected: 0, actual: $nopCount")
+ assert(gotoCount == 1, s"GOTOs expected: 1, actual: $gotoCount")
+ }
+
+ def count(insnList: InsnList, opcode: Int): Int = {
+ def isNop(node: asm.tree.AbstractInsnNode): Boolean =
+ (node.getOpcode == opcode)
+ insnList.iterator.asScala.count(isNop)
+ }
+}
diff --git a/test/pending/pos/inliner2.flags b/test/pending/pos/inliner2.flags
new file mode 100644
index 0000000000..4bf93a9c2a
--- /dev/null
+++ b/test/pending/pos/inliner2.flags
@@ -0,0 +1,35 @@
+-optimise -Ybackend:GenASM -Xfatal-warnings
+/*
+This is what we get with 2.11.2-M3 and -Yopt:l:project:
+
+ public final int bob1();
+ Code:
+ 0: aload_0
+ 1: aload_0
+ 2: astore 6
+ 4: aload 6
+ 6: invokedynamic #62, 0 // InvokeDynamic #0:apply$mcZ$sp:(LA;)Lscala/runtime/java8/JFunction0$mcZ$sp;
+ 11: checkcast #29 // class scala/Function0
+ 14: invokedynamic #71, 0 // InvokeDynamic #1:apply$mcI$sp:()Lscala/runtime/java8/JFunction0$mcI$sp;
+ 19: checkcast #29 // class scala/Function0
+ 22: invokedynamic #76, 0 // InvokeDynamic #2:apply$mcI$sp:()Lscala/runtime/java8/JFunction0$mcI$sp;
+ 27: checkcast #29 // class scala/Function0
+ 30: astore 4
+ 32: astore_3
+ 33: astore_2
+ 34: astore_1
+ 35: aload_2
+ 36: pop
+ 37: aload 6
+ 39: invokevirtual #53 // Method A$$$anonfun$1:()Z
+ 42: ifeq 54
+ 45: aload_3
+ 46: invokeinterface #36, 1 // InterfaceMethod scala/Function0.apply:()Ljava/lang/Object;
+ 51: goto 61
+ 54: aload 4
+ 56: invokeinterface #36, 1 // InterfaceMethod scala/Function0.apply:()Ljava/lang/Object;
+ 61: astore 5
+ 63: aload 5
+ 65: invokestatic #82 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
+ 68: ireturn
+*/ \ No newline at end of file
diff --git a/test/pending/pos/inliner2.scala b/test/pending/pos/inliner2.scala
new file mode 100644
index 0000000000..bc83e04312
--- /dev/null
+++ b/test/pending/pos/inliner2.scala
@@ -0,0 +1,57 @@
+// This isn't actually testing much, because no warning is emitted in versions
+// before the fix which comes with this because the method isn't even considered
+// for inlining due to the bug.
+class A {
+ private var debug = false
+ @inline private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T =
+ if (cond) ifPart else elsePart
+
+ final def bob1() = ifelse(debug, 1, 2)
+ final def bob2() = if (debug) 1 else 2
+}
+// Cool:
+//
+// % ls -1 /tmp/2901/
+// A$$anonfun$bob1$1.class
+// A$$anonfun$bob1$2.class
+// A$$anonfun$bob1$3.class
+// A.class
+// % ls -1 /tmp/trunk
+// A.class
+//
+// Observations:
+//
+// (1) The inlined version accesses the field: the explicit one calls the accessor.
+// (2) The inlined version fails to eliminate boxing. With reference types it emits
+// an unneeded checkcast.
+// (3) The private var debug is mangled to A$$debug, but after inlining it is never accessed
+// from outside of the class and doesn't need mangling.
+// (4) We could forego emitting bytecode for ifelse entirely if it has been
+// inlined at all sites.
+//
+// Generated bytecode for the above:
+//
+// public final int bob1();
+// Code:
+// Stack=1, Locals=1, Args_size=1
+// 0: aload_0
+// 1: getfield #11; //Field A$$debug:Z
+// 4: ifeq 14
+// 7: iconst_1
+// 8: invokestatic #41; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
+// 11: goto 18
+// 14: iconst_2
+// 15: invokestatic #41; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
+// 18: invokestatic #45; //Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
+// 21: ireturn
+//
+// public final int bob2();
+// Code:
+// Stack=1, Locals=1, Args_size=1
+// 0: aload_0
+// 1: invokevirtual #48; //Method A$$debug:()Z
+// 4: ifeq 11
+// 7: iconst_1
+// 8: goto 12
+// 11: iconst_2
+// 12: ireturn
diff --git a/test/pending/pos/sealed-final.flags b/test/pending/pos/sealed-final.flags
new file mode 100644
index 0000000000..63d024a0ba
--- /dev/null
+++ b/test/pending/pos/sealed-final.flags
@@ -0,0 +1,41 @@
+-Xfatal-warnings -Yinline-warnings -Ybackend:GenASM -optimise
+/*
+The new flag settings could be
+ -Yopt-warnings -Yopt:l:project
+
+The issue here is that things are being inlined, but a lot of
+redundant load/store instructions are left behind:
+
+2.11.7:
+
+ public int f();
+ Code:
+ 0: getstatic #19 // Field Foo$.MODULE$:LFoo$;
+ 3: invokevirtual #23 // Method Foo$.mkFoo:()LFoo;
+ 6: pop
+ 7: bipush 10
+ 9: iconst_1
+ 10: iadd
+ 11: ireturn
+
+
+2.12.0-M3:
+
+ public int f();
+ Code:
+ 0: getstatic #19 // Field Foo$.MODULE$:LFoo$;
+ 3: invokevirtual #23 // Method Foo$.mkFoo:()LFoo;
+ 6: bipush 10
+ 8: istore_2
+ 9: dup
+ 10: ifnonnull 15
+ 13: aconst_null
+ 14: athrow
+ 15: astore_1
+ 16: iload_2
+ 17: iconst_1
+ 18: iadd
+ 19: istore_3
+ 20: iload_3
+ 21: ireturn
+*/ \ No newline at end of file
diff --git a/test/pending/pos/sealed-final.scala b/test/pending/pos/sealed-final.scala
new file mode 100644
index 0000000000..bdedb5c1f6
--- /dev/null
+++ b/test/pending/pos/sealed-final.scala
@@ -0,0 +1,14 @@
+sealed abstract class Foo {
+ @inline def bar(x: Int) = x + 1
+}
+object Foo {
+ def mkFoo(): Foo = new Baz2
+}
+
+object Baz1 extends Foo
+final class Baz2 extends Foo
+
+object Test {
+ // bar should be inlined now
+ def f = Foo.mkFoo() bar 10
+}
diff --git a/test/pending/run/inline-ex-handlers.check b/test/pending/run/inline-ex-handlers.check
new file mode 100644
index 0000000000..fce32771b4
--- /dev/null
+++ b/test/pending/run/inline-ex-handlers.check
@@ -0,0 +1,491 @@
+--- a
++++ b
+@@ -171,5 +171,5 @@
+ def productElement(x$1: Int (INT)): Object {
+- locals: value x$1, value x1
++ locals: value x$1, value x1, variable boxed1
+ startBlock: 1
+- blocks: [1,2,3,4]
++ blocks: [1,3,4]
+
+@@ -186,2 +186,4 @@
+ 92 LOAD_LOCAL(value x$1)
++ 92 STORE_LOCAL(variable boxed1)
++ 92 LOAD_LOCAL(variable boxed1)
+ 92 BOX INT
+@@ -194,5 +196,2 @@
+ 92 CALL_METHOD MyException.message (dynamic)
+- 92 JUMP 2
+-
+- 2:
+ 92 RETURN(REF(class Object))
+@@ -246,3 +245,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]
++ blocks: [1,2,3,4,5,6,8,11,12,13,14,15,16,17,18]
+
+@@ -257,5 +256,2 @@
+ 92 SCOPE_ENTER value x1
+- 92 JUMP 7
+-
+- 7:
+ 92 LOAD_LOCAL(value x1)
+@@ -408,5 +404,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13]
++ blocks: [1,2,3,5,8,10,11,13,14]
+
+@@ -434,4 +430,13 @@
+ 103 CALL_METHOD MyException.<init> (static-instance)
+- 103 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 14
+
++ 14:
++ 101 LOAD_LOCAL(value ex6)
++ 101 STORE_LOCAL(value x4)
++ 101 SCOPE_ENTER value x4
++ 106 LOAD_LOCAL(value x4)
++ 106 IS_INSTANCE REF(class MyException)
++ 106 CZJUMP (BOOL)NE ? 5 : 8
++
+ 13:
+@@ -447,5 +452,2 @@
+ 101 SCOPE_ENTER value x4
+- 101 JUMP 4
+-
+- 4:
+ 106 LOAD_LOCAL(value x4)
+@@ -459,8 +461,5 @@
+ 106 SCOPE_ENTER value x5
+- 106 LOAD_LOCAL(value x5)
+- 106 CALL_METHOD MyException.message (dynamic)
+- 106 STORE_LOCAL(value message)
+- 106 SCOPE_ENTER value message
+ 106 LOAD_MODULE object Predef
+- 106 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 106 CALL_METHOD MyException.message (dynamic)
+ 106 CALL_METHOD scala.Predef.println (dynamic)
+@@ -536,3 +535,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,6,7,9,10]
++ blocks: [1,3,4,6,7,9,10,11,12,13]
+
+@@ -565,4 +564,9 @@
+ 306 CALL_METHOD MyException.<init> (static-instance)
+- 306 THROW(MyException)
++ ? JUMP 11
+
++ 11:
++ ? LOAD_LOCAL(variable monitor4)
++ 305 MONITOR_EXIT
++ ? JUMP 12
++
+ 9:
+@@ -571,3 +575,3 @@
+ 305 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? JUMP 12
+
+@@ -577,4 +581,11 @@
+ 304 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
+
++ 12:
++ ? LOAD_LOCAL(variable monitor3)
++ 304 MONITOR_EXIT
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
++
+ 3:
+@@ -591,5 +602,14 @@
+ 310 CALL_METHOD scala.Predef.println (dynamic)
+- 310 JUMP 2
++ 300 RETURN(UNIT)
+
+- 2:
++ 13:
++ 310 LOAD_MODULE object Predef
++ 310 CALL_PRIMITIVE(StartConcat)
++ 310 CONSTANT("Caught crash: ")
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 LOAD_LOCAL(value t)
++ 310 CALL_METHOD java.lang.Throwable.toString (dynamic)
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 CALL_PRIMITIVE(EndConcat)
++ 310 CALL_METHOD scala.Predef.println (dynamic)
+ 300 RETURN(UNIT)
+@@ -601,6 +621,6 @@
+ with finalizer: null
+- catch (Throwable) in Vector(7, 9, 10) starting at: 6
++ catch (Throwable) in Vector(7, 9, 10, 11) starting at: 6
+ consisting of blocks: List(6)
+ with finalizer: null
+- catch (Throwable) in Vector(4, 6, 7, 9, 10) starting at: 3
++ catch (Throwable) in Vector(4, 6, 7, 9, 10, 11, 12) starting at: 3
+ consisting of blocks: List(3)
+@@ -636,3 +656,3 @@
+ startBlock: 1
+- blocks: [1,3,4,5,6,8,9]
++ blocks: [1,3,4,5,6,8,9,10,11]
+
+@@ -660,4 +680,10 @@
+ 78 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 78 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 10
+
++ 10:
++ 81 LOAD_LOCAL(value e)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
++
+ 8:
+@@ -686,3 +712,4 @@
+ 81 LOAD_LOCAL(value e)
+- 81 THROW(Exception)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
+
+@@ -703,2 +730,15 @@
+
++ 11:
++ 83 LOAD_MODULE object Predef
++ 83 CONSTANT("finally")
++ 83 CALL_METHOD scala.Predef.println (dynamic)
++ 84 LOAD_LOCAL(variable result)
++ 84 CONSTANT(1)
++ 84 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 84 CONSTANT(2)
++ 84 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 84 STORE_LOCAL(variable result)
++ 84 LOAD_LOCAL(variable exc1)
++ 84 THROW(Throwable)
++
+ }
+@@ -708,3 +748,3 @@
+ with finalizer: null
+- catch (<none>) in Vector(4, 5, 6, 8) starting at: 3
++ catch (<none>) in Vector(4, 5, 6, 8, 10) starting at: 3
+ consisting of blocks: List(3)
+@@ -732,5 +772,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24]
++ blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24,25,26,27]
+
+@@ -758,4 +798,11 @@
+ 172 CALL_METHOD MyException.<init> (static-instance)
+- 172 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 25
+
++ 25:
++ 170 LOAD_LOCAL(value ex6)
++ 170 STORE_LOCAL(value x4)
++ 170 SCOPE_ENTER value x4
++ 170 JUMP 14
++
+ 23:
+@@ -798,8 +845,5 @@
+ 175 SCOPE_ENTER value x5
+- 175 LOAD_LOCAL(value x5)
+- 175 CALL_METHOD MyException.message (dynamic)
+- 175 STORE_LOCAL(value message)
+- 175 SCOPE_ENTER value message
+ 176 LOAD_MODULE object Predef
+- 176 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 176 CALL_METHOD MyException.message (dynamic)
+ 176 CALL_METHOD scala.Predef.println (dynamic)
+@@ -807,5 +851,7 @@
+ 177 DUP(REF(class MyException))
+- 177 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 177 CALL_METHOD MyException.message (dynamic)
+ 177 CALL_METHOD MyException.<init> (static-instance)
+- 177 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -813,3 +859,4 @@
+ 170 LOAD_LOCAL(value ex6)
+- 170 THROW(Throwable)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -823,2 +870,8 @@
+
++ 26:
++ 169 LOAD_LOCAL(value ex6)
++ 169 STORE_LOCAL(value x4)
++ 169 SCOPE_ENTER value x4
++ 169 JUMP 5
++
+ 5:
+@@ -833,8 +886,5 @@
+ 180 SCOPE_ENTER value x5
+- 180 LOAD_LOCAL(value x5)
+- 180 CALL_METHOD MyException.message (dynamic)
+- 180 STORE_LOCAL(value message)
+- 180 SCOPE_ENTER value message
+ 181 LOAD_MODULE object Predef
+- 181 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 181 CALL_METHOD MyException.message (dynamic)
+ 181 CALL_METHOD scala.Predef.println (dynamic)
+@@ -842,5 +892,7 @@
+ 182 DUP(REF(class MyException))
+- 182 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 182 CALL_METHOD MyException.message (dynamic)
+ 182 CALL_METHOD MyException.<init> (static-instance)
+- 182 THROW(MyException)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -848,3 +900,4 @@
+ 169 LOAD_LOCAL(value ex6)
+- 169 THROW(Throwable)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -865,2 +918,15 @@
+
++ 27:
++ 184 LOAD_MODULE object Predef
++ 184 CONSTANT("finally")
++ 184 CALL_METHOD scala.Predef.println (dynamic)
++ 185 LOAD_LOCAL(variable result)
++ 185 CONSTANT(1)
++ 185 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 185 CONSTANT(2)
++ 185 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 185 STORE_LOCAL(variable result)
++ 185 LOAD_LOCAL(variable exc2)
++ 185 THROW(Throwable)
++
+ }
+@@ -870,6 +936,6 @@
+ with finalizer: null
+- catch (Throwable) in Vector(13, 14, 15, 18, 20, 21, 23) starting at: 4
++ catch (Throwable) in Vector(13, 14, 15, 18, 20, 21, 23, 25) starting at: 4
+ consisting of blocks: List(9, 8, 6, 5, 4)
+ with finalizer: null
+- catch (<none>) in Vector(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23) starting at: 3
++ catch (<none>) in Vector(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23, 25, 26) starting at: 3
+ consisting of blocks: List(3)
+@@ -897,5 +963,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value e, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,6,7,8,11,13,14,16]
++ blocks: [1,2,3,6,7,8,11,13,14,16,17]
+
+@@ -923,4 +989,11 @@
+ 124 CALL_METHOD MyException.<init> (static-instance)
+- 124 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 122 LOAD_LOCAL(value ex6)
++ 122 STORE_LOCAL(value x4)
++ 122 SCOPE_ENTER value x4
++ 122 JUMP 7
++
+ 16:
+@@ -948,8 +1021,5 @@
+ 127 SCOPE_ENTER value x5
+- 127 LOAD_LOCAL(value x5)
+- 127 CALL_METHOD MyException.message (dynamic)
+- 127 STORE_LOCAL(value message)
+- 127 SCOPE_ENTER value message
+ 127 LOAD_MODULE object Predef
+- 127 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 127 CALL_METHOD MyException.message (dynamic)
+ 127 CALL_METHOD scala.Predef.println (dynamic)
+@@ -982,3 +1052,3 @@
+ with finalizer: null
+- catch (IllegalArgumentException) in Vector(6, 7, 8, 11, 13, 14, 16) starting at: 3
++ catch (IllegalArgumentException) in Vector(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3
+ consisting of blocks: List(3)
+@@ -1006,5 +1076,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
++ locals: value args, variable result, value ex6, value x4, value x5, value x, value e
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,12,13,14,16]
++ blocks: [1,2,3,5,8,12,13,14,16,17]
+
+@@ -1032,4 +1102,13 @@
+ 148 CALL_METHOD MyException.<init> (static-instance)
+- 148 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 145 LOAD_LOCAL(value ex6)
++ 145 STORE_LOCAL(value x4)
++ 145 SCOPE_ENTER value x4
++ 154 LOAD_LOCAL(value x4)
++ 154 IS_INSTANCE REF(class MyException)
++ 154 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1053,5 +1132,2 @@
+ 145 SCOPE_ENTER value x4
+- 145 JUMP 4
+-
+- 4:
+ 154 LOAD_LOCAL(value x4)
+@@ -1065,8 +1141,5 @@
+ 154 SCOPE_ENTER value x5
+- 154 LOAD_LOCAL(value x5)
+- 154 CALL_METHOD MyException.message (dynamic)
+- 154 STORE_LOCAL(value message)
+- 154 SCOPE_ENTER value message
+ 154 LOAD_MODULE object Predef
+- 154 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 154 CALL_METHOD MyException.message (dynamic)
+ 154 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1287,3 +1360,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1311,4 +1384,11 @@
+ 38 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 38 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 42 LOAD_MODULE object Predef
++ 42 CONSTANT("IllegalArgumentException")
++ 42 CALL_METHOD scala.Predef.println (dynamic)
++ 42 JUMP 2
++
+ 7:
+@@ -1358,5 +1438,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13,14,16]
++ blocks: [1,2,3,5,8,10,11,13,14,16,17]
+
+@@ -1384,3 +1464,4 @@
+ 203 CALL_METHOD MyException.<init> (static-instance)
+- 203 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
+@@ -1404,4 +1485,13 @@
+ 209 CALL_METHOD MyException.<init> (static-instance)
+- 209 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 200 LOAD_LOCAL(value ex6)
++ 200 STORE_LOCAL(value x4)
++ 200 SCOPE_ENTER value x4
++ 212 LOAD_LOCAL(value x4)
++ 212 IS_INSTANCE REF(class MyException)
++ 212 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1417,5 +1507,2 @@
+ 200 SCOPE_ENTER value x4
+- 200 JUMP 4
+-
+- 4:
+ 212 LOAD_LOCAL(value x4)
+@@ -1429,8 +1516,5 @@
+ 212 SCOPE_ENTER value x5
+- 212 LOAD_LOCAL(value x5)
+- 212 CALL_METHOD MyException.message (dynamic)
+- 212 STORE_LOCAL(value message)
+- 212 SCOPE_ENTER value message
+ 213 LOAD_MODULE object Predef
+- 213 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 213 CALL_METHOD MyException.message (dynamic)
+ 213 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1478,3 +1562,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1502,4 +1586,11 @@
+ 58 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 58 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 62 LOAD_MODULE object Predef
++ 62 CONSTANT("RuntimeException")
++ 62 CALL_METHOD scala.Predef.println (dynamic)
++ 62 JUMP 2
++
+ 7:
+@@ -1551,3 +1642,3 @@
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1571,4 +1662,9 @@
+ 229 CALL_METHOD MyException.<init> (static-instance)
+- 229 THROW(MyException)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor1)
++ 228 MONITOR_EXIT
++ 228 THROW(Throwable)
++
+ 3:
+@@ -1577,3 +1673,3 @@
+ 228 MONITOR_EXIT
+- ? THROW(Throwable)
++ 228 THROW(Throwable)
+
+@@ -1605,5 +1701,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, variable monitor2, variable monitorResult1
++ locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1630,4 +1726,12 @@
+ 245 CALL_METHOD MyException.<init> (static-instance)
+- 245 THROW(MyException)
++ ? STORE_LOCAL(value exception$1)
++ ? DROP ConcatClass
++ ? LOAD_LOCAL(value exception$1)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor2)
++ 244 MONITOR_EXIT
++ 244 THROW(Throwable)
++
+ 3:
+@@ -1636,3 +1740,3 @@
+ 244 MONITOR_EXIT
+- ? THROW(Throwable)
++ 244 THROW(Throwable)
diff --git a/test/pending/run/inline-ex-handlers.scala b/test/pending/run/inline-ex-handlers.scala
new file mode 100644
index 0000000000..964594d258
--- /dev/null
+++ b/test/pending/run/inline-ex-handlers.scala
@@ -0,0 +1,329 @@
+import scala.tools.partest.IcodeComparison
+
+object Test extends IcodeComparison {
+ override def printIcodeAfterPhase = "inlinehandlers"
+}
+
+import scala.util.Random._
+
+/** There should be no inlining taking place in this class */
+object TestInlineHandlersNoInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersNoInline")
+ var result = -1
+
+ try {
+ if (nextInt % 2 == 0)
+ throw new IllegalArgumentException("something")
+ result = 1
+ } catch {
+ case e: StackOverflowError =>
+ println("Stack overflow")
+ }
+
+ result
+ }
+}
+
+/** Just a simple inlining should take place in this class */
+object TestInlineHandlersSimpleInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSimpleInline")
+ var result = -1
+
+ try {
+ if (nextInt % 2 == 0)
+ throw new IllegalArgumentException("something")
+ result = 1
+ } catch {
+ case e: IllegalArgumentException =>
+ println("IllegalArgumentException")
+ }
+
+ result
+ }
+}
+
+/** Inlining should take place because the handler is taking a superclass of the exception thrown */
+object TestInlineHandlersSubclassInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSubclassInline")
+ var result = -1
+
+ try {
+ if (nextInt % 2 == 0)
+ throw new IllegalArgumentException("something")
+ result = 1
+ } catch {
+ case e: RuntimeException =>
+ println("RuntimeException")
+ }
+
+ result
+ }
+}
+
+/** For this class, the finally handler should be inlined */
+object TestInlineHandlersFinallyInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersFinallyInline")
+ var result = -1
+
+ try {
+ if (nextInt % 2 == 0)
+ throw new IllegalArgumentException("something")
+ result = 1
+ } catch {
+ case e: Exception => throw e
+ } finally {
+ println("finally")
+ result = (result - 1) / 2
+ }
+
+ result
+ }
+}
+
+
+case class MyException(message: String) extends RuntimeException(message)
+
+/** For this class, we test inlining for a case class error */
+object TestInlineHandlersCaseClassExceptionInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersCaseClassExceptionInline")
+ var result = -1
+
+ try {
+ if (nextInt % 2 == 0)
+ throw new MyException("something")
+ result = 1
+ } catch {
+ case MyException(message) => println(message)
+ }
+
+ result
+ }
+}
+
+
+/** For this class, inline should take place in the inner handler */
+object TestInlineHandlersNestedHandlerInnerInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersNestedHandlersInnerInline")
+ var result = -1
+
+ try {
+ try {
+ if (nextInt % 2 == 0)
+ throw new MyException("something")
+ result = 1
+ } catch {
+ case MyException(message) => println(message)
+ }
+ } catch {
+ case e: IllegalArgumentException => println("IllegalArgumentException")
+ }
+
+ result
+ }
+}
+
+
+/** For this class, inline should take place in the outer handler */
+object TestInlineHandlersNestedHandlerOuterInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersNestedHandlersOuterInline")
+ var result = -1
+
+ try {
+ try {
+ if (nextInt % 2 == 0)
+ throw new MyException("something")
+ result = 1
+ } catch {
+ case e: IllegalArgumentException => println("IllegalArgumentException")
+ }
+ } catch {
+ case MyException(message) => println(message)
+ }
+
+ result
+ }
+}
+
+
+/** For this class, inline should take place in the all handlers (inner, outer and finally) */
+object TestInlineHandlersNestedHandlerAllInline {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersNestedHandlersOuterInline")
+ var result = -1
+
+ try {
+ try {
+ if (nextInt % 2 == 0)
+ throw new MyException("something")
+ result = 1
+ } catch {
+ case MyException(message) =>
+ println(message)
+ throw MyException(message)
+ }
+ } catch {
+ case MyException(message) =>
+ println(message)
+ throw MyException(message)
+ } finally {
+ println("finally")
+ result = (result - 1) / 2
+ }
+
+ result
+ }
+}
+
+
+/** This class is meant to test whether the inline handler is copied only once for multiple inlines */
+object TestInlineHandlersSingleCopy {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSingleCopy")
+ var result = -1
+
+ try {
+
+ if (nextInt % 2 == 0)
+ throw new MyException("something")
+
+ println("A side effect in the middle")
+ result = 3 // another one
+
+ if (nextInt % 3 == 2)
+ throw new MyException("something else")
+ result = 1
+ } catch {
+ case MyException(message) =>
+ println(message)
+ }
+
+ result
+ }
+}
+
+/** This should test the special exception handler for synchronized blocks */
+object TestInlineHandlersSynchronized {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSynchronized")
+ var result = "hello"
+
+ // any exception thrown here will be caught by a default handler that does MONTIOR_EXIT on result :)
+ result.synchronized {
+ throw MyException(result)
+ }
+
+ result.length
+ }
+}
+
+/** This should test the special exception handler for synchronized blocks with stack */
+object TestInlineHandlersSynchronizedWithStack {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSynchronizedWithStack")
+ var result = "hello"
+
+ // any exception thrown here will be caught by a default handler that does MONTIOR_EXIT on result :)
+ result = "abc" + result.synchronized {
+ throw MyException(result)
+ }
+
+ result.length
+ }
+}
+
+/** This test should trigger a bug in the dead code elimination phase - it actually crashes ICodeCheckers
+object TestInlineHandlersSynchronizedWithStackDoubleThrow {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersSynchronizedWithStackDoubleThrow")
+ var result = "a"
+
+ // any exception thrown here will be caught by a default handler that does MONTIOR_EXIT on result :)
+ result += result.synchronized { throw MyException(result) }
+ result += result.synchronized { throw MyException(result) }
+
+ result.length
+ }
+}
+*/
+
+/** This test should check the preciseness of the inliner: it should not do any inlining here
+* as it is not able to discern between the different exceptions
+*/
+object TestInlineHandlersPreciseness {
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersCorrectHandler")
+
+ try {
+ val exception: Throwable =
+ if (scala.util.Random.nextInt % 2 == 0)
+ new IllegalArgumentException("even")
+ else
+ new StackOverflowError("odd")
+ throw exception
+ } catch {
+ case e: IllegalArgumentException =>
+ println("Correct, IllegalArgumentException")
+ case e: StackOverflowError =>
+ println("Correct, StackOverflowException")
+ case t: Throwable =>
+ println("WROOOONG, not Throwable!")
+ }
+ }
+}
+
+/** This check should verify that the double no-local exception handler is duplicated correctly */
+object TestInlineHandlersDoubleNoLocal {
+
+ val a1: String = "a"
+ val a2: String = "b"
+
+ def main(args: Array[String]): Unit = {
+ println("TestInlineHandlersDoubleNoLocal")
+
+ try {
+ a1.synchronized {
+ a2. synchronized {
+ throw new MyException("crash")
+ }
+ }
+ } catch {
+ case t: Throwable => println("Caught crash: " + t.toString)
+ }
+
+ /* try {
+ val exception: Throwable =
+ if (scala.util.Random.nextInt % 2 == 0)
+ new IllegalArgumentException("even")
+ else
+ new StackOverflowError("odd")
+ throw exception
+ } catch {
+ case e: IllegalArgumentException =>
+ println("Correct, IllegalArgumentException")
+ case e: StackOverflowError =>
+ println("Correct, StackOverflowException")
+ case t: Throwable =>
+ println("WROOOONG, not Throwable!")
+ }*/
+ }
+}
diff --git a/test/pending/run/t5313.check b/test/pending/run/t5313.check
new file mode 100644
index 0000000000..7a48b2b711
--- /dev/null
+++ b/test/pending/run/t5313.check
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 0000000000..4a5b076e6e
--- /dev/null
+++ b/test/pending/run/t5313.scala
@@ -0,0 +1,54 @@
+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")
+ }
+}
diff --git a/test/pending/run/t6955.scala b/test/pending/run/t6955.scala
new file mode 100644
index 0000000000..787617eff1
--- /dev/null
+++ b/test/pending/run/t6955.scala
@@ -0,0 +1,33 @@
+import scala.tools.partest.IcodeComparison
+
+// this class should compile to code that uses switches (twice)
+class Switches {
+ type Tag = Byte
+
+ def switchBad(i: Tag): Int = i match { // notice type of i is Tag = Byte
+ case 1 => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+
+ // this worked before, should keep working
+ def switchOkay(i: Byte): Int = i match {
+ case 1 => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+}
+
+object Test extends IcodeComparison {
+ // ensure we get two switches out of this -- ignore the rest of the output for robustness
+ // exclude the constant we emit for the "SWITCH ..." string below (we get the icode for all the code you see in this file)
+ override def show() = {
+ val expected = 2
+ val actual = (collectIcode() filter {
+ x => x.indexOf("SWITCH ...") >= 0 && x.indexOf("CONSTANT(") == -1
+ }).size
+ assert(actual == expected, s"switches expected: $expected, actual: $actual")
+ }
+}
diff --git a/test/pending/run/t6956.scala b/test/pending/run/t6956.scala
new file mode 100644
index 0000000000..57d721807d
--- /dev/null
+++ b/test/pending/run/t6956.scala
@@ -0,0 +1,31 @@
+import scala.tools.partest.IcodeComparison
+
+class Switches {
+ private[this] final val ONE = 1
+
+ def switchBad(i: Byte): Int = i match {
+ case ONE => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+
+ def switchOkay(i: Byte): Int = i match {
+ case 1 => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+}
+
+object Test extends IcodeComparison {
+ // ensure we get two switches out of this -- ignore the rest of the output for robustness
+ // exclude the constant we emit for the "SWITCH ..." string below (we get the icode for all the code you see in this file)
+ override def show() = {
+ val expected = 2
+ val actual = (collectIcode() filter {
+ x => x.indexOf("SWITCH ...") >= 0 && x.indexOf("CONSTANT(") == -1
+ }).size
+ assert(actual == expected, s"switches expected: $expected, actual: $actual")
+ }
+}
diff --git a/test/pending/run/test-cpp.check b/test/pending/run/test-cpp.check
new file mode 100644
index 0000000000..ff4c9bf2bf
--- /dev/null
+++ b/test/pending/run/test-cpp.check
@@ -0,0 +1,81 @@
+--- a
++++ b
+@@ -54,3 +54,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -59,10 +59,6 @@
+ 1:
+- 52 CONSTANT(2)
+- 52 STORE_LOCAL(value x)
+ 52 SCOPE_ENTER value x
+- 53 LOAD_LOCAL(value x)
+- 53 STORE_LOCAL(value y)
+ 53 SCOPE_ENTER value y
+ 54 LOAD_MODULE object Predef
+- 54 LOAD_LOCAL(value y)
++ 54 CONSTANT(2)
+ 54 BOX INT
+@@ -109,3 +105,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args, value x
+ startBlock: 1
+@@ -118,7 +114,5 @@
+ 81 SCOPE_ENTER value x
+- 82 LOAD_LOCAL(value x)
+- 82 STORE_LOCAL(value y)
+ 82 SCOPE_ENTER value y
+ 83 LOAD_MODULE object Predef
+- 83 LOAD_LOCAL(value y)
++ 83 LOAD_LOCAL(value x)
+ 83 BOX INT
+@@ -152,3 +146,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -157,10 +151,6 @@
+ 1:
+- 66 THIS(TestAliasChainDerefThis)
+- 66 STORE_LOCAL(value x)
+ 66 SCOPE_ENTER value x
+- 67 LOAD_LOCAL(value x)
+- 67 STORE_LOCAL(value y)
+ 67 SCOPE_ENTER value y
+ 68 LOAD_MODULE object Predef
+- 68 LOAD_LOCAL(value y)
++ 68 THIS(Object)
+ 68 CALL_METHOD scala.Predef.println (dynamic)
+@@ -193,3 +183,3 @@
+ def test(x: Int (INT)): Unit {
+- locals: value x, value y
++ locals: value x
+ startBlock: 1
+@@ -198,7 +188,5 @@
+ 1:
+- 29 LOAD_LOCAL(value x)
+- 29 STORE_LOCAL(value y)
+ 29 SCOPE_ENTER value y
+ 30 LOAD_MODULE object Predef
+- 30 LOAD_LOCAL(value y)
++ 30 LOAD_LOCAL(value x)
+ 30 BOX INT
+@@ -240,7 +228,5 @@
+ 96 SCOPE_ENTER variable x
+- 97 LOAD_LOCAL(variable x)
+- 97 STORE_LOCAL(variable y)
+ 97 SCOPE_ENTER variable y
+ 98 LOAD_MODULE object Predef
+- 98 LOAD_LOCAL(variable y)
++ 98 LOAD_LOCAL(variable x)
+ 98 BOX INT
+@@ -250,6 +236,4 @@
+ 100 STORE_LOCAL(variable y)
+- 101 LOAD_LOCAL(variable y)
+- 101 STORE_LOCAL(variable x)
+ 102 LOAD_MODULE object Predef
+- 102 LOAD_LOCAL(variable x)
++ 102 LOAD_LOCAL(variable y)
+ 102 BOX INT
diff --git a/test/pending/run/test-cpp.scala b/test/pending/run/test-cpp.scala
new file mode 100644
index 0000000000..4fca67d51e
--- /dev/null
+++ b/test/pending/run/test-cpp.scala
@@ -0,0 +1,104 @@
+/**
+ * The only change is in the decision to replace a LOAD_LOCAL(l)
+ * in the copy-propagation performed before ClosureElimination.
+ *
+ * In the general case, the local variable 'l' is connected through
+ * an alias chain with other local variables and at the end of the
+ * alias chain there may be a Value, call it 'v'.
+ *
+ * If 'v' is cheaper to access (it is a Deref(This) or Const(_)), then
+ * replace the instruction to load it from the cheaper place.
+ * Otherwise, we use the local variable at the end of the alias chain
+ * instead of 'l'.
+ */
+
+import scala.tools.partest.IcodeComparison
+
+object Test extends IcodeComparison {
+ override def printIcodeAfterPhase = "dce"
+}
+
+import scala.util.Random._
+
+/**
+ * The example in the bug report (Issue-5321): an alias chain which store
+ * an Unknown. Should remove local variable 'y'.
+ */
+object TestBugReport {
+ def test(x: Int) = {
+ val y = x
+ println(y)
+ }
+}
+
+/**
+ * The code taken from scala.tools.nsc.settings.Settings:
+ * After inlining of the setter is performed, there is an opportunity for
+ * copy-propagation to eliminate some local variables.
+ */
+object TestSetterInline {
+ private var _postSetHook: this.type => Unit = (x: this.type) => ()
+ def withPostSetHook(f: this.type => Unit): this.type = { _postSetHook = f ; this }
+}
+
+
+/**
+ * The access of the local variable 'y' should be replaced by the
+ * constant.
+ */
+object TestAliasChainConstant {
+
+ def main(args: Array[String]): Unit = {
+ val x = 2
+ val y = x
+ println(y)
+ }
+}
+
+/**
+ * At the end of the alias chain we have a reference to 'this'.
+ * The local variables should be all discarded and replace by a
+ * direct reference to this
+ */
+class TestAliasChainDerefThis {
+
+ def main(args: Array[String]): Unit = {
+ val x = this
+ val y = x
+ println(y)
+ }
+}
+
+/**
+ * At the end of the alias chain, there is the value of a field.
+ * The use of variable 'y' should be replaced by 'x', not by an access
+ * to the field 'f' since it is more costly.
+ */
+object TestAliasChainDerefField {
+ def f = nextInt
+
+ def main(args: Array[String]): Unit = {
+ val x = f
+ val y = x
+ println(y)
+ }
+}
+
+
+/**
+ * The first time 'println' is called, 'x' is replaced by 'y'
+ * and the second time, 'y' is replaced by 'x'. But none of them
+ * can be removed.
+ */
+object TestDifferentBindings {
+
+ def main(args: Array[String]): Unit = {
+ var x = nextInt
+ var y = x
+ println(y)
+
+ y = nextInt
+ x = y
+ println(x)
+ }
+}