in src/jvm/main/org/jetbrains/kotlinx/lincheck/strategy/managed/InterleavingSequenceTrackableSet.kt [241:289]
fun mergeBranch(newChain: List<InterleavingHistoryNode>, startIndex: Int, executionsCountedEarlier: Int) {
if (startIndex > newChain.lastIndex) return
val firstNewNode = newChain[startIndex]
var firstNewNodeExecutions = (firstNewNode.executions + firstNewNode.spinCyclePeriod) - executionsCountedEarlier
check(firstNewNode.threadId == threadId)
// Some execution points may be added to the history after the spin-cycle is detected early
// even if we switched the execution using LoopDetector hint. In this case, the new branch may have
// more executions than the InterleavingSequenceSetNode which told switching the thread at this point.
// But these executions will be omitted in the next time, so we merge new branch taking execution count
// from the corresponding existing node.
if (cycleOccurred && firstNewNodeExecutions > executions) {
firstNewNodeExecutions = executions
}
when {
executions == firstNewNodeExecutions -> mergeFurtherOrAddNewBranch(newChain, startIndex + 1, 0)
executions < firstNewNodeExecutions -> mergeFurtherOrAddNewBranch(
newChain = newChain,
startIndex = startIndex,
executionsCountedEarlier = executionsCountedEarlier + executions
)
else -> { // node.operations > first.operations
if (startIndex == newChain.lastIndex) return
val deltaExecutions = executions - firstNewNodeExecutions
val nextNode = InterleavingSequenceSetNode(
threadId = threadId,
executions = deltaExecutions,
transitions = transitions,
cyclePeriod = cyclePeriod,
cycleOccurred = cycleOccurred,
cycleLocationsHash = cycleLocationsHash
)
executions = firstNewNodeExecutions
cyclePeriod = firstNewNode.spinCyclePeriod
cycleOccurred = firstNewNode.cycleOccurred
val (newChainRoot, newChainLeaf) = wrapChain(newChain, startIndex + 1)
transitions = mutableMapOf(
threadId to nextNode,
newChainRoot.threadId to newChainRoot
)
cursor.setTo(newChainLeaf)
}
}
}