diff options
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.scala | 34 |
1 files changed, 31 insertions, 3 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 40f91cbed4..594fd8923c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala @@ -57,8 +57,20 @@ import scala.collection.convert.decorateAsScala._ * copying operations. */ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName) { + + /* Timers for benchmarking ProdCons + import scala.reflect.internal.util.Statistics._ + import ProdConsAnalyzer._ + val analyzerTimer = newSubTimer(classInternalName + "#" + methodNode.name + " - analysis", prodConsAnalyzerTimer) + val consumersTimer = newSubTimer(classInternalName + "#" + methodNode.name + " - consumers", prodConsAnalyzerTimer) + */ + val analyzer = new Analyzer(new InitialProducerSourceInterpreter) + +// val start = analyzerTimer.start() analyzer.analyze(classInternalName, methodNode) +// analyzerTimer.stop(start) +// println(analyzerTimer.line) def frameAt(insn: AbstractInsnNode) = analyzer.frameAt(insn, methodNode) @@ -103,7 +115,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 +137,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) @@ -384,6 +404,7 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName) /** For each instruction, a set of potential consumers of the produced values. */ private lazy val _consumersOfOutputsFrom: Map[AbstractInsnNode, Vector[Set[AbstractInsnNode]]] = { +// val start = consumersTimer.start() var res = Map.empty[AbstractInsnNode, Vector[Set[AbstractInsnNode]]] for { insn <- methodNode.instructions.iterator.asScala @@ -396,6 +417,8 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName) val outputIndex = producedSlots.indexOf(i) res = res.updated(producer, currentConsumers.updated(outputIndex, currentConsumers(outputIndex) + insn)) } +// consumersTimer.stop(start) +// println(consumersTimer.line) res } @@ -403,6 +426,11 @@ class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName) private val _ultimateConsumersCache: mutable.AnyRefMap[(AbstractInsnNode, Int), Set[AbstractInsnNode]] = mutable.AnyRefMap.empty } +object ProdConsAnalyzer { + import scala.reflect.internal.util.Statistics._ + val prodConsAnalyzerTimer = newTimer("Time in ProdConsAnalyzer", "jvm") +} + /** * A class for pseudo-instructions representing the initial producers of local values that have * no producer instruction in the method: @@ -447,4 +475,4 @@ class InitialProducerSourceInterpreter extends SourceInterpreter { override def newExceptionValue(tryCatchBlockNode: TryCatchBlockNode, handlerFrame: Frame[_ <: Value], exceptionType: Type): SourceValue = { new SourceValue(1, ExceptionProducer(handlerFrame)) } -}
\ No newline at end of file +} |