From e9c742e1d27c41ee8646ea20dfb59efbc3d94ef3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 6 Jul 2015 20:12:53 +0200 Subject: 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. --- test/files/presentation/t7678/Runner.scala | 3 -- test/files/run/t8029.scala | 3 -- .../tools/nsc/backend/jvm/opt/InlinerTest.scala | 37 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) (limited to 'test') 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") + } } -- cgit v1.2.3