diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-07-03 08:25:30 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-07-23 15:02:17 +0200 |
commit | 404e86239e445307fdff4fb0cb4e512993ac56b8 (patch) | |
tree | f8e31ac3c3a29e14b50a71d3bcde3fab12cc3d08 /test | |
parent | 1b0703e74d22ed54b95a134216835569a20d2325 (diff) | |
download | scala-404e86239e445307fdff4fb0cb4e512993ac56b8.tar.gz scala-404e86239e445307fdff4fb0cb4e512993ac56b8.tar.bz2 scala-404e86239e445307fdff4fb0cb4e512993ac56b8.zip |
[backport] 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')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala | 42 |
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") + } } |