summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.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 /src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.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 'src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
index ad75363102..5d56861ffc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
@@ -103,7 +103,11 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName)
def initialProducersForValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
def initialProducers(insn: AbstractInsnNode, producedSlot: Int): Set[AbstractInsnNode] = {
if (isCopyOperation(insn)) {
- _initialProducersCache.getOrElseUpdate((insn, producedSlot), {
+ val key = (insn, producedSlot)
+ _initialProducersCache.getOrElseUpdate(key, {
+ // prevent infinite recursion if an instruction is its own producer or consumer
+ // see cyclicProdCons in ProdConsAnalyzerTest
+ _initialProducersCache(key) = Set.empty
val (sourceValue, sourceValueSlot) = copyOperationSourceValue(insn, producedSlot)
sourceValue.insns.iterator.asScala.flatMap(initialProducers(_, sourceValueSlot)).toSet
})
@@ -121,7 +125,11 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName)
def ultimateConsumersOfValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
def ultimateConsumers(insn: AbstractInsnNode, consumedSlot: Int): Set[AbstractInsnNode] = {
if (isCopyOperation(insn)) {
- _ultimateConsumersCache.getOrElseUpdate((insn, consumedSlot), {
+ val key = (insn, consumedSlot)
+ _ultimateConsumersCache.getOrElseUpdate(key, {
+ // prevent infinite recursion if an instruction is its own producer or consumer
+ // see cyclicProdCons in ProdConsAnalyzerTest
+ _ultimateConsumersCache(key) = Set.empty
for {
producedSlot <- copyOperationProducedValueSlots(insn, consumedSlot)
consumer <- consumersOfValueAt(insn.getNext, producedSlot)