Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion usvm-core/src/main/kotlin/org/usvm/PathSelector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,17 @@ interface UPathSelector<State> {
* Updates the internal priority of the [state].
*/
fun update(state: State)
}

/**
* Removes and yields every queued state after execution has stopped.
* Wrappers with scheduling or merging side effects must drain their children directly.
* Each state is removed before it is yielded; the sequence must be consumed once.
*/
fun drain(): Sequence<State> = sequence {
while (!isEmpty()) {
val state = peek()
remove(state)
yield(state)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ class MergingPathSelector<State : UState<*, *, *, *, *, State>>(
closeStatesSearcher.add(states)
}

override fun drain(): Sequence<State> = sequence {
for (state in underlyingPathSelector.drain()) {
closeStatesSearcher.remove(state)
yield(state)
}
}

override fun remove(state: State) {
underlyingPathSelector.remove(state)
closeStatesSearcher.remove(state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.usvm.ps

import org.usvm.UPathSelector
import org.usvm.UState
import java.util.Collections
import java.util.IdentityHashMap

/**
Expand Down Expand Up @@ -92,6 +93,26 @@ class ExceptionPropagationPathSelector<State : UState<*, *, *, *, *, State>>(
selector.add(statesToAdd)
}

override fun drain(): Sequence<State> = sequence {
val emittedStates = Collections.newSetFromMap(IdentityHashMap<State, Boolean>())
for (state in selector.drain()) {
statesInSelector.remove(state)
exceptionalStates.remove(state)
if (emittedStates.add(state)) {
yield(state)
}
}

while (exceptionalStates.isNotEmpty()) {
val state = exceptionalStates.keys.first()
exceptionalStates.remove(state)
statesInSelector.remove(state)
if (emittedStates.add(state)) {
yield(state)
}
}
}

override fun remove(state: State) {
if (state in exceptionalStates) {
exceptionalStates -= state
Expand Down
13 changes: 13 additions & 0 deletions usvm-core/src/main/kotlin/org/usvm/ps/InterleavedPathSelector.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.usvm.ps

import org.usvm.UPathSelector
import java.util.Collections
import java.util.IdentityHashMap

/**
* An interleaved path selector.
Expand Down Expand Up @@ -40,6 +42,17 @@ class InterleavedPathSelector<State>(
ptr = (ptr + 1) % selectors.size
}

override fun drain(): Sequence<State> = sequence {
val emittedStates = Collections.newSetFromMap(IdentityHashMap<State, Boolean>())
for (selector in selectors) {
for (state in selector.drain()) {
if (emittedStates.add(state)) {
yield(state)
}
}
}
}

override fun remove(state: State) {
selectors.forEach { it.remove(state) }
}
Expand Down
18 changes: 18 additions & 0 deletions usvm-core/src/main/kotlin/org/usvm/ps/IterativeDeepeningPs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ class IterativeDeepeningPs<Stmt, Method, Loop : Any, State : UState<*, Method, S
underlyingPs.remove(state)
}

override fun drain(): Sequence<State> = sequence {
yieldAll(underlyingPs.drain())

for (level in pendingStates.keys.sorted()) {
val states = pendingStates.getValue(level)
while (states.isNotEmpty()) {
yield(states.removeAt(states.lastIndex))
}
pendingStates.remove(level)
}

stateStats.clear()
lastPeekedState = null
lastPeekedStateStats = StateLoopStatistic.rootStats()
currentLevel = 0
maxLevel = 0
}

private fun pushStates() {
while (underlyingPs.isEmpty() && currentLevel <= maxLevel) {
currentLevel++
Expand Down
6 changes: 6 additions & 0 deletions usvm-core/src/main/kotlin/org/usvm/ps/KeyedPathSelector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ abstract class KeyedPathSelector<State, Key>(private val getKey: (State) -> Key)
pathSelectors[key]?.remove(state) ?: throw IllegalStateException("Trying to remove state with unknown key")
}

override fun drain(): Sequence<State> = sequence {
for (selector in pathSelectors.values) {
yieldAll(selector.drain())
}
}

fun removeKey(key: Key) {
pathSelectors.remove(key)
}
Expand Down
8 changes: 8 additions & 0 deletions usvm-core/src/main/kotlin/org/usvm/ps/LoopLimiterPs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ class LoopLimiterPs<Stmt, Method, Loop : Any, State : UState<*, Method, Stmt, *,
addSingleState(state)
}

override fun drain(): Sequence<State> = sequence {
yieldAll(underlyingPs.drain())

stateStats.clear()
lastPeekedState = null
lastPeekedStateStats = StateLoopStatistic.rootStats()
}

override fun remove(state: State) {
check(state === lastPeekedState) { "Try to remove not peeked state" }

Expand Down
13 changes: 13 additions & 0 deletions usvm-core/src/main/kotlin/org/usvm/ps/ParallelPathSelector.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.usvm.ps

import org.usvm.UPathSelector
import java.util.Collections
import java.util.IdentityHashMap

/**
* A parallel path selector.
Expand Down Expand Up @@ -40,6 +42,17 @@ class ParallelPathSelector<State>(
ptr = (ptr + 1) % selectors.size
}

override fun drain(): Sequence<State> = sequence {
val emittedStates = Collections.newSetFromMap(IdentityHashMap<State, Boolean>())
for (selector in selectors) {
for (state in selector.drain()) {
if (emittedStates.add(state)) {
yield(state)
}
}
}
}

override fun remove(state: State) {
selectors[ptr].remove(state)
}
Expand Down
Loading
Loading