summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-10-02 12:27:43 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-10-20 11:17:04 +0200
commit0a33c421767f6e4587f8adac19169f184d845548 (patch)
tree9a6de2618f81a5324e642865d6655d77f9f83c59 /test
parent5bca4b2fca92dfe1f89785ba8d80cb9599d747f6 (diff)
downloadscala-0a33c421767f6e4587f8adac19169f184d845548.tar.gz
scala-0a33c421767f6e4587f8adac19169f184d845548.tar.bz2
scala-0a33c421767f6e4587f8adac19169f184d845548.zip
Simplify post inlining requests
Clean up inliner test
Diffstat (limited to 'test')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala3
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala13
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala152
3 files changed, 40 insertions, 128 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index 769236ae49..1f2ec274d3 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -169,6 +169,9 @@ object CodeGenTools {
def getSingleMethod(classNode: ClassNode, name: String): Method =
convertMethod(classNode.methods.asScala.toList.find(_.name == name).get)
+ def findAsmMethods(c: ClassNode, p: String => Boolean) = c.methods.iterator.asScala.filter(m => p(m.name)).toList.sortBy(_.name)
+ def findAsmMethod(c: ClassNode, name: String) = findAsmMethods(c, _ == name).head
+
/**
* Instructions that match `query` when textified.
* If `query` starts with a `+`, the next instruction is returned.
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 efd88f10c3..f329a43b30 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala
@@ -50,9 +50,6 @@ class CallGraphTest extends ClearAfterClass {
compileClasses(compiler)(code, allowMessage = allowMessage).map(c => byteCodeRepository.classNode(c.name).get)
}
- def getMethods(c: ClassNode, p: String => Boolean) = c.methods.iterator.asScala.filter(m => p(m.name)).toList.sortBy(_.name)
- def getMethod(c: ClassNode, name: String) = getMethods(c, _ == name).head
-
def callsInMethod(methodNode: MethodNode): List[MethodInsnNode] = methodNode.instructions.iterator.asScala.collect({
case call: MethodInsnNode => call
}).toList
@@ -121,10 +118,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) = getMethods(cCls, _.startsWith("f"))
- val List(df1, df3) = getMethods(dCls, _.startsWith("f"))
- val g1 = getMethod(cMod, "g1")
- val List(t1, t2) = getMethods(testCls, _.startsWith("t"))
+ 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(cf1Call, cf2Call, cf3Call, cf4Call, cf5Call, cf6Call, cf7Call, cg1Call) = callsInMethod(t1)
val List(df1Call, df2Call, df3Call, df4Call, df5Call, df6Call, df7Call, dg1Call) = callsInMethod(t2)
@@ -160,7 +157,7 @@ class CallGraphTest extends ClearAfterClass {
|}
""".stripMargin
val List(c) = compile(code)
- val m = getMethod(c, "m")
+ val m = findAsmMethod(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/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
index 81c6dd2ce2..cdba4073f2 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -6,17 +6,11 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
import scala.collection.generic.Clearable
-import scala.collection.immutable.IntMap
-import scala.collection.mutable.ListBuffer
-import scala.reflect.internal.util.{NoPosition, 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
@@ -69,6 +63,7 @@ class InlinerTest extends ClearAfterClass {
val compiler = InlinerTest.compiler
import compiler.genBCode.bTypes._
import compiler.genBCode.bTypes.backendUtils._
+ import inlinerHeuristics._
def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = {
InlinerTest.notPerRun.foreach(_.clear())
@@ -88,55 +83,27 @@ class InlinerTest extends ClearAfterClass {
assert(callsite.callee.get.callee == callee, callsite.callee.get.callee.name)
}
- def makeInlineRequest( callsiteInstruction: MethodInsnNode, callsiteMethod: MethodNode, callsiteClass: ClassBType,
- callee: MethodNode, calleeDeclarationClass: ClassBType,
- callsiteStackHeight: Int, receiverKnownNotNull: Boolean,
- post: List[inlinerHeuristics.PostInlineRequest] = Nil) = inlinerHeuristics.InlineRequest(
- callsite = callGraph.Callsite(
- callsiteInstruction = callsiteInstruction,
- callsiteMethod = callsiteMethod,
- callsiteClass = callsiteClass,
- callee = Right(callGraph.Callee(callee = callee, calleeDeclarationClass = calleeDeclarationClass, safeToInline = true, safeToRewrite = false, annotatedInline = false, annotatedNoInline = false, samParamTypes = IntMap.empty, calleeInfoWarning = None)),
- argInfos = IntMap.empty,
- callsiteStackHeight = callsiteStackHeight,
- receiverKnownNotNull = receiverKnownNotNull,
- callsitePosition = NoPosition),
- post = post)
-
- def inlineRequest(code: String, mod: ClassNode => Unit = _ => ()): (inlinerHeuristics.InlineRequest, MethodNode) = {
- val List(cls) = compile(code)
- mod(cls)
- val clsBType = classBTypeFromParsedClassfile(cls.name)
-
- 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()
-
- val analyzer = new AsmAnalyzer(g, clsBType.internalName)
-
- val request = makeInlineRequest(
- callsiteInstruction = fCall,
- callsiteMethod = g,
- callsiteClass = clsBType,
- callee = f,
- calleeDeclarationClass = clsBType,
- callsiteStackHeight = analyzer.frameAt(fCall).getStackSize,
- receiverKnownNotNull = true
- )
- (request, g)
- }
+ def getCallsite(method: MethodNode, calleeName: String) = callGraph.callsites(method).valuesIterator.find(_.callee.get.callee.name == calleeName).get
- // inline first invocation of f into g in class C
- def inlineTest(code: String, mod: ClassNode => Unit = _ => ()): MethodNode = {
- val (request, g) = inlineRequest(code, mod)
- inliner.inline(request)
- g
+ def gMethAndFCallsite(code: String, mod: ClassNode => Unit = _ => ()) = {
+ val List(c) = compile(code)
+ mod(c)
+ val gMethod = findAsmMethod(c, "g")
+ val fCall = getCallsite(gMethod, "f")
+ (gMethod, fCall)
}
def canInlineTest(code: String, mod: ClassNode => Unit = _ => ()): Option[OptimizerWarning] = {
- val cs = inlineRequest(code, mod)._1.callsite
+ val cs = gMethAndFCallsite(code, mod)._2
inliner.earlyCanInlineCheck(cs) orElse inliner.canInlineBody(cs)
}
+ def inlineTest(code: String, mod: ClassNode => Unit = _ => ()): MethodNode = {
+ val (gMethod, fCall) = gMethAndFCallsite(code, mod)
+ inliner.inline(InlineRequest(fCall, Nil))
+ gMethod
+ }
+
@Test
def simpleInlineOK(): Unit = {
val code =
@@ -251,29 +218,9 @@ class InlinerTest extends ClearAfterClass {
""".stripMargin
val List(c, d) = compile(code)
-
- val cTp = classBTypeFromParsedClassfile(c.name)
- val dTp = classBTypeFromParsedClassfile(d.name)
-
- val g = c.methods.asScala.find(_.name == "g").get
- val h = d.methods.asScala.find(_.name == "h").get
- val gCall = h.instructions.iterator.asScala.collect({
- case m: MethodInsnNode if m.name == "g" => m
- }).next()
-
- val analyzer = new AsmAnalyzer(h, dTp.internalName)
-
- val request = makeInlineRequest(
- callsiteInstruction = gCall,
- callsiteMethod = h,
- callsiteClass = dTp,
- callee = g,
- calleeDeclarationClass = cTp,
- callsiteStackHeight = analyzer.frameAt(gCall).getStackSize,
- receiverKnownNotNull = true
- )
-
- val r = inliner.canInlineBody(request.callsite)
+ val hMeth = findAsmMethod(d, "h")
+ val gCall = getCallsite(hMeth, "g")
+ val r = inliner.canInlineBody(gCall)
assert(r.nonEmpty && r.get.isInstanceOf[IllegalAccessInstruction], r)
}
@@ -411,28 +358,14 @@ class InlinerTest extends ClearAfterClass {
""".stripMargin
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 analyzer = new AsmAnalyzer(f, clsBType.internalName)
-
- val integerClassBType = classBTypeFromInternalName("java/lang/Integer")
- val lowestOneBitMethod = byteCodeRepository.methodNode(integerClassBType.internalName, "lowestOneBit", "(I)I").get._1
-
- val request = makeInlineRequest(
- callsiteInstruction = callsiteIns,
- callsiteMethod = f,
- callsiteClass = clsBType,
- callee = lowestOneBitMethod,
- calleeDeclarationClass = integerClassBType,
- callsiteStackHeight = analyzer.frameAt(callsiteIns).getStackSize,
- receiverKnownNotNull = false
- )
-
- val warning = inliner.canInlineBody(request.callsite)
+ val fMeth = findAsmMethod(c, "f")
+ val call = getCallsite(fMeth, "lowestOneBit")
+
+ val warning = inliner.canInlineBody(call)
assert(warning.isEmpty, warning)
- inliner.inline(request)
- val ins = instructionsFromMethod(f)
+
+ inliner.inline(InlineRequest(call, Nil))
+ val ins = instructionsFromMethod(fMeth)
// no invocations, lowestOneBit is inlined
assertNoInvoke(ins)
@@ -1078,36 +1011,15 @@ class InlinerTest extends ClearAfterClass {
""".stripMargin
val List(c) = compile(code)
+ val hMeth = findAsmMethod(c, "h")
+ val gMeth = findAsmMethod(c, "g")
+ val gCall = getCallsite(hMeth, "g")
+ val fCall = getCallsite(gMeth, "f")
- val cTp = classBTypeFromParsedClassfile(c.name)
-
- val f = c.methods.asScala.find(_.name == "f").get
- val g = c.methods.asScala.find(_.name == "g").get
- val h = c.methods.asScala.find(_.name == "h").get
-
- val gCall = h.instructions.iterator.asScala.collect({
- case m: MethodInsnNode if m.name == "g" => m
- }).next()
- val fCall = g.instructions.iterator.asScala.collect({
- case m: MethodInsnNode if m.name == "f" => m
- }).next()
-
- val analyzer = new AsmAnalyzer(h, cTp.internalName)
-
- val request = makeInlineRequest(
- callsiteInstruction = gCall,
- callsiteMethod = h,
- callsiteClass = cTp,
- callee = g,
- calleeDeclarationClass = cTp,
- callsiteStackHeight = analyzer.frameAt(gCall).getStackSize,
- receiverKnownNotNull = false,
- post = List(inlinerHeuristics.PostInlineRequest(fCall, Nil))
- )
-
- val warning = inliner.canInlineBody(request.callsite)
+ val warning = inliner.canInlineBody(gCall)
assert(warning.isEmpty, warning)
- inliner.inline(request)
+
+ inliner.inline(InlineRequest(gCall, List(InlineRequest(fCall, Nil))))
assertNoInvoke(getSingleMethod(c, "h")) // no invoke in h: first g is inlined, then the inlined call to f is also inlined
assertInvoke(getSingleMethod(c, "g"), "C", "f") // g itself still has the call to f
}