[JVM] Split mergeControlFlowEdge into full and fast versions

This is needed because for `FastStackAnalyzer` we actually
will use only `fast` version, that can potentially improve overall
performance.
This commit is contained in:
Ivan Kylchik
2023-09-19 13:22:40 +02:00
committed by Space Team
parent 07c7792693
commit 96a2da4906
@@ -209,12 +209,20 @@ abstract class FastAnalyzer<V : Value, F : Frame<V>>(
} }
} }
private fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false) {
if (useFastMergeControlFlowEdge) {
fastMergeControlFlowEdge(dest, frame, canReuse)
} else {
fullMergeControlFlowEdge(dest, frame, canReuse)
}
}
/** /**
* Updates frame at the index [dest] with its old value if provided and previous control flow node frame [frame]. * Updates frame at the index [dest] with its old value if provided and previous control flow node frame [frame].
* Reuses old frame when possible and when [canReuse] is true. * Reuses old frame when possible and when [canReuse] is true.
* If updated, adds the frame to the queue * If updated, adds the frame to the queue
*/ */
private fun mergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false) { private fun fullMergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean = false) {
val oldFrame = frames[dest] val oldFrame = frames[dest]
val changes = when { val changes = when {
canReuse && !isMergeNode[dest] -> { canReuse && !isMergeNode[dest] -> {
@@ -229,12 +237,26 @@ abstract class FastAnalyzer<V : Value, F : Frame<V>>(
oldFrame.init(frame) oldFrame.init(frame)
true true
} }
!useFastMergeControlFlowEdge -> else -> try {
try { oldFrame.merge(frame, interpreter)
oldFrame.merge(frame, interpreter) } catch (e: AnalyzerException) {
} catch (e: AnalyzerException) { throw AnalyzerException(null, "${e.message}\nframe: ${frame.dump()}\noldFrame: ${oldFrame.dump()}")
throw AnalyzerException(null, "${e.message}\nframe: ${frame.dump()}\noldFrame: ${oldFrame.dump()}") }
}
updateQueue(changes, dest)
}
private fun fastMergeControlFlowEdge(dest: Int, frame: F, canReuse: Boolean) {
val oldFrame = frames[dest]
val changes = when {
oldFrame == null -> {
frames[dest] = if (canReuse && !isMergeNode[dest]) {
frame
} else {
newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
} }
true
}
else -> false else -> false
} }
updateQueue(changes, dest) updateQueue(changes, dest)