summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-07-06 20:12:53 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-07-07 14:33:54 +0200
commite9c742e1d27c41ee8646ea20dfb59efbc3d94ef3 (patch)
tree32ce64bba9d2c2efef5799c5312825e5dbeff08b /test
parent4e9be26c1d0ea4818b54c1f882a2972f439b6e39 (diff)
downloadscala-e9c742e1d27c41ee8646ea20dfb59efbc3d94ef3.tar.gz
scala-e9c742e1d27c41ee8646ea20dfb59efbc3d94ef3.tar.bz2
scala-e9c742e1d27c41ee8646ea20dfb59efbc3d94ef3.zip
Accessibility checks for methods with an InvokeDynamic instruction
Implements the necessary tests to check if a method with an InvokeDynamic instruction can be inlined into a destination class. Only InvokeDynamic instructions with LambdaMetaFactory as bootstrap methods can be inlined. The accessibility checks cannot be implemented generically, because it depends on what the bootstrap method is doing. In particular, the bootstrap method receives a Lookup object as argument which can be used to access private methods of the class where the InvokeDynamic method is located. A comment in the inliner explains the details.
Diffstat (limited to 'test')
-rw-r--r--test/files/presentation/t7678/Runner.scala3
-rw-r--r--test/files/run/t8029.scala3
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala37
3 files changed, 37 insertions, 6 deletions
diff --git a/test/files/presentation/t7678/Runner.scala b/test/files/presentation/t7678/Runner.scala
index e45f057ff1..14d6dc2a70 100644
--- a/test/files/presentation/t7678/Runner.scala
+++ b/test/files/presentation/t7678/Runner.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warnings; re-run with
- */
import scala.tools.nsc.interactive.tests._
import scala.reflect.internal.util._
diff --git a/test/files/run/t8029.scala b/test/files/run/t8029.scala
index 62629d51bc..dbd5c41387 100644
--- a/test/files/run/t8029.scala
+++ b/test/files/run/t8029.scala
@@ -1,6 +1,3 @@
-/*
- * filter: inliner warning; re-run with
- */
import scala.tools.partest._
import scala.tools.nsc._
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
index 0309bb97cc..617eced560 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -991,4 +991,41 @@ class InlinerTest extends ClearAfterClass {
assert(2 == t.collect({case Ldc(_, "hai!") => }).size) // twice the body of f
assert(1 == t.collect({case Jump(IFNONNULL, _) => }).size) // one single null check
}
+
+ @Test
+ def inlineIndyLambda(): Unit = {
+ val code =
+ """object M {
+ | @inline def m(s: String) = {
+ | val f = (x: String) => x.trim
+ | f(s)
+ | }
+ |}
+ |class C {
+ | @inline final def m(s: String) = {
+ | val f = (x: String) => x.trim
+ | f(s)
+ | }
+ | def t1 = m("foo")
+ | def t2 = M.m("bar")
+ |}
+ """.stripMargin
+
+ val List(c, _, _) = compile(code)
+
+ val t1 = getSingleMethod(c, "t1")
+ assert(t1.instructions exists {
+ case _: InvokeDynamic => true
+ case _ => false
+ })
+ // the indy call is inlined into t, and the closure elimination rewrites the closure invocation to the body method
+ assertInvoke(t1, "C", "C$$$anonfun$2")
+
+ val t2 = getSingleMethod(c, "t2")
+ assert(t2.instructions exists {
+ case _: InvokeDynamic => true
+ case _ => false
+ })
+ assertInvoke(t2, "M$", "M$$$anonfun$1")
+ }
}