summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-07-03 08:25:30 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-07-03 10:45:02 +0200
commit0f3505421cd49d20d948808248266998dfc36867 (patch)
treeaabd326d8306e95470217d61a18e75717d329e46 /test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
parent055a373802a34ee09fc0ed20b2b25c3fa20507d4 (diff)
downloadscala-0f3505421cd49d20d948808248266998dfc36867.tar.gz
scala-0f3505421cd49d20d948808248266998dfc36867.tar.bz2
scala-0f3505421cd49d20d948808248266998dfc36867.zip
Prevent infinite recursion in ProdConsAnalyzer
When an instruction is its own producer or consumer, the `initialProducer` / `ultimateConsumer` methods would loop. While loops or @tailrec annotated methods can generate such bytecode.
Diffstat (limited to 'test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala42
1 files changed, 42 insertions, 0 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
index 9af9ef54fc..a5b3faced8 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
@@ -246,4 +246,46 @@ class ProdConsAnalyzerTest extends ClearAfterClass {
testSingleInsn(a.consumersOfOutputsFrom(l2i), "IRETURN")
testSingleInsn(a.producersForInputsOf(ret), "L2I")
}
+
+ @Test
+ def cyclicProdCons(): Unit = {
+ import Opcodes._
+ val m = genMethod(descriptor = "(I)I")(
+ Label(1),
+ VarOp(ILOAD, 1),
+ IntOp(BIPUSH, 10),
+ Op(IADD), // consumer of the above ILOAD
+
+ Op(ICONST_0),
+ Jump(IF_ICMPNE, Label(2)),
+
+ VarOp(ILOAD, 1),
+ VarOp(ISTORE, 1),
+ Jump(GOTO, Label(1)),
+
+ Label(2),
+ IntOp(BIPUSH, 9),
+ Op(IRETURN)
+ )
+ m.maxLocals = 2
+ m.maxStack = 2
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(iadd) = findInstr(m, "IADD")
+ val firstLoad = iadd.getPrevious.getPrevious
+ assert(firstLoad.getOpcode == ILOAD)
+ val secondLoad = findInstr(m, "ISTORE").head.getPrevious
+ assert(secondLoad.getOpcode == ILOAD)
+
+ testSingleInsn(a.producersForValueAt(iadd, 2), "ILOAD")
+ testSingleInsn(a.initialProducersForValueAt(iadd, 2), "ParameterProducer(1)")
+ testMultiInsns(a.producersForInputsOf(firstLoad), List("ParameterProducer", "ISTORE"))
+ testMultiInsns(a.producersForInputsOf(secondLoad), List("ParameterProducer", "ISTORE"))
+
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(firstLoad), "IADD")
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(secondLoad), "IADD")
+
+ testSingleInsn(a.consumersOfOutputsFrom(firstLoad), "IADD")
+ testSingleInsn(a.consumersOfOutputsFrom(secondLoad), "ISTORE")
+ }
}