diff options
Diffstat (limited to 'test/junit/scala/tools/nsc/backend/jvm/opt')
17 files changed, 440 insertions, 533 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala index 09675870f0..025248ac28 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala @@ -2,28 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import org.junit.Assert._ -import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.backend.jvm.analysis.{AliasingFrame, AliasingAnalyzer} - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import BackendReporting._ -import BytecodeUtils._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.nsc.backend.jvm.analysis.{AliasingAnalyzer, AliasingFrame} +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class AnalyzerTest extends ClearAfterClass { - val noOptCompiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) +class AnalyzerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ @Test def aliasingOfPrimitives(): Unit = { @@ -39,17 +32,17 @@ class AnalyzerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(noOptCompiler)(code) + val c = compileClass(code) val a = new AliasingAnalyzer(new BasicInterpreter) - val f = findAsmMethod(c, "f") + val f = getAsmMethod(c, "f") a.analyze("C", f) - val List(_, i2l) = findInstr(f, "I2L") + val List(_, i2l) = findInstrs(f, "I2L") val aliasesAtI2l = a.frameAt(i2l, f).asInstanceOf[AliasingFrame[_]].aliases assertEquals(aliasesAtI2l(1).iterator.toList, List(1, 8, 9)) // a, e and stack top assertEquals(aliasesAtI2l(4).iterator.toList, List(4, 6)) - val List(add) = findInstr(f, "LADD") + val add = findInstr(f, "LADD") val aliasesAtAdd = a.frameAt(add, f).asInstanceOf[AliasingFrame[_]].aliases assertEquals(aliasesAtAdd(1).iterator.toList, List(1, 8)) // after i2l the value on the stack is no longer an alias assertEquals(aliasesAtAdd(4).iterator.toList, List(4, 6, 10)) // c, d and stack top 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 aba0aab038..e7aea71e72 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -2,37 +2,29 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.{Ignore, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ import scala.tools.nsc.backend.jvm.BTypes.InternalName -import scala.tools.testing.AssertUtil._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ +import scala.tools.nsc.backend.jvm.BackendReporting._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class BTypesFromClassfileTest { +class BTypesFromClassfileTest extends BytecodeTesting { // inliner enabled -> inlineInfos are collected (and compared) in ClassBTypes - val compiler = newCompiler(extraArgs = "-Yopt:inline-global") + override def compilerArgs = "-Yopt:inline-global" - import compiler._ + import compiler.global._ import definitions._ import genBCode.bTypes import bTypes._ - def duringBackend[T](f: => T) = compiler.exitingDelambdafy(f) + def duringBackend[T](f: => T) = global.exitingDelambdafy(f) - val run = new compiler.Run() // initializes some of the compiler - duringBackend(compiler.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler + val run = new global.Run() // initializes some of the compiler + duringBackend(global.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler duringBackend(bTypes.initializeCoreBTypes()) def clearCache() = bTypes.classBTypeFromInternalName.clear() @@ -91,7 +83,9 @@ class BTypesFromClassfileTest { sameBType(fromSymbol, fromClassfile) } - @Test + // Can be enabled when using 2.12.0-M5 as starr. This test works under a full boostrap, but not + // when compiled with M4. + @Test @Ignore def compareClassBTypes(): Unit = { // Note that not only these classes are tested, but also all their parents and all nested // classes in their InnerClass attributes. diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala index 9a27c42cac..630416a925 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -2,46 +2,38 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test + +import scala.collection.JavaConverters._ import scala.collection.generic.Clearable import scala.collection.immutable.IntMap -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.BackendReporting._ import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class CallGraphTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:inline-global -Yopt-warnings") - ) - import compiler.genBCode.bTypes +class CallGraphTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:inline-global -Yopt-warnings" + import compiler._ + import global.genBCode.bTypes val notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses, bTypes.callGraph.callsites) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache - import compiler.genBCode.bTypes._ + import global.genBCode.bTypes._ import callGraph._ def compile(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(code, allowMessage = allowMessage).map(c => byteCodeRepository.classNode(c.name).get) + compileClasses(code, allowMessage = allowMessage).map(c => byteCodeRepository.classNode(c.name).get) } def callsInMethod(methodNode: MethodNode): List[MethodInsnNode] = methodNode.instructions.iterator.asScala.collect({ @@ -112,10 +104,10 @@ class CallGraphTest extends ClearAfterClass { val List(cCls, cMod, dCls, testCls) = compile(code, checkMsg) assert(msgCount == 6, msgCount) - val List(cf1, cf2, cf3, cf4, cf5, cf6, cf7) = findAsmMethods(cCls, _.startsWith("f")) - val List(df1, df3) = findAsmMethods(dCls, _.startsWith("f")) - val g1 = findAsmMethod(cMod, "g1") - val List(t1, t2) = findAsmMethods(testCls, _.startsWith("t")) + val List(cf1, cf2, cf3, cf4, cf5, cf6, cf7) = getAsmMethods(cCls, _.startsWith("f")) + val List(df1, df3) = getAsmMethods(dCls, _.startsWith("f")) + val g1 = getAsmMethod(cMod, "g1") + val List(t1, t2) = getAsmMethods(testCls, _.startsWith("t")) val List(cf1Call, cf2Call, cf3Call, cf4Call, cf5Call, cf6Call, cf7Call, cg1Call) = callsInMethod(t1) val List(df1Call, df2Call, df3Call, df4Call, df5Call, df6Call, df7Call, dg1Call) = callsInMethod(t2) @@ -151,7 +143,7 @@ class CallGraphTest extends ClearAfterClass { |} """.stripMargin val List(c) = compile(code) - val m = findAsmMethod(c, "m") + val m = getAsmMethod(c, "m") val List(fn) = callsInMethod(m) val forNameMeth = byteCodeRepository.methodNode("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;").get._1 val classTp = classBTypeFromInternalName("java/lang/Class") diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index e8530af4e0..218b02f822 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -2,34 +2,19 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test 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.io._ -import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class ClosureOptimizerTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:classpath -Yopt-warnings:_")) +class ClosureOptimizerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings:_" + import compiler._ @Test def nothingTypedClosureBody(): Unit = { @@ -41,9 +26,9 @@ class ClosureOptimizerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) - val t = findAsmMethod(c, "t") - val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") + val c = compileClass(code) + val t = getAsmMethod(c, "t") + val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") assert(bodyCall.getNext.getOpcode == ATHROW) } @@ -57,9 +42,9 @@ class ClosureOptimizerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) - val t = findAsmMethod(c, "t") - val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") + val c = compileClass(code) + val t = getAsmMethod(c, "t") + val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") assert(bodyCall.getNext.getOpcode == POP) assert(bodyCall.getNext.getNext.getOpcode == ACONST_NULL) } @@ -74,8 +59,8 @@ class ClosureOptimizerTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) - assertSameCode(getSingleMethod(c, "t"), + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List(VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/collection/immutable/List", "head", "()Ljava/lang/Object;", false), TypeOp(CHECKCAST, "java/lang/String"), Invoke(INVOKESTATIC, "C", "C$$$anonfun$1", "(Ljava/lang/String;)Ljava/lang/String;", false), Op(ARETURN))) @@ -95,7 +80,7 @@ class ClosureOptimizerTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) - assertSameSummary(getSingleMethod(c, "t"), List(NEW, DUP, LDC, "<init>", ATHROW)) + val c = compileClass(code) + assertSameSummary(getMethod(c, "t"), List(NEW, DUP, LDC, "<init>", ATHROW)) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala index ac1b759fe2..c3748a05bd 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala @@ -2,23 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting._ +import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class CompactLocalVariablesTest { - +class CompactLocalVariablesTest extends ClearAfterClass { // recurse-unreachable-jumps is required for eliminating catch blocks, in the first dce round they // are still live.only after eliminating the empty handler the catch blocks become unreachable. - val methodOptCompiler = newCompiler(extraArgs = "-Yopt:unreachable-code,compact-locals") - val noCompactVarsCompiler = newCompiler(extraArgs = "-Yopt:unreachable-code") + val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code,compact-locals")) + val noCompactVarsCompiler = cached("noCompactVarsCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) @Test def compactUnused(): Unit = { @@ -58,8 +56,8 @@ class CompactLocalVariablesTest { |} |""".stripMargin - val List(noCompact) = compileMethods(noCompactVarsCompiler)(code) - val List(withCompact) = compileMethods(methodOptCompiler)(code) + val noCompact = noCompactVarsCompiler.compileAsmMethod(code) + val withCompact = methodOptCompiler.compileAsmMethod(code) // code is the same, except for local var indices assertTrue(noCompact.instructions.size == withCompact.instructions.size) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 6d566c722f..3324058cb7 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -2,22 +2,23 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class EmptyExceptionHandlersTest extends ClearAfterClass { +class EmptyExceptionHandlersTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:unreachable-code" + def dceCompiler = compiler + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) val exceptionDescriptor = "java/lang/Exception" @@ -59,8 +60,8 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { def eliminateUnreachableHandler(): Unit = { val code = "def f: Unit = try { } catch { case _: Exception => println(0) }; println(1)" - assertTrue(singleMethod(noOptCompiler)(code).handlers.length == 1) - val optMethod = singleMethod(dceCompiler)(code) + assertTrue(noOptCompiler.compileMethod(code).handlers.length == 1) + val optMethod = dceCompiler.compileMethod(code) assertTrue(optMethod.handlers.isEmpty) val code2 = @@ -72,7 +73,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { | println(2) |}""".stripMargin - assertTrue(singleMethod(dceCompiler)(code2).handlers.isEmpty) + assertTrue(dceCompiler.compileMethod(code2).handlers.isEmpty) } @Test @@ -84,6 +85,6 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { | catch { case _: Exception => 2 } |}""".stripMargin - assertTrue(singleMethod(dceCompiler)(code).handlers.length == 1) + assertTrue(dceCompiler.compileMethod(code).handlers.length == 1) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala index 7283e20745..d57d44f2a3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala @@ -2,16 +2,16 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.asm.Opcodes._ import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.AssertUtil._ +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class EmptyLabelsAndLineNumbersTest { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala index 5cb1aab4a9..e45d7139a3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala @@ -2,36 +2,31 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.collection.generic.Clearable -import org.junit.Assert._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import scala.tools.testing.ClearAfterClass - -import BackendReporting._ import scala.collection.JavaConverters._ +import scala.collection.generic.Clearable +import scala.tools.nsc.backend.jvm.BackendReporting._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class InlineInfoTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:classpath")) +class InlineInfoTest extends BytecodeTesting { + import compiler.global + import global.genBCode.bTypes + + override def compilerArgs = "-Yopt:l:classpath" - import compiler.genBCode.bTypes def notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache def compile(code: String) = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(code) + compiler.compileClasses(code) } @Test @@ -55,11 +50,11 @@ class InlineInfoTest extends ClearAfterClass { """.stripMargin val classes = compile(code) - val fromSyms = classes.map(c => compiler.genBCode.bTypes.classBTypeFromInternalName(c.name).info.get.inlineInfo) + val fromSyms = classes.map(c => global.genBCode.bTypes.classBTypeFromInternalName(c.name).info.get.inlineInfo) val fromAttrs = classes.map(c => { assert(c.attrs.asScala.exists(_.isInstanceOf[InlineInfoAttribute]), c.attrs) - compiler.genBCode.bTypes.inlineInfoFromClassfile(c) + global.genBCode.bTypes.inlineInfoFromClassfile(c) }) assert(fromSyms == fromAttrs) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 6dd0a33289..f0913f3631 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -2,41 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test 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.io._ -import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ -import BackendReporting._ +@RunWith(classOf[JUnit4]) +class InlineWarningTest extends BytecodeTesting { + def optCp = "-Yopt:l:classpath" + override def compilerArgs = s"$optCp -Yopt-warnings" -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass + import compiler._ -@RunWith(classOf[JUnit4]) -class InlineWarningTest extends ClearAfterClass { - val argsNoWarn = "-Yopt:l:classpath" - val args = argsNoWarn + " -Yopt-warnings" - val compiler = cached("compiler", () => newCompiler(extraArgs = args)) - val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:_")) - - def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false, compiler: Global = compiler): List[ClassNode] = { - compileClasses(compiler)(scalaCode, javaCode, allowMessage) - } + val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = s"$optCp -Yopt-warnings:_")) @Test def nonFinal(): Unit = { @@ -58,7 +38,7 @@ class InlineWarningTest extends ClearAfterClass { "C::m1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden", "T::m2()I is annotated @inline but cannot be inlined: the method is not final and may be overridden", "D::m2()I is annotated @inline but cannot be inlined: the method is not final and may be overridden") - compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) + compileToBytes(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) assert(count == 4, count) } @@ -73,7 +53,7 @@ class InlineWarningTest extends ClearAfterClass { """.stripMargin var c = 0 - compile(code, allowMessage = i => {c += 1; i.msg contains "operand stack at the callsite in C::t1()V contains more values"}) + compileToBytes(code, allowMessage = i => {c += 1; i.msg contains "operand stack at the callsite in C::t1()V contains more values"}) assert(c == 1, c) } @@ -103,14 +83,14 @@ class InlineWarningTest extends ClearAfterClass { |Note that the parent class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin) var c = 0 - val List(b) = compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.tail.exists(i.msg contains _)}) + val List(b) = compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.tail.exists(i.msg contains _)}) assert(c == 1, c) // no warnings here - compileClasses(newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:none"))(scalaCode, List((javaCode, "A.java"))) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:none").compileToBytes(scalaCode, List((javaCode, "A.java"))) c = 0 - compileClasses(newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:no-inline-mixed"))(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:no-inline-mixed").compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } @@ -137,7 +117,7 @@ class InlineWarningTest extends ClearAfterClass { |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 - compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } @@ -156,7 +136,7 @@ class InlineWarningTest extends ClearAfterClass { | def t(a: M) = a.f(x => x + 1) |} """.stripMargin - compile(code, allowMessage = _ => false) // no warnings allowed + compileToBytes(code, allowMessage = _ => false) // no warnings allowed val warn = """M::f(Lscala/Function1;)I could not be inlined: @@ -164,7 +144,7 @@ class InlineWarningTest extends ClearAfterClass { |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 - compile(code, compiler = compilerWarnAll, allowMessage = i => { c += 1; i.msg contains warn }) + compilerWarnAll.compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } @@ -185,7 +165,7 @@ class InlineWarningTest extends ClearAfterClass { |does not have the same strictfp mode as the callee C::f()I.""".stripMargin var c = 0 - compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } } 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 ab1aef47cd..c2ada8afec 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -2,27 +2,22 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.asm.tree._ -import scala.tools.testing.AssertUtil._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.Opcodes._ +import scala.tools.asm.tree._ +import scala.tools.nsc.backend.jvm.AsmUtils._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class InlinerIllegalAccessTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - import compiler.genBCode.bTypes._ +class InlinerIllegalAccessTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + + import compiler._ + import global.genBCode.bTypes._ def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, ByteCodeRepository.Classfile) def assertEmpty(ins: Option[AbstractInsnNode]) = for (i <- ins) @@ -44,7 +39,7 @@ class InlinerIllegalAccessTest extends ClearAfterClass { |} """.stripMargin - val allClasses = compileClasses(compiler)(code) + val allClasses = compileClasses(code) val List(cClass, dClass, eClass) = allClasses assert(cClass.name == "a/C" && dClass.name == "a/D" && eClass.name == "b/E", s"${cClass.name}, ${dClass.name}, ${eClass.name}") addToRepo(allClasses) // they are not on the compiler's classpath, so we add them manually to the code repo @@ -120,7 +115,7 @@ class InlinerIllegalAccessTest extends ClearAfterClass { |} """.stripMargin - val allClasses = compileClasses(compiler)(code) + val allClasses = compileClasses(code) val List(cCl, dCl, eCl, fCl, gCl, hCl, iCl) = allClasses addToRepo(allClasses) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index 075513a2b7..b196f1a9ba 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -2,26 +2,15 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import scala.collection.JavaConverters._ - -object InlinerSeparateCompilationTest { - val args = "-Yopt:l:classpath" -} +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class InlinerSeparateCompilationTest { - import InlinerSeparateCompilationTest._ + val args = "-Yopt:l:classpath" @Test def inlnieMixedinMember(): Unit = { @@ -44,9 +33,9 @@ class InlinerSeparateCompilationTest { val warn = "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -Yopt-warnings", _.msg contains warn) - assertInvoke(getSingleMethod(c, "t1"), "T", "f") - assertNoInvoke(getSingleMethod(c, "t2")) - assertNoInvoke(getSingleMethod(c, "t3")) + assertInvoke(getMethod(c, "t1"), "T", "f") + assertNoInvoke(getMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t3")) } @Test @@ -64,7 +53,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(c, t) = compileClassesSeparately(List(codeA, codeB), args) - assertNoInvoke(getSingleMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t1")) } @Test @@ -87,7 +76,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(c, t, u) = compileClassesSeparately(List(codeA, codeB), args) - for (m <- List("t1", "t2", "t3")) assertNoInvoke(getSingleMethod(c, m)) + for (m <- List("t1", "t2", "t3")) assertNoInvoke(getMethod(c, m)) } @Test @@ -108,7 +97,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(a, t) = compileClassesSeparately(List(codeA, assembly), args) - assertNoInvoke(getSingleMethod(t, "f")) - assertNoInvoke(getSingleMethod(a, "n")) + assertNoInvoke(getMethod(t, "f")) + assertNoInvoke(getMethod(a, "n")) } } 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 b7641b5ec7..4e014d4529 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -2,48 +2,44 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.{Ignore, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test + +import scala.collection.JavaConverters._ import scala.collection.generic.Clearable import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - import scala.tools.asm.tree._ +import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.reporters.StoreReporter - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class InlinerTest extends ClearAfterClass { - val args = "-Yopt:l:classpath -Yopt-warnings" - val compiler = cached("compiler", () => newCompiler(extraArgs = args)) +class InlinerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings" + val inlineOnlyCompiler = cached("inlineOnlyCompiler", () => newCompiler(extraArgs = "-Yopt:inline-project")) - import compiler.genBCode.bTypes + + import compiler._ + import global.genBCode.bTypes // allows inspecting the caches after a compilation run def notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses, bTypes.callGraph.callsites) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache - import compiler.genBCode.bTypes._ - import compiler.genBCode.bTypes.backendUtils._ + import global.genBCode.bTypes.{byteCodeRepository, callGraph, inliner, inlinerHeuristics} import inlinerHeuristics._ def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(scalaCode, javaCode, allowMessage) + compileToBytes(scalaCode, javaCode, allowMessage) // Use the class nodes stored in the byteCodeRepository. The ones returned by compileClasses are not the same, // these are created new from the classfile byte array. They are completely separate instances which cannot // be used to look up methods / callsites in the callGraph hash maps for example. @@ -64,7 +60,7 @@ class InlinerTest extends ClearAfterClass { def gMethAndFCallsite(code: String, mod: ClassNode => Unit = _ => ()) = { val List(c) = compile(code) mod(c) - val gMethod = findAsmMethod(c, "g") + val gMethod = getAsmMethod(c, "g") val fCall = getCallsite(gMethod, "f") (gMethod, fCall) } @@ -138,7 +134,7 @@ class InlinerTest extends ClearAfterClass { assertSameCode(convertMethod(g), gBeforeLocalOpt) - compiler.genBCode.bTypes.localOpt.methodOptimizations(g, "C") + global.genBCode.bTypes.localOpt.methodOptimizations(g, "C") assertSameCode(convertMethod(g), invokeQQQ :+ Op(ATHROW)) } @@ -152,7 +148,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val can = canInlineTest(code, cls => { - val f = cls.methods.asScala.find(_.name == "f").get + val f = getAsmMethod(cls, "f") f.access |= ACC_SYNCHRONIZED }) assert(can.nonEmpty && can.get.isInstanceOf[SynchronizedMethod], can) @@ -201,7 +197,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, d) = compile(code) - val hMeth = findAsmMethod(d, "h") + val hMeth = getAsmMethod(d, "h") val gCall = getCallsite(hMeth, "g") val r = inliner.canInlineBody(gCall) assert(r.nonEmpty && r.get.isInstanceOf[IllegalAccessInstruction], r) @@ -218,7 +214,7 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(cCls) = compile(code) - val instructions = getSingleMethod(cCls, "test").instructions + val instructions = getInstructions(cCls, "test") assert(instructions.contains(Op(ICONST_0)), instructions.stringLines) assert(!instructions.contains(Op(ICONST_1)), instructions) } @@ -284,7 +280,7 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, _, _) = compile(code) - val ins = getSingleMethod(c, "f").instructions + val ins = getInstructions(c, "f") val invokeSysArraycopy = Invoke(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false) assert(ins contains invokeSysArraycopy, ins.stringLines) } @@ -316,7 +312,7 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, t) = compile(code) - assertNoInvoke(getSingleMethod(c, "g")) + assertNoInvoke(getMethod(c, "g")) } @Test @@ -329,7 +325,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) // no more invoke, f is inlined - assertNoInvoke(getSingleMethod(c, "g")) + assertNoInvoke(getMethod(c, "g")) } @Test @@ -341,7 +337,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - val fMeth = findAsmMethod(c, "f") + val fMeth = getAsmMethod(c, "f") val call = getCallsite(fMeth, "lowestOneBit") val warning = inliner.canInlineBody(call) @@ -380,7 +376,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin // use a compiler without local optimizations (cleanups) - val List(c) = compileClasses(inlineOnlyCompiler)(code) + val c = inlineOnlyCompiler.compileClass(code) val ms @ List(f1, f2, g1, g2) = c.methods.asScala.filter(_.name.length == 2).toList // stack height at callsite of f1 is 1, so max of g1 after inlining is max of f1 + 1 @@ -425,7 +421,7 @@ class InlinerTest extends ClearAfterClass { var c = 0 val List(b) = compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn}) assert(c == 1, c) - val ins = getSingleMethod(b, "g").instructions + val ins = getInstructions(b, "g") val invokeFlop = Invoke(INVOKEVIRTUAL, "B", "flop", "()I", false) assert(ins contains invokeFlop, ins.stringLines) } @@ -445,8 +441,8 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, t) = compile(code) // both are just `return 1`, no more calls - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -464,8 +460,8 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, t, u) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -485,8 +481,8 @@ class InlinerTest extends ClearAfterClass { var count = 0 val List(c, t) = compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) assert(count == 2, count) - assertInvoke(getSingleMethod(c, "t1"), "T", "f") - assertInvoke(getSingleMethod(c, "t2"), "C", "f") + assertInvoke(getMethod(c, "t1"), "T", "f") + assertInvoke(getMethod(c, "t2"), "C", "f") } @Test @@ -500,7 +496,7 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, t) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t1")) } @Test @@ -524,11 +520,11 @@ class InlinerTest extends ClearAfterClass { val List(c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1; i.msg contains warn}) assert(count == 1, count) - assertNoInvoke(getSingleMethod(t, "f")) + assertNoInvoke(getMethod(t, "f")) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) - assertInvoke(getSingleMethod(c, "t3"), "T", "f") + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) + assertInvoke(getMethod(c, "t3"), "T", "f") } @Test @@ -550,12 +546,12 @@ class InlinerTest extends ClearAfterClass { val List(assembly, c, t) = compile(code) - assertNoInvoke(getSingleMethod(t, "f")) + assertNoInvoke(getMethod(t, "f")) - assertNoInvoke(getSingleMethod(assembly, "n")) + assertNoInvoke(getMethod(assembly, "n")) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -628,20 +624,20 @@ class InlinerTest extends ClearAfterClass { val List(ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1; i.msg contains warning}) assert(count == 4, count) // see comments, f is not inlined 4 times - assertNoInvoke(getSingleMethod(t2a, "g2a")) - assertInvoke(getSingleMethod(t2b, "g2b"), "T1", "f") + assertNoInvoke(getMethod(t2a, "g2a")) + assertInvoke(getMethod(t2b, "g2b"), "T1", "f") - assertInvoke(getSingleMethod(ca, "m1a"), "T1", "f") - assertNoInvoke(getSingleMethod(ca, "m2a")) // no invoke, see comment on def g2a - assertNoInvoke(getSingleMethod(ca, "m3a")) - assertInvoke(getSingleMethod(ca, "m4a"), "T1", "f") - assertNoInvoke(getSingleMethod(ca, "m5a")) + assertInvoke(getMethod(ca, "m1a"), "T1", "f") + assertNoInvoke(getMethod(ca, "m2a")) // no invoke, see comment on def g2a + assertNoInvoke(getMethod(ca, "m3a")) + assertInvoke(getMethod(ca, "m4a"), "T1", "f") + assertNoInvoke(getMethod(ca, "m5a")) - assertInvoke(getSingleMethod(cb, "m1b"), "T1", "f") - assertInvoke(getSingleMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b - assertNoInvoke(getSingleMethod(cb, "m3b")) - assertInvoke(getSingleMethod(cb, "m4b"), "T1", "f") - assertNoInvoke(getSingleMethod(cb, "m5b")) + assertInvoke(getMethod(cb, "m1b"), "T1", "f") + assertInvoke(getMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b + assertNoInvoke(getMethod(cb, "m3b")) + assertInvoke(getMethod(cb, "m4b"), "T1", "f") + assertNoInvoke(getMethod(cb, "m5b")) } @Test @@ -658,7 +654,7 @@ class InlinerTest extends ClearAfterClass { |} // so d.f can be resolved statically. same for E.f """.stripMargin val List(c, d, e, eModule, t) = compile(code) - assertNoInvoke(getSingleMethod(t, "t1")) + assertNoInvoke(getMethod(t, "t1")) } @Test @@ -673,8 +669,8 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, d, t) = compile(code) - assertNoInvoke(getSingleMethod(d, "m")) - assertNoInvoke(getSingleMethod(c, "m")) + assertNoInvoke(getMethod(d, "m")) + assertNoInvoke(getMethod(c, "m")) } @Test @@ -688,8 +684,8 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c, t) = compile(code) - val t1 = getSingleMethod(t, "t1") - val t2 = getSingleMethod(t, "t2") + val t1 = getMethod(t, "t1") + val t2 = getMethod(t, "t2") val cast = TypeOp(CHECKCAST, "C") Set(t1, t2).foreach(m => assert(m.instructions.contains(cast), m.instructions)) } @@ -769,27 +765,27 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, t, u) = compile(code, allowMessage = _.msg contains "i()I is annotated @inline but cannot be inlined") - val m1 = getSingleMethod(c, "m1") + val m1 = getMethod(c, "m1") assertInvoke(m1, "T", "a") assertInvoke(m1, "T", "b") assertInvoke(m1, "T", "c") - assertNoInvoke(getSingleMethod(c, "m2")) + assertNoInvoke(getMethod(c, "m2")) - val m3 = getSingleMethod(c, "m3") + val m3 = getMethod(c, "m3") assertInvoke(m3, "T", "f") assertInvoke(m3, "T", "g") assertInvoke(m3, "T", "h") assertInvoke(m3, "T", "i") - val m4 = getSingleMethod(c, "m4") + val m4 = getMethod(c, "m4") assertInvoke(m4, "U", "a") assertInvoke(m4, "U", "b") assertInvoke(m4, "U", "c") - assertNoInvoke(getSingleMethod(c, "m5")) + assertNoInvoke(getMethod(c, "m5")) - val m6 = getSingleMethod(c, "m6") + val m6 = getMethod(c, "m6") assertInvoke(m6, "U", "f") assertInvoke(m6, "U", "g") assertInvoke(m6, "U", "h") @@ -829,7 +825,7 @@ class InlinerTest extends ClearAfterClass { var c = 0 - compileClasses(newCompiler(extraArgs = args + " -Yopt-warnings:_"))( + newCompiler(extraArgs = compilerArgs + " -Yopt-warnings:_").compileClasses( scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn}) @@ -873,15 +869,15 @@ class InlinerTest extends ClearAfterClass { 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(getMethod(b, "t1"), "Aa", "f1") + assertInvoke(getMethod(b, "t2"), "B", "B$$f2m") + assertInvoke(getMethod(b, "t3"), "B", "<init>") + assertInvoke(getMethod(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>") + assertInvoke(getMethod(t, "t1"), "B", "f1") + assertInvoke(getMethod(t, "t2"), "B", "B$$f2m") + assertInvoke(getMethod(t, "t3"), "B", "<init>") + assertInvoke(getMethod(t, "t4"), "B", "<init>") } @Test @@ -891,8 +887,8 @@ class InlinerTest extends ClearAfterClass { | def t = System.arraycopy(null, 0, null, 0, 0) |} """.stripMargin - val List(c) = compileClasses(newCompiler(extraArgs = args + " -Yopt-inline-heuristics:everything"))(code) - assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy") + val c = newCompiler(extraArgs = compilerArgs + " -Yopt-inline-heuristics:everything").compileClass(code) + assertInvoke(getMethod(c, "t"), "java/lang/System", "arraycopy") } @Test @@ -906,7 +902,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "<init>") + assertInvoke(getMethod(c, "t"), "java/lang/Error", "<init>") } @Test @@ -919,7 +915,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - val t = getSingleMethod(c, "t").instructions + val t = getInstructions(c, "t") assertNoInvoke(t) assert(1 == t.collect({case Ldc(_, "hai!") => }).size) // push-pop eliminates the first LDC("hai!") assert(1 == t.collect({case Jump(IFNONNULL, _) => }).size) // one single null check @@ -946,12 +942,12 @@ class InlinerTest extends ClearAfterClass { val List(c, _, _) = compile(code) - val t1 = getSingleMethod(c, "t1") + val t1 = getMethod(c, "t1") assertNoIndy(t1) // 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") + val t2 = getMethod(c, "t2") assertNoIndy(t2) assertInvoke(t2, "M$", "M$$$anonfun$1") } @@ -968,9 +964,9 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - val hMeth = findAsmMethod(c, "h") - val gMeth = findAsmMethod(c, "g") - val iMeth = findAsmMethod(c, "i") + val hMeth = getAsmMethod(c, "h") + val gMeth = getAsmMethod(c, "g") + val iMeth = getAsmMethod(c, "i") val fCall = getCallsite(gMeth, "f") val gCall = getCallsite(hMeth, "g") val hCall = getCallsite(iMeth, "h") @@ -997,7 +993,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(cl) = compile(code) - val List(b, c, d) = List("b", "c", "d").map(findAsmMethod(cl, _)) + val List(b, c, d) = List("b", "c", "d").map(getAsmMethod(cl, _)) val aCall = getCallsite(b, "a") val bCall = getCallsite(c, "b") val cCall = getCallsite(d, "c") @@ -1037,15 +1033,15 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t1"), "C", "C$$$anonfun$1") - assertInvoke(getSingleMethod(c, "t2"), "C", "a") - assertInvoke(getSingleMethod(c, "t3"), "C", "b") - assertNoInvoke(getSingleMethod(c, "t4")) - assertNoInvoke(getSingleMethod(c, "t5")) - assertNoInvoke(getSingleMethod(c, "t6")) - assertInvoke(getSingleMethod(c, "t7"), "C", "c") - assertInvoke(getSingleMethod(c, "t8"), "scala/Predef$", "println") - assertNoInvoke(getSingleMethod(c, "t9")) + assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t2"), "C", "a") + assertInvoke(getMethod(c, "t3"), "C", "b") + assertNoInvoke(getMethod(c, "t4")) + assertNoInvoke(getMethod(c, "t5")) + assertNoInvoke(getMethod(c, "t6")) + assertInvoke(getMethod(c, "t7"), "C", "c") + assertInvoke(getMethod(c, "t8"), "scala/Predef$", "println") + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -1070,15 +1066,15 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertInvoke(getSingleMethod(c, "t2"), "C", "f2") - assertInvoke(getSingleMethod(c, "t3"), "C", "f1") - assertInvoke(getSingleMethod(c, "t4"), "C", "f2") - assertNoInvoke(getSingleMethod(c, "t5")) - assertInvoke(getSingleMethod(c, "t6"), "C", "f3") - assertNoInvoke(getSingleMethod(c, "t7")) - assertInvoke(getSingleMethod(c, "t8"), "C", "f1") - assertNoInvoke(getSingleMethod(c, "t9")) + assertNoInvoke(getMethod(c, "t1")) + assertInvoke(getMethod(c, "t2"), "C", "f2") + assertInvoke(getMethod(c, "t3"), "C", "f1") + assertInvoke(getMethod(c, "t4"), "C", "f2") + assertNoInvoke(getMethod(c, "t5")) + assertInvoke(getMethod(c, "t6"), "C", "f3") + assertNoInvoke(getMethod(c, "t7")) + assertInvoke(getMethod(c, "t8"), "C", "f1") + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -1101,11 +1097,11 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t1"), "C", "C$$$anonfun$1") - assertInvoke(getSingleMethod(c, "t2"), "C", "C$$$anonfun$2") - assertInvoke(getSingleMethod(c, "t3"), "scala/Function1", "apply$mcII$sp") - assertInvoke(getSingleMethod(c, "t4"), "scala/Function1", "apply$mcII$sp") - assertInvoke(getSingleMethod(c, "t5"), "C", "h") + assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t2"), "C", "C$$$anonfun$2") + assertInvoke(getMethod(c, "t3"), "scala/Function1", "apply$mcII$sp") + assertInvoke(getMethod(c, "t4"), "scala/Function1", "apply$mcII$sp") + assertInvoke(getMethod(c, "t5"), "C", "h") } @Test @@ -1125,7 +1121,7 @@ class InlinerTest extends ClearAfterClass { |when entering an exception handler declared in the inlined method.""".stripMargin val List(c) = compile(code, allowMessage = _.msg contains warn) - assertInvoke(getSingleMethod(c, "t"), "C", "g") + assertInvoke(getMethod(c, "t"), "C", "g") } @Test @@ -1149,8 +1145,8 @@ class InlinerTest extends ClearAfterClass { |that would cause an IllegalAccessError when inlined into class D.""".stripMargin val List(c, d) = compile(code, allowMessage = _.msg contains warn) - assertInvoke(getSingleMethod(c, "h"), "C", "f$1") - assertInvoke(getSingleMethod(d, "t"), "C", "h") + assertInvoke(getMethod(c, "h"), "C", "f$1") + assertInvoke(getMethod(d, "t"), "C", "h") } @Test @@ -1168,8 +1164,8 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, d) = compile(code) - assertNoInvoke(getSingleMethod(c, "g")) - assertNoInvoke(getSingleMethod(d, "t")) + assertNoInvoke(getMethod(c, "g")) + assertNoInvoke(getMethod(d, "t")) } @Test @@ -1277,40 +1273,40 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, _, _) = compile(code) - assertSameSummary(getSingleMethod(c, "t1"), List(BIPUSH, "C$$$anonfun$1", IRETURN)) - assertSameSummary(getSingleMethod(c, "t1a"), List(LCONST_1, "C$$$anonfun$2", IRETURN)) - assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, ICONST_2, "C$$$anonfun$3",IRETURN)) + assertSameSummary(getMethod(c, "t1"), List(BIPUSH, "C$$$anonfun$1", IRETURN)) + assertSameSummary(getMethod(c, "t1a"), List(LCONST_1, "C$$$anonfun$2", IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_2, "C$$$anonfun$3",IRETURN)) // val a = new ValKl(n); new ValKl(anonfun(a.x)).x // value class instantiation-extraction should be optimized by boxing elim - assertSameSummary(getSingleMethod(c, "t3"), List( + assertSameSummary(getMethod(c, "t3"), List( NEW, DUP, ICONST_1, "<init>", ASTORE, NEW, DUP, ALOAD, "x", "C$$$anonfun$4", "<init>", "x", IRETURN)) - assertSameSummary(getSingleMethod(c, "t4"), List(BIPUSH, "C$$$anonfun$5", "boxToInteger", ARETURN)) - assertSameSummary(getSingleMethod(c, "t4a"), List(ICONST_1, LDC, "C$$$anonfun$6", LRETURN)) - assertSameSummary(getSingleMethod(c, "t5"), List(BIPUSH, ICONST_3, "C$$$anonfun$7", "boxToInteger", ARETURN)) - assertSameSummary(getSingleMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "C$$$anonfun$8", IRETURN)) - assertSameSummary(getSingleMethod(c, "t6"), List(BIPUSH, "C$$$anonfun$9", RETURN)) - assertSameSummary(getSingleMethod(c, "t7"), List(ICONST_1, "C$$$anonfun$10", RETURN)) - assertSameSummary(getSingleMethod(c, "t8"), List(ICONST_1, LDC, "C$$$anonfun$11", LRETURN)) - assertSameSummary(getSingleMethod(c, "t9"), List(ICONST_1, "boxToInteger", "C$$$anonfun$12", RETURN)) + assertSameSummary(getMethod(c, "t4"), List(BIPUSH, "C$$$anonfun$5", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t4a"), List(ICONST_1, LDC, "C$$$anonfun$6", LRETURN)) + assertSameSummary(getMethod(c, "t5"), List(BIPUSH, ICONST_3, "C$$$anonfun$7", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "C$$$anonfun$8", IRETURN)) + assertSameSummary(getMethod(c, "t6"), List(BIPUSH, "C$$$anonfun$9", RETURN)) + assertSameSummary(getMethod(c, "t7"), List(ICONST_1, "C$$$anonfun$10", RETURN)) + assertSameSummary(getMethod(c, "t8"), List(ICONST_1, LDC, "C$$$anonfun$11", LRETURN)) + assertSameSummary(getMethod(c, "t9"), List(ICONST_1, "boxToInteger", "C$$$anonfun$12", RETURN)) // t9a inlines Range.foreach, which is quite a bit of code, so just testing the core - assertInvoke(getSingleMethod(c, "t9a"), "C", "C$$$anonfun$13") - assertInvoke(getSingleMethod(c, "t9a"), "scala/runtime/BoxesRunTime", "boxToInteger") + assertInvoke(getMethod(c, "t9a"), "C", "C$$$anonfun$13") + assertInvoke(getMethod(c, "t9a"), "scala/runtime/BoxesRunTime", "boxToInteger") - assertSameSummary(getSingleMethod(c, "t10"), List( + assertSameSummary(getMethod(c, "t10"), List( ICONST_1, ISTORE, ALOAD, ILOAD, "C$$$anonfun$14", RETURN)) // t10a inlines Range.foreach - assertInvoke(getSingleMethod(c, "t10a"), "C", "C$$$anonfun$15") - assertDoesNotInvoke(getSingleMethod(c, "t10a"), "boxToInteger") + assertInvoke(getMethod(c, "t10a"), "C", "C$$$anonfun$15") + assertDoesNotInvoke(getMethod(c, "t10a"), "boxToInteger") } @Test @@ -1333,8 +1329,8 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c) = compile(code) - assertSameCode(getSingleMethod(c, "t1"), List(Op(ICONST_0), Op(ICONST_1), Op(IADD), Op(IRETURN))) - assertEquals(getSingleMethod(c, "t2").instructions collect { case i: Invoke => i.owner +"."+ i.name }, List( + assertSameCode(getMethod(c, "t1"), List(Op(ICONST_0), Op(ICONST_1), Op(IADD), Op(IRETURN))) + assertEquals(getInstructions(c, "t2") collect { case i: Invoke => i.owner +"."+ i.name }, List( "scala/runtime/IntRef.create", "C.C$$$anonfun$1")) } @@ -1374,11 +1370,11 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c) = compile(code) - assertSameCode(getSingleMethod(c, "t1"), List(Op(ICONST_3), Op(ICONST_4), Op(IADD), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t2"), List(Op(ICONST_1), Op(ICONST_2), Op(IADD), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(Op(ICONST_1), Op(ICONST_3), Op(ISUB), Op(IRETURN))) - assertNoInvoke(getSingleMethod(c, "t4")) - assertNoInvoke(getSingleMethod(c, "t5")) + assertSameCode(getMethod(c, "t1"), List(Op(ICONST_3), Op(ICONST_4), Op(IADD), Op(IRETURN))) + assertSameCode(getMethod(c, "t2"), List(Op(ICONST_1), Op(ICONST_2), Op(IADD), Op(IRETURN))) + assertSameCode(getMethod(c, "t3"), List(Op(ICONST_1), Op(ICONST_3), Op(ISUB), Op(IRETURN))) + assertNoInvoke(getMethod(c, "t4")) + assertNoInvoke(getMethod(c, "t5")) } @Test @@ -1404,10 +1400,10 @@ class InlinerTest extends ClearAfterClass { |class D extends C """.stripMargin val List(c, _) = compile(code) - def casts(m: String) = getSingleMethod(c, m).instructions collect { case TypeOp(CHECKCAST, tp) => tp } - assertSameCode(getSingleMethod(c, "t1"), List(VarOp(ALOAD, 1), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t2"), List(VarOp(ALOAD, 1), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(VarOp(ALOAD, 1), TypeOp(CHECKCAST, "C"), Op(ARETURN))) + def casts(m: String) = getInstructions(c, m) collect { case TypeOp(CHECKCAST, tp) => tp } + assertSameCode(getMethod(c, "t1"), List(VarOp(ALOAD, 1), Op(ARETURN))) + assertSameCode(getMethod(c, "t2"), List(VarOp(ALOAD, 1), Op(ARETURN))) + assertSameCode(getMethod(c, "t3"), List(VarOp(ALOAD, 1), TypeOp(CHECKCAST, "C"), Op(ARETURN))) assertEquals(casts("t4"), List("C")) assertEquals(casts("t5"), Nil) assertEquals(casts("t6"), Nil) @@ -1432,8 +1428,8 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val cls = compile(code) - val test = cls.find(_.name == "Test$").get - assertSameSummary(getSingleMethod(test, "f"), List( + val test = findClass(cls, "Test$") + assertSameSummary(getMethod(test, "f"), List( GETSTATIC, "mkFoo", BIPUSH, ISTORE, IFNONNULL, ACONST_NULL, ATHROW, -1 /*label*/, @@ -1452,7 +1448,7 @@ class InlinerTest extends ClearAfterClass { val List(c) = compile(code) // box-unbox will clean it up - assertSameSummary(getSingleMethod(c, "t"), List( + assertSameSummary(getMethod(c, "t"), List( ALOAD, "C$$$anonfun$1", IFEQ /*A*/, "C$$$anonfun$2", IRETURN, -1 /*A*/, "C$$$anonfun$3", IRETURN)) @@ -1464,7 +1460,7 @@ class InlinerTest extends ClearAfterClass { val codeB = "class B { def t(a: A) = a.f }" // tests that no warning is emitted val List(a, b) = compileClassesSeparately(List(codeA, codeB), extraArgs = "-Yopt:l:project -Yopt-warnings") - assertInvoke(getSingleMethod(b, "t"), "A", "f") + assertInvoke(getMethod(b, "t"), "A", "f") } @Test @@ -1476,7 +1472,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin val List(c, t1, t2) = compile(code, allowMessage = _ => true) // the forwarder C.f is inlined, so there's no invocation - assertSameSummary(getSingleMethod(c, "f"), List(ICONST_1, IRETURN)) + assertSameSummary(getMethod(c, "f"), List(ICONST_1, IRETURN)) } @Test @@ -1489,10 +1485,12 @@ class InlinerTest extends ClearAfterClass { |class C { def t = (new K).f } """.stripMargin val c :: _ = compile(code) - assertSameSummary(getSingleMethod(c, "t"), List(NEW, "<init>", ICONST_1, IRETURN)) // ICONST_1, U.f is inlined (not T.f) + assertSameSummary(getMethod(c, "t"), List(NEW, "<init>", ICONST_1, IRETURN)) // ICONST_1, U.f is inlined (not T.f) } - @Test + // Can be enabled when using 2.12.0-M5 as starr. This test works under a full boostrap, but not + // when compiled with M4. + @Test @Ignore def inlineArrayForeach(): Unit = { val code = """class C { @@ -1501,7 +1499,7 @@ class InlinerTest extends ClearAfterClass { |} """.stripMargin val List(c) = compile(code) - val t = getSingleMethod(c, "t") + val t = getMethod(c, "t") assertNoIndy(t) assertInvoke(t, "C", "C$$$anonfun$1") } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 003b2d4880..fa76c0d930 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -2,42 +2,40 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.collection.JavaConverters._ +import scala.tools.asm.Opcodes._ import scala.tools.asm.tree.ClassNode import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.testing.AssertUtil._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass -import scala.collection.JavaConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class MethodLevelOptsTest extends ClearAfterClass { - val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:method")) +class MethodLevelOptsTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:method" + import compiler._ def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) - def locals(c: ClassNode, m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) + def locals(c: ClassNode, m: String) = getAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) @Test def eliminateEmptyTry(): Unit = { val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }" val warn = "a pure expression does nothing in statement position" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) + assertSameCode(compileInstructions(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) } @Test def eliminateLoadBoxedUnit(): Unit = { // the compiler inserts a boxed into the try block. it's therefore non-empty (and live) and not eliminated. val code = "def f = { try {} catch { case _: Throwable => 0 }; 1 }" - val m = singleMethod(methodOptCompiler)(code) + val m = compileMethod(code) assertTrue(m.handlers.length == 0) assertSameCode(m, List(Op(ICONST_1), Op(IRETURN))) } @@ -46,7 +44,7 @@ class MethodLevelOptsTest extends ClearAfterClass { def inlineThrowInCatchNotTry(): Unit = { // the try block does not contain the `ATHROW` instruction, but in the catch block, `ATHROW` is inlined val code = "def f(e: Exception) = throw { try e catch { case _: Throwable => e } }" - val m = singleMethod(methodOptCompiler)(code) + val m = compileMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(VarOp(ALOAD, 1), Label(3), Op(ATHROW), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), VarOp(ALOAD, 1), Op(ATHROW)) @@ -57,7 +55,7 @@ class MethodLevelOptsTest extends ClearAfterClass { def inlineReturnInCatchNotTry(): Unit = { val code = "def f: Int = return { try 1 catch { case _: Throwable => 2 } }" // cannot inline the IRETURN into the try block (because RETURN may throw IllegalMonitorState) - val m = singleMethod(methodOptCompiler)(code) + val m = compileMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(Op(ICONST_1), Label(3), Op(IRETURN), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), Op(ICONST_2), Op(IRETURN))) @@ -79,7 +77,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | println(x) | } """.stripMargin - val m = singleMethod(methodOptCompiler)(code) + val m = compileMethod(code) assertTrue(m.handlers.isEmpty) assertSameCode(m, List(Op(ICONST_3), Op(IRETURN))) } @@ -99,8 +97,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( Op(ACONST_NULL), Invoke(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false), Op(ARETURN))) } @@ -116,9 +114,9 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val c = compileClass(code) assertSameCode( - getSingleMethod(c, "t"), List(Ldc(LDC, "c"), Op(ARETURN))) + getMethod(c, "t"), List(Ldc(LDC, "c"), Op(ARETURN))) } @Test @@ -136,9 +134,9 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val c = compileClass(code) - assertSameCode(getSingleMethod(c, "t"), List( + assertSameCode(getMethod(c, "t"), List( Ldc(LDC, "el"), VarOp(ASTORE, 1), Field(GETSTATIC, "scala/Predef$", "MODULE$", "Lscala/Predef$;"), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), Op(ACONST_NULL), VarOp(ASTORE, 1), @@ -160,8 +158,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( IntOp(BIPUSH, 23), IntOp(NEWARRAY, 5), Op(POP), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) } @@ -175,8 +173,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( TypeOp(NEW, "java/lang/Integer"), Ldc(LDC, "nono"), Invoke(INVOKESPECIAL, "java/lang/Integer", "<init>", "(Ljava/lang/String;)V", false), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) } @@ -201,8 +199,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameCode(getSingleMethod(c, "t"), List(Op(ICONST_0), Op(IRETURN))) + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List(Op(ICONST_0), Op(IRETURN))) } @Test @@ -217,8 +215,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( IntOp(BIPUSH, 30), VarOp(ISTORE, 3), // no constant propagation, so we keep the store (and load below) of a const VarOp(ILOAD, 1), VarOp(ILOAD, 2), @@ -238,8 +236,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - val t = getSingleMethod(c, "t") + val c = compileClass(code) + val t = getMethod(c, "t") assert(!t.instructions.exists(_.opcode == INVOKEDYNAMIC), t) } @@ -319,23 +317,23 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) - assertInvoke(getSingleMethod(c, "t3"), "scala/runtime/BoxesRunTime", "unboxToInt") - assertInvoke(getSingleMethod(c, "t4"), "scala/runtime/BoxesRunTime", "boxToLong") - assertNoInvoke(getSingleMethod(c, "t5")) - assertNoInvoke(getSingleMethod(c, "t6")) - assertNoInvoke(getSingleMethod(c, "t7")) - assertSameSummary(getSingleMethod(c, "t8"), List(ICONST_0, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t9")) + val c = compileClass(code) + + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) + assertInvoke(getMethod(c, "t3"), "scala/runtime/BoxesRunTime", "unboxToInt") + assertInvoke(getMethod(c, "t4"), "scala/runtime/BoxesRunTime", "boxToLong") + assertNoInvoke(getMethod(c, "t5")) + assertNoInvoke(getMethod(c, "t6")) + assertNoInvoke(getMethod(c, "t7")) + assertSameSummary(getMethod(c, "t8"), List(ICONST_0, IRETURN)) + assertNoInvoke(getMethod(c, "t9")) // t10: no invocation of unbox - assertEquals(getSingleMethod(c, "t10").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + assertEquals(getInstructions(c, "t10") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("java/lang/Integer", "valueOf"), ("C", "escape"))) - assertSameSummary(getSingleMethod(c, "t11"), List( + assertSameSummary(getMethod(c, "t11"), List( BIPUSH, "valueOf", ASTORE /*2*/, BIPUSH, "valueOf", ASTORE /*3*/, ALOAD /*0*/, ALOAD /*2*/, "escape", @@ -343,7 +341,7 @@ class MethodLevelOptsTest extends ClearAfterClass { ASTORE /*4*/, GETSTATIC /*Predef*/, ALOAD /*4*/, "Integer2int", IRETURN)) // no unbox invocations - assertEquals(getSingleMethod(c, "t12").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + assertEquals(getInstructions(c, "t12") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("java/lang/Integer", "valueOf"), ("java/lang/Integer", "valueOf"), ("C", "escape"))) @@ -395,14 +393,14 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_0, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t2")) - assertSameSummary(getSingleMethod(c, "t3"), List(LDC, LDC, LADD, LRETURN)) - assertNoInvoke(getSingleMethod(c, "t4")) - assertEquals(getSingleMethod(c, "t5").instructions collect { case Field(_, owner, name, _) => s"$owner.$name" }, + val c = compileClass(code) + assertSameSummary(getMethod(c, "t1"), List(ICONST_0, IRETURN)) + assertNoInvoke(getMethod(c, "t2")) + assertSameSummary(getMethod(c, "t3"), List(LDC, LDC, LADD, LRETURN)) + assertNoInvoke(getMethod(c, "t4")) + assertEquals(getInstructions(c, "t5") collect { case Field(_, owner, name, _) => s"$owner.$name" }, List("scala/runtime/IntRef.elem")) - assertEquals(getSingleMethod(c, "t6").instructions collect { case Field(op, owner, name, _) => s"$op $owner.$name" }, + assertEquals(getInstructions(c, "t6") collect { case Field(op, owner, name, _) => s"$op $owner.$name" }, List(s"$PUTFIELD scala/runtime/IntRef.elem", s"$GETFIELD scala/runtime/IntRef.elem")) } @@ -459,23 +457,23 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, ICONST_3, IADD, IRETURN)) - assertSameSummary(getSingleMethod(c, "t3"), List(ICONST_3, ICONST_4, IADD, IRETURN)) - assertSameSummary(getSingleMethod(c, "t4"), List(ICONST_3, "boxToInteger", ARETURN)) - assertEquals(getSingleMethod(c, "t5").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + val c = compileClass(code) + assertNoInvoke(getMethod(c, "t1")) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_3, IADD, IRETURN)) + assertSameSummary(getMethod(c, "t3"), List(ICONST_3, ICONST_4, IADD, IRETURN)) + assertSameSummary(getMethod(c, "t4"), List(ICONST_3, "boxToInteger", ARETURN)) + assertEquals(getInstructions(c, "t5") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("scala/runtime/BoxesRunTime", "boxToInteger"), ("scala/runtime/BoxesRunTime", "boxToInteger"), ("C", "tpl"), ("scala/Tuple2", "_1$mcI$sp"))) - assertSameSummary(getSingleMethod(c, "t6"), List(ICONST_1, ICONST_2, ISUB, IRETURN)) - assertSameSummary(getSingleMethod(c, "t7"), List( + assertSameSummary(getMethod(c, "t6"), List(ICONST_1, ICONST_2, ISUB, IRETURN)) + assertSameSummary(getMethod(c, "t7"), List( ICONST_1, ICONST_2, ISTORE, ISTORE, ICONST_3, ISTORE, ILOAD, ILOAD, IADD, ILOAD, IADD, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t8")) - assertNoInvoke(getSingleMethod(c, "t9")) + assertNoInvoke(getMethod(c, "t8")) + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -524,14 +522,14 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertSameSummary(getSingleMethod(c, "t1"), List(NEW, DUP, "<init>", ARETURN)) - assertSameCode(getSingleMethod(c, "t2"), List(Op(LCONST_0), Op(LRETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(Op(ICONST_1), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t4"), List(Op(ICONST_1), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t5"), List(Op(DCONST_0), Op(DRETURN))) - assertSameCode(getSingleMethod(c, "t6"), List(Op(ACONST_NULL), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t7"), List(Op(ICONST_0), Op(IRETURN))) + val c = compileClass(code) + assertSameSummary(getMethod(c, "t1"), List(NEW, DUP, "<init>", ARETURN)) + assertSameCode(getMethod(c, "t2"), List(Op(LCONST_0), Op(LRETURN))) + assertSameCode(getMethod(c, "t3"), List(Op(ICONST_1), Op(IRETURN))) + assertSameCode(getMethod(c, "t4"), List(Op(ICONST_1), Op(IRETURN))) + assertSameCode(getMethod(c, "t5"), List(Op(DCONST_0), Op(DRETURN))) + assertSameCode(getMethod(c, "t6"), List(Op(ACONST_NULL), Op(ARETURN))) + assertSameCode(getMethod(c, "t7"), List(Op(ICONST_0), Op(IRETURN))) } @Test @@ -544,9 +542,9 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val c = compileClass(code) assertSameCode( - getSingleMethod(c, "t"), List( + getMethod(c, "t"), List( VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN))) } @@ -615,28 +613,28 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) + val c = compileClass(code) + def stores(m: String) = getInstructions(c, m).filter(_.opcode == ASTORE) assertEquals(locals(c, "t1"), List(("this",0), ("kept1",1), ("result",2))) assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t1"))) + textify(getAsmMethod(c, "t1"))) assertEquals(locals(c, "t2"), List(("this",0), ("kept2",1), ("kept3",2))) assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t2"))) + textify(getAsmMethod(c, "t2"))) assertEquals(locals(c, "t3"), List(("this",0), ("kept4",1))) assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t3"))) + textify(getAsmMethod(c, "t3"))) assertEquals(locals(c, "t4"), List(("this",0), ("kept5",1))) assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t4"))) + textify(getAsmMethod(c, "t4"))) assertEquals(locals(c, "t5"), List(("this",0), ("kept6",1))) assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t5"))) + textify(getAsmMethod(c, "t5"))) } @Test @@ -683,13 +681,13 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val c = compileClass(code) assertEquals(locals(c, "t1"), List(("this", 0), ("x", 1))) assertEquals(locals(c, "t2"), List(("this", 0), ("x", 1))) // we don't have constant propagation (yet). // the local var can't be optimized as a store;laod sequence, there's a GETSTATIC between the two - assertSameSummary(getSingleMethod(c, "t2"), List( + assertSameSummary(getMethod(c, "t2"), List( ICONST_2, ISTORE, GETSTATIC, ILOAD, "boxToInteger", "println", RETURN)) assertEquals(locals(c, "t3"), List(("this", 0))) @@ -711,8 +709,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - val t = getSingleMethod(c, "t") + val c = compileClass(code) + val t = getMethod(c, "t") assertEquals(t.handlers, Nil) assertEquals(locals(c, "t"), List(("this", 0))) assertSameSummary(t, List(GETSTATIC, LDC, "print", -1, GOTO)) @@ -729,8 +727,8 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) - assertNoInvoke(getSingleMethod(c, "compare")) + val c = compileClass(code) + assertNoInvoke(getMethod(c, "compare")) } @Test @@ -743,9 +741,9 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val c = compileClass(code) - assertSameSummary(getSingleMethod(c, "t"), List( + assertSameSummary(getMethod(c, "t"), List( BIPUSH, ILOAD, IF_ICMPNE, BIPUSH, ILOAD, IF_ICMPNE, LDC, ASTORE, GOTO, diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala index 6cb3fd3bba..5bd285f97f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala @@ -2,23 +2,20 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import CodeGenTools._ -import scala.tools.asm.tree.ClassNode -import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InlineInfo} -import scala.tools.partest.ASMConverters -import ASMConverters._ import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.tree.ClassNode +import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo} +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class ScalaInlineInfoTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) +class ScalaInlineInfoTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ def inlineInfo(c: ClassNode): InlineInfo = c.attrs.asScala.collect({ case a: InlineInfoAttribute => a.inlineInfo }).head @@ -72,7 +69,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { |} """.stripMargin - val cs @ List(c, t, tl, to) = compileClasses(compiler)(code) + val cs @ List(c, t, tl, to) = compileClasses(code) val infoT = inlineInfo(t) val expectT = InlineInfo ( false, // final class @@ -149,7 +146,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { | def nullary: Int |} """.stripMargin - val cs = compileClasses(compiler)(code) + val cs = compileClasses(code) val sams = cs.map(c => (c.name, inlineInfo(c).sam)) assertEquals(sams, List( @@ -165,7 +162,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { @Test def lzyComputeInlineInfo(): Unit = { val code = "class C { object O }" - val List(c, om) = compileClasses(compiler)(code) + val List(c, om) = compileClasses(code) val infoC = inlineInfo(c) val expected = Map( "<init>()V" -> MethodInlineInfo(false,false,false), diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala index 99acb318de..992a0e541b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -2,15 +2,15 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.asm.Opcodes._ import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class SimplifyJumpsTest { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index 46f06d1d39..63bbcc396b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -2,17 +2,15 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ import scala.tools.testing.AssertUtil._ - -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) @@ -20,12 +18,12 @@ class UnreachableCodeTest extends ClearAfterClass { // jvm-1.6 enables emitting stack map frames, which impacts the code generation wrt dead basic blocks, // see comment in BCodeBodyBuilder val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:method")) - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) - val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) + val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) def assertEliminateDead(code: (Instruction, Boolean)*): Unit = { val method = genMethod()(code.map(_._1): _*) - dceCompiler.genBCode.bTypes.localOpt.removeUnreachableCodeImpl(method, "C") + dceCompiler.global.genBCode.bTypes.localOpt.removeUnreachableCodeImpl(method, "C") val nonEliminated = instructionsFromMethod(method) val expectedLive = code.filter(_._2).map(_._1).toList assertSameCode(nonEliminated, expectedLive) @@ -112,10 +110,10 @@ class UnreachableCodeTest extends ClearAfterClass { @Test def basicEliminationCompiler(): Unit = { val code = "def f: Int = { return 1; 2 }" - val withDce = singleMethodInstructions(dceCompiler)(code) + val withDce = dceCompiler.compileInstructions(code) assertSameCode(withDce.dropNonOp, List(Op(ICONST_1), Op(IRETURN))) - val noDce = singleMethodInstructions(noOptCompiler)(code) + val noDce = noOptCompiler.compileInstructions(code) // The emitted code is ICONST_1, IRETURN, ICONST_2, IRETURN. The latter two are dead. // @@ -141,23 +139,23 @@ class UnreachableCodeTest extends ClearAfterClass { def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) val code = "def f: Int = { return 0; try { 1 } catch { case _: Exception => 2 } }" - val m = singleMethod(dceCompiler)(code) + val m = dceCompiler.compileMethod(code) assertTrue(m.handlers.isEmpty) // redundant (if code is gone, handler is gone), but done once here for extra safety assertSameCode(m.instructions, wrapInDefault(Op(ICONST_0), Op(IRETURN))) val code2 = "def f: Unit = { try { } catch { case _: Exception => () }; () }" // requires fixpoint optimization of methodOptCompiler (dce alone is not enough): first the handler is eliminated, then it's dead catch block. - assertSameCode(singleMethodInstructions(methodOptCompiler)(code2), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code2), wrapInDefault(Op(RETURN))) val code3 = "def f: Unit = { try { } catch { case _: Exception => try { } catch { case _: Exception => () } }; () }" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code3), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code3), wrapInDefault(Op(RETURN))) // this example requires two iterations to get rid of the outer handler. // the first iteration of DCE cannot remove the inner handler. then the inner (empty) handler is removed. // then the second iteration of DCE removes the inner catch block, and then the outer handler is removed. val code4 = "def f: Unit = { try { try { } catch { case _: Exception => () } } catch { case _: Exception => () }; () }" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code4), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code4), wrapInDefault(Op(RETURN))) } @Test // test the dce-testing tools @@ -174,7 +172,7 @@ class UnreachableCodeTest extends ClearAfterClass { } @Test - def bytecodeEquivalence: Unit = { + def bytecodeEquivalence(): Unit = { assertTrue(List(VarOp(ILOAD, 1)) === List(VarOp(ILOAD, 2))) assertTrue(List(VarOp(ILOAD, 1), VarOp(ISTORE, 1)) === @@ -216,35 +214,35 @@ class UnreachableCodeTest extends ClearAfterClass { | def t4 = cons(nt) |} """.stripMargin - val List(c) = compileClasses(noOptCompiler)(code) + val c = noOptCompiler.compileClass(code) - assertSameSummary(getSingleMethod(c, "nl"), List(ACONST_NULL, ARETURN)) + assertSameSummary(getMethod(c, "nl"), List(ACONST_NULL, ARETURN)) - assertSameSummary(getSingleMethod(c, "nt"), List( + assertSameSummary(getMethod(c, "nt"), List( NEW, DUP, LDC, "<init>", ATHROW)) - assertSameSummary(getSingleMethod(c, "t1"), List( + assertSameSummary(getMethod(c, "t1"), List( ALOAD, ACONST_NULL, "cons", RETURN)) // GenBCode introduces POP; ACONST_NULL after loading an expression of type scala.runtime.Null$, // see comment in BCodeBodyBuilder.adapt - assertSameSummary(getSingleMethod(c, "t2"), List( + assertSameSummary(getMethod(c, "t2"), List( ALOAD, ALOAD, "nl", POP, ACONST_NULL, "cons", RETURN)) // the bytecode generated by GenBCode is ... ATHROW; INVOKEVIRTUAL C.cons; RETURN // the ASM classfile writer creates a new basic block (creates a label) right after the ATHROW // and replaces all instructions by NOP*; ATHROW, see comment in BCodeBodyBuilder.adapt // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below) - assertSameSummary(getSingleMethod(c, "t3"), List( + assertSameSummary(getMethod(c, "t3"), List( ALOAD, NEW, DUP, LDC, "<init>", ATHROW, NOP, NOP, NOP, ATHROW)) // GenBCode introduces an ATHROW after the invocation of C.nt, see BCodeBodyBuilder.adapt // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below) - assertSameSummary(getSingleMethod(c, "t4"), List( + assertSameSummary(getMethod(c, "t4"), List( ALOAD, ALOAD, "nt", ATHROW, NOP, NOP, NOP, ATHROW)) - val List(cDCE) = compileClasses(dceCompiler)(code) - assertSameSummary(getSingleMethod(cDCE, "t3"), List(ALOAD, NEW, DUP, LDC, "<init>", ATHROW)) - assertSameSummary(getSingleMethod(cDCE, "t4"), List(ALOAD, ALOAD, "nt", ATHROW)) + val cDCE = dceCompiler.compileClass(code) + assertSameSummary(getMethod(cDCE, "t3"), List(ALOAD, NEW, DUP, LDC, "<init>", ATHROW)) + assertSameSummary(getMethod(cDCE, "t4"), List(ALOAD, ALOAD, "nt", ATHROW)) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala index 77e73e64b9..c9c98b403b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala @@ -2,21 +2,20 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.collection.JavaConverters._ -import CodeGenTools._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.collection.JavaConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class UnusedLocalVariablesTest extends ClearAfterClass { - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) +class UnusedLocalVariablesTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:unreachable-code" + import compiler._ @Test def removeUnusedVar(): Unit = { @@ -49,7 +48,7 @@ class UnusedLocalVariablesTest extends ClearAfterClass { | } |} |""".stripMargin - val cls = compileClasses(dceCompiler)(code).head + val cls = compileClass(code) val m = convertMethod(cls.methods.asScala.toList.find(_.desc == "(I)V").get) assertTrue(m.localVars.length == 2) // this, a, but not y @@ -70,19 +69,14 @@ class UnusedLocalVariablesTest extends ClearAfterClass { |} """.stripMargin - val clss2 = compileClasses(dceCompiler)(code2) - val cls2 = clss2.find(_.name == "C").get - val companion2 = clss2.find(_.name == "C$").get - - val clsConstr = convertMethod(cls2.methods.asScala.toList.find(_.name == "<init>").get) - val companionConstr = convertMethod(companion2.methods.asScala.toList.find(_.name == "<init>").get) + val List(cls2, companion2) = compileClasses(code2) - assertTrue(clsConstr.localVars.length == 1) // this - assertTrue(companionConstr.localVars.length == 1) // this + assertTrue(getMethod(cls2, "<init>").localVars.length == 1) // this + assertTrue(getMethod(companion2, "<init>").localVars.length == 1) // this } def assertLocalVarCount(code: String, numVars: Int): Unit = { - assertTrue(singleMethod(dceCompiler)(code).localVars.length == numVars) + assertTrue(compileMethod(code).localVars.length == numVars) } } |