summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
diff options
context:
space:
mode:
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.scala38
1 files changed, 33 insertions, 5 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..1c24acba03 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:
@@ -431,9 +459,9 @@ abstract class InitialProducer extends AbstractInsnNode(-1) {
override def accept(cv: MethodVisitor): Unit = throw new UnsupportedOperationException
}
-case class ParameterProducer(local: Int) extends InitialProducer
-case class UninitializedLocalProducer(local: Int) extends InitialProducer
-case class ExceptionProducer(handlerFrame: Frame[_ <: Value]) extends InitialProducer
+case class ParameterProducer(local: Int) extends InitialProducer
+case class UninitializedLocalProducer(local: Int) extends InitialProducer
+case class ExceptionProducer[V <: Value](handlerFrame: Frame[V]) extends InitialProducer
class InitialProducerSourceInterpreter extends SourceInterpreter {
override def newParameterValue(isInstanceMethod: Boolean, local: Int, tp: Type): SourceValue = {