summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2016-02-16 12:13:54 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2016-02-16 12:13:54 +0100
commit97d8e5a2fd24f83e1adb17a11c15de2d8d9390bf (patch)
treeeda82ceb06acfb59e7b15192eff0e7d9588bae28 /test
parentc524f18ee4959f6fe8297971fc882e63468c4317 (diff)
downloadscala-97d8e5a2fd24f83e1adb17a11c15de2d8d9390bf.tar.gz
scala-97d8e5a2fd24f83e1adb17a11c15de2d8d9390bf.tar.bz2
scala-97d8e5a2fd24f83e1adb17a11c15de2d8d9390bf.zip
Tests for optimizing val patterns
Fixes https://github.com/scala/scala-dev/issues/28
Diffstat (limited to 'test')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala27
-rw-r--r--test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala59
2 files changed, 72 insertions, 14 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index 0d353e930e..fe43ed2f6a 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -164,8 +164,18 @@ object CodeGenTools {
convertMethod(m)
}
+ def assertSameCode(method: Method, expected: List[Instruction]): Unit = assertSameCode(method.instructions.dropNonOp, expected)
def assertSameCode(actual: List[Instruction], expected: List[Instruction]): Unit = {
- assertTrue(s"\nExpected: $expected\nActual : $actual", actual === expected)
+ assert(actual === expected, s"\nExpected: $expected\nActual : $actual")
+ }
+
+ def assertSameSummary(method: Method, expected: List[Any]): Unit = assertSameSummary(method.instructions, expected)
+ def assertSameSummary(actual: List[Instruction], expected: List[Any]): Unit = {
+ def expectedString = expected.map({
+ case s: String => s""""$s""""
+ case i: Int => opcodeToString(i, i)
+ }).mkString("List(", ", ", ")")
+ assert(actual.summary == expected, s"\nFound : ${actual.summaryText}\nExpected: $expectedString")
}
def assertNoInvoke(m: Method): Unit = assertNoInvoke(m.instructions)
@@ -181,6 +191,21 @@ object CodeGenTools {
}, l.stringLines)
}
+ def assertDoesNotInvoke(m: Method, method: String): Unit = assertDoesNotInvoke(m.instructions, method)
+ def assertDoesNotInvoke(l: List[Instruction], method: String): Unit = {
+ assert(!l.exists {
+ case i: Invoke => i.name == method
+ case _ => false
+ }, l.stringLines)
+ }
+
+ def assertInvokedMethods(m: Method, expected: List[String]): Unit = assertInvokedMethods(m.instructions, expected)
+ def assertInvokedMethods(l: List[Instruction], expected: List[String]): Unit = {
+ def quote(l: List[String]) = l.map(s => s""""$s"""").mkString("List(", ", ", ")")
+ val actual = l collect { case i: Invoke => i.owner + "." + i.name }
+ assert(actual == expected, s"\nFound : ${quote(actual)}\nExpected: ${quote(expected)}")
+ }
+
def getSingleMethod(classNode: ClassNode, name: String): Method =
convertMethod(classNode.methods.asScala.toList.find(_.name == name).get)
diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
index 3fc3144eb2..ac558e2e21 100644
--- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
+++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
@@ -18,7 +18,7 @@ import scala.tools.testing.ClearAfterClass
object PatmatBytecodeTest extends ClearAfterClass.Clearable {
var compiler = newCompiler()
- var optCompiler = newCompiler(extraArgs = "-Yopt:l:method")
+ var optCompiler = newCompiler(extraArgs = "-Yopt:l:project")
def clear(): Unit = { compiler = null; optCompiler = null }
}
@@ -96,10 +96,9 @@ class PatmatBytecodeTest extends ClearAfterClass {
""".stripMargin
val c = compileClasses(optCompiler)(code).head
- assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary,
- List(
- NEW, DUP, ICONST_1, LDC, "<init>",
- "y", ARETURN))
+ assertSameSummary(getSingleMethod(c, "a"), List(
+ NEW, DUP, ICONST_1, LDC, "<init>",
+ "y", ARETURN))
}
@Test
@@ -127,12 +126,12 @@ class PatmatBytecodeTest extends ClearAfterClass {
|}
""".stripMargin
val c = compileClasses(optCompiler)(code).head
- assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary,
- List(NEW, DUP, ICONST_1, "boxToInteger", LDC, "<init>", ASTORE /*1*/,
- ALOAD /*1*/, "y", ASTORE /*2*/,
- ALOAD /*1*/, "x", INSTANCEOF, IFNE /*R*/,
- NEW, DUP, ALOAD /*1*/, "<init>", ATHROW,
- /*R*/ -1, ALOAD /*2*/, ARETURN))
+ assertSameSummary(getSingleMethod(c, "a"), List(
+ NEW, DUP, ICONST_1, "boxToInteger", LDC, "<init>", ASTORE /*1*/,
+ ALOAD /*1*/, "y", ASTORE /*2*/,
+ ALOAD /*1*/, "x", INSTANCEOF, IFNE /*R*/,
+ NEW, DUP, ALOAD /*1*/, "<init>", ATHROW,
+ /*R*/ -1, ALOAD /*2*/, ARETURN))
}
@Test
@@ -156,7 +155,41 @@ class PatmatBytecodeTest extends ClearAfterClass {
-1 /*A*/ , NEW /*MatchError*/ , DUP, ALOAD /*1*/ , "<init>", ATHROW,
-1 /*B*/ , ILOAD, IRETURN)
- assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary, expected)
- assertEquals(textify(findAsmMethod(c, "b")), getSingleMethod(c, "b").instructions.summary, expected)
+ assertSameSummary(getSingleMethod(c, "a"), expected)
+ assertSameSummary(getSingleMethod(c, "b"), expected)
+ }
+
+ @Test
+ def valPatterns(): Unit = {
+ val code =
+ """case class C(a: Any, b: Int) {
+ | def tplCall = ("hi", 3)
+ | @inline final def tplInline = (true, 'z')
+ |
+ | def t1 = { val (a, b) = (1, 2); a + b }
+ | def t2 = { val (a, _) = (1, 3); a }
+ | def t3 = { val (s, i) = tplCall; s.length + i }
+ | def t4 = { val (_, i) = tplCall; i }
+ | def t5 = { val (b, c) = tplInline; b || c == 'e' }
+ | def t6 = { val (_, c) = tplInline; c }
+ |
+ | def t7 = { val C(s: String, b) = this; s.length + b }
+ | def t8 = { val C(_, b) = this; b }
+ | def t9 = { val C(a, _) = C("hi", 23); a.toString }
+ |}
+ """.stripMargin
+ val List(c, cMod) = compileClasses(optCompiler)(code)
+ assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_1, ICONST_2, IADD, IRETURN))
+ assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, IRETURN))
+ assertInvokedMethods(getSingleMethod(c, "t3"), List("C.tplCall", "scala/Tuple2._1", "scala/Tuple2._2$mcI$sp", "scala/MatchError.<init>", "java/lang/String.length"))
+ assertInvokedMethods(getSingleMethod(c, "t4"), List("C.tplCall", "scala/Tuple2._2$mcI$sp", "scala/MatchError.<init>"))
+ assertNoInvoke(getSingleMethod(c, "t5"))
+ assertSameSummary(getSingleMethod(c, "t6"), List(BIPUSH, IRETURN))
+
+ // MatchError reachable because of the type pattern `s: String`
+ assertInvokedMethods(getSingleMethod(c, "t7"), List("C.a", "C.b", "scala/MatchError.<init>", "java/lang/String.length"))
+ assertSameSummary(getSingleMethod(c, "t8"), List(ALOAD, "b", IRETURN))
+ // C allocation not eliminated - constructor may have side-effects.
+ assertSameSummary(getSingleMethod(c, "t9"), List(NEW, DUP, LDC, BIPUSH, "<init>", "a", "toString", ARETURN))
}
}