diff options
Diffstat (limited to 'test/junit')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala | 26 | ||||
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala | 48 |
2 files changed, 61 insertions, 13 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala index 03d2f2f108..b4839dcec8 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -59,7 +59,7 @@ class InlinerIllegalAccessTest extends ClearAfterClass { def check(classNode: ClassNode, test: Option[AbstractInsnNode] => Unit) = { for (m <- methods) - test(inliner.findIllegalAccess(m.instructions, classBTypeFromParsedClassfile(classNode.name)).map(_._1)) + test(inliner.findIllegalAccess(m.instructions, classBTypeFromParsedClassfile(cClass.name), classBTypeFromParsedClassfile(classNode.name)).map(_._1)) } check(cClass, assertEmpty) @@ -152,8 +152,8 @@ class InlinerIllegalAccessTest extends ClearAfterClass { val List(rbD, rcD, rfD, rgD) = dCl.methods.asScala.toList.filter(_.name(0) == 'r').sortBy(_.name) - def check(method: MethodNode, dest: ClassNode, test: Option[AbstractInsnNode] => Unit): Unit = { - test(inliner.findIllegalAccess(method.instructions, classBTypeFromParsedClassfile(dest.name)).map(_._1)) + def check(method: MethodNode, decl: ClassNode, dest: ClassNode, test: Option[AbstractInsnNode] => Unit): Unit = { + test(inliner.findIllegalAccess(method.instructions, classBTypeFromParsedClassfile(decl.name), classBTypeFromParsedClassfile(dest.name)).map(_._1)) } val cOrDOwner = (_: Option[AbstractInsnNode] @unchecked) match { @@ -164,35 +164,35 @@ class InlinerIllegalAccessTest extends ClearAfterClass { // PUBLIC // public methods allowed everywhere - for (m <- Set(raC, reC); c <- allClasses) check(m, c, assertEmpty) + for (m <- Set(raC, reC); c <- allClasses) check(m, cCl, c, assertEmpty) // DEFAULT ACCESS // default access OK in same package - for (m <- Set(rbC, rfC, rbD, rfD); c <- allClasses) { - if (c.name startsWith "a/") check(m, c, assertEmpty) - else check(m, c, cOrDOwner) + for ((m, declCls) <- Set((rbC, cCl), (rfC, cCl), (rbD, dCl), (rfD, dCl)); c <- allClasses) { + if (c.name startsWith "a/") check(m, declCls, c, assertEmpty) + else check(m, declCls, c, cOrDOwner) } // PROTECTED // protected accessed in same class, or protected static accessed in subclass(rgD). // can be inlined to subclasses, and classes in the same package (gCl) - for (m <- Set(rcC, rgC, rgD); c <- Set(cCl, dCl, eCl, fCl, gCl, hCl)) check(m, c, assertEmpty) + for ((m, declCls) <- Set((rcC, cCl), (rgC, cCl), (rgD, dCl)); c <- Set(cCl, dCl, eCl, fCl, gCl, hCl)) check(m, declCls, c, assertEmpty) // protected in non-subclass and different package - for (m <- Set(rcC, rgC)) check(m, iCl, cOrDOwner) + for (m <- Set(rcC, rgC)) check(m, cCl, iCl, cOrDOwner) // non-static protected accessed in subclass (rcD). can be inlined to related class, or classes in the same package - for (c <- Set(cCl, dCl, eCl, fCl, gCl)) check(rcD, c, assertEmpty) + for (c <- Set(cCl, dCl, eCl, fCl, gCl)) check(rcD, dCl, c, assertEmpty) // rcD cannot be inlined into non-related classes, if the declaration and destination are not in the same package - for (c <- Set(hCl, iCl)) check(rcD, c, cOrDOwner) + for (c <- Set(hCl, iCl)) check(rcD, dCl, c, cOrDOwner) // PRIVATE // privated method accesses can only be inlined in the same class - for (m <- Set(rdC, rhC)) check(m, cCl, assertEmpty) - for (m <- Set(rdC, rhC); c <- allClasses.tail) check(m, c, cOrDOwner) + for (m <- Set(rdC, rhC)) check(m, cCl, cCl, assertEmpty) + for (m <- Set(rdC, rhC); c <- allClasses.tail) check(m, cCl, c, cOrDOwner) } } 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 0581bd24fe..39fb28570e 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -902,4 +902,52 @@ class InlinerTest extends ClearAfterClass { allowMessage = i => {c += 1; i.msg contains warn}) assert(c == 1, c) } + + @Test + def inlineInvokeSpecial(): Unit = { + val code = + """class Aa { + | def f1 = 0 + |} + |class B extends Aa { + | @inline final override def f1 = 1 + super.f1 // invokespecial Aa.f1 + | + | private def f2m = 0 // public B$$f2m in bytecode + | @inline final def f2 = f2m // invokevirtual B.B$$f2m + | + | private def this(x: Int) = this() // public in bytecode + | @inline final def f3 = new B() // invokespecial B.<init>() + | @inline final def f4 = new B(1) // invokespecial B.<init>(I) + | + | def t1 = f1 // inlined + | def t2 = f2 // inlined + | def t3 = f3 // inlined + | def t4 = f4 // inlined + |} + |class T { + | def t1(b: B) = b.f1 // cannot inline: contains a super call + | def t2(b: B) = b.f2 // inlined + | def t3(b: B) = b.f3 // inlined + | def t4(b: B) = b.f4 // inlined + |} + """.stripMargin + + val warn = + """B::f1()I is annotated @inline but could not be inlined: + |The callee B::f1()I contains the instruction INVOKESPECIAL Aa.f1 ()I + |that would cause an IllegalAccessError when inlined into class T.""".stripMargin + var c = 0 + val List(a, b, t) = compile(code, allowMessage = i => {c += 1; i.msg contains warn}) + assert(c == 1, c) + + assertInvoke(getSingleMethod(b, "t1"), "Aa", "f1") + assertInvoke(getSingleMethod(b, "t2"), "B", "B$$f2m") + assertInvoke(getSingleMethod(b, "t3"), "B", "<init>") + assertInvoke(getSingleMethod(b, "t4"), "B", "<init>") + + assertInvoke(getSingleMethod(t, "t1"), "B", "f1") + assertInvoke(getSingleMethod(t, "t2"), "B", "B$$f2m") + assertInvoke(getSingleMethod(t, "t3"), "B", "<init>") + assertInvoke(getSingleMethod(t, "t4"), "B", "<init>") + } } |