Skip to content

Commit c9b97df

Browse files
retronymisaacl
authored andcommitted
Avoid performance problem after ASM upgrade in prod/cons analysis
ASM 6.2 now creates a new Frame inside the loop in which `newExceptionValue` is called. We were including this frame in the case-class equality of the pseudo-instruction, `ExceptionProducer`, and upon receiving new instances each time the `ProdCons` analysis massively slowed down. This commit just captures the data we need: the stack top of the handler frame.
1 parent eee8374 commit c9b97df

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ trait ProdConsAnalyzerImpl {
9494
}
9595

9696
def consumersOfOutputsFrom(insn: AbstractInsnNode): Set[AbstractInsnNode] = insn match {
97-
case _: UninitializedLocalProducer => Set.empty
98-
case ParameterProducer(local) => consumersOfValueAt(methodNode.instructions.getFirst, local)
99-
case ExceptionProducer(handlerLabel, handlerFrame) => consumersOfValueAt(handlerLabel, handlerFrame.stackTop)
97+
case _: UninitializedLocalProducer => Set.empty
98+
case ParameterProducer(local) => consumersOfValueAt(methodNode.instructions.getFirst, local)
99+
case ExceptionProducer(handlerLabel, handlerStackTop) => consumersOfValueAt(handlerLabel, handlerStackTop)
100100
case _ =>
101101
_consumersOfOutputsFrom.get(insn).map(v => Set.from[AbstractInsnNode](v.indices.iterator.flatMap(v.apply))).getOrElse(Set.empty)
102102
}
@@ -388,7 +388,7 @@ trait ProdConsAnalyzerImpl {
388388
private def outputValueSlots(insn: AbstractInsnNode): Seq[Int] = insn match {
389389
case ParameterProducer(local) => Seq(local)
390390
case UninitializedLocalProducer(local) => Seq(local)
391-
case ExceptionProducer(_, frame) => Seq(frame.stackTop)
391+
case ExceptionProducer(_, stackTop) => Seq(stackTop)
392392
case _ =>
393393
if (insn.getOpcode == -1) return Seq.empty
394394
if (isStore(insn)) {
@@ -453,9 +453,9 @@ abstract class InitialProducer extends AbstractInsnNode(-1) {
453453
override def accept(cv: MethodVisitor): Unit = throw new UnsupportedOperationException
454454
}
455455

456-
case class ParameterProducer(local: Int) extends InitialProducer
457-
case class UninitializedLocalProducer(local: Int) extends InitialProducer
458-
case class ExceptionProducer[V <: Value](handlerLabel: LabelNode, handlerFrame: Frame[V]) extends InitialProducer
456+
case class ParameterProducer(local: Int) extends InitialProducer
457+
case class UninitializedLocalProducer(local: Int) extends InitialProducer
458+
case class ExceptionProducer[V <: Value](handlerLabel: LabelNode, handlerStackTop: Int) extends InitialProducer
459459

460460
class InitialProducerSourceInterpreter extends SourceInterpreter {
461461
override def newParameterValue(isInstanceMethod: Boolean, local: Int, tp: Type): SourceValue = {
@@ -467,6 +467,7 @@ class InitialProducerSourceInterpreter extends SourceInterpreter {
467467
}
468468

469469
override def newExceptionValue(tryCatchBlockNode: TryCatchBlockNode, handlerFrame: Frame[_ <: Value], exceptionType: Type): SourceValue = {
470-
new SourceValue(1, ExceptionProducer(tryCatchBlockNode.handler, handlerFrame))
470+
val handlerStackTop = handlerFrame.stackTop + 1 // +1 because this value is about to be pushed onto `handlerFrame`.
471+
new SourceValue(1, ExceptionProducer(tryCatchBlockNode.handler, handlerStackTop))
471472
}
472473
}

0 commit comments

Comments
 (0)