diff options
Diffstat (limited to 'test/junit')
3 files changed, 42 insertions, 7 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala index 65c96226ff..f7c9cab284 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -90,7 +90,7 @@ class BTypesFromClassfileTest { clearCache() val fromSymbol = classBTypeFromSymbol(classSym) clearCache() - val fromClassfile = bTypes.classBTypeFromParsedClassfile(fromSymbol.internalName) + val fromClassfile = bTypes.classBTypeFromParsedClassfile(fromSymbol.internalName).get sameBType(fromSymbol, fromClassfile) } 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 40dc990c0f..ef0f6bcd77 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))) + test(inliner.findIllegalAccess(m.instructions, classBTypeFromParsedClassfile(classNode.name).get)) } check(cClass, assertEmpty) @@ -153,7 +153,7 @@ 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))) + test(inliner.findIllegalAccess(method.instructions, classBTypeFromParsedClassfile(dest.name).get)) } val cOrDOwner = (_: Option[AbstractInsnNode] @unchecked) match { 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 240d106f5c..4e7a2399a2 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -6,12 +6,15 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.Test import scala.collection.generic.Clearable +import scala.collection.mutable.ListBuffer +import scala.reflect.internal.util.BatchSourceFile import scala.tools.asm.Opcodes._ import org.junit.Assert._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.BasicAnalyzer +import scala.tools.nsc.io._ import scala.tools.testing.AssertUtil._ import CodeGenTools._ @@ -57,7 +60,7 @@ class InlinerTest extends ClearAfterClass { def inlineTest(code: String, mod: ClassNode => Unit = _ => ()): (MethodNode, Option[String]) = { val List(cls) = compile(code) mod(cls) - val clsBType = classBTypeFromParsedClassfile(cls.name) + val clsBType = classBTypeFromParsedClassfile(cls.name).get val List(f, g) = cls.methods.asScala.filter(m => Set("f", "g")(m.name)).toList.sortBy(_.name) val fCall = g.instructions.iterator.asScala.collect({ case i: MethodInsnNode if i.name == "f" => i }).next() @@ -191,8 +194,8 @@ class InlinerTest extends ClearAfterClass { val List(c, d) = compile(code) - val cTp = classBTypeFromParsedClassfile(c.name) - val dTp = classBTypeFromParsedClassfile(d.name) + val cTp = classBTypeFromParsedClassfile(c.name).get + val dTp = classBTypeFromParsedClassfile(d.name).get val g = c.methods.asScala.find(_.name == "g").get val h = d.methods.asScala.find(_.name == "h").get @@ -350,7 +353,7 @@ class InlinerTest extends ClearAfterClass { val List(c) = compile(code) val f = c.methods.asScala.find(_.name == "f").get val callsiteIns = f.instructions.iterator().asScala.collect({ case c: MethodInsnNode => c }).next() - val clsBType = classBTypeFromParsedClassfile(c.name) + val clsBType = classBTypeFromParsedClassfile(c.name).get val analyzer = new BasicAnalyzer(f, clsBType.internalName) val integerClassBType = classBTypeFromInternalName("java/lang/Integer") @@ -414,4 +417,36 @@ class InlinerTest extends ClearAfterClass { // like maxLocals for g1 / f1, but no return value assert(g2.maxLocals == 4 && f2.maxLocals == 3, s"${g2.maxLocals} - ${f2.maxLocals}") } + + @Test + def mixedCompilationNoInline(): Unit = { + // The inliner checks if the invocation `A.bar` can be safely inlined. For that it needs to have + // the bytecode of the invoked method. In mixed compilation, there's no classfile available for + // A, so `flop` cannot be inlined, we cannot check if it's safe. + + val javaCode = + """public class A { + | public static final int bar() { return 100; } + |} + """.stripMargin + + val scalaCode = + """class B { + | @inline final def flop = A.bar + | def g = flop + |} + """.stripMargin + + InlinerTest.notPerRun.foreach(_.clear()) + compiler.reporter.reset() + compiler.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None)) + val run = new compiler.Run() + run.compileSources(List(new BatchSourceFile("A.java", javaCode), new BatchSourceFile("B.scala", scalaCode))) + val outDir = compiler.settings.outputDirs.getSingleOutput.get + + val List(b) = outDir.iterator.map(f => AsmUtils.readClass(f.toByteArray)).toList.sortBy(_.name) + val ins = getSingleMethod(b, "g").instructions + val invokeFlop = Invoke(INVOKEVIRTUAL, "B", "flop", "()I", false) + assert(ins contains invokeFlop, ins mkString "\n") + } } |