DFA: improved memory state isSuperState; squash states via isSuperState

This commit is contained in:
Tagir Valeev
2017-12-05 10:55:04 +07:00
parent bd8362a647
commit 90a7c7576d
2 changed files with 21 additions and 2 deletions
@@ -24,6 +24,7 @@ import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.stream.Collectors;
public class DfaInstructionState implements Comparable<DfaInstructionState> {
public static final DfaInstructionState[] EMPTY_ARRAY = new DfaInstructionState[0];
@@ -93,6 +94,10 @@ class StateQueue {
memoryStates.add((DfaMemoryStateImpl)anotherState);
}
if (memoryStates.size() > 1) {
memoryStates = squash(memoryStates);
}
if (memoryStates.size() > 1 && joinInstructions.contains(instruction)) {
MultiMap<Object, DfaMemoryStateImpl> groups = MultiMap.create();
for (DfaMemoryStateImpl memoryState : memoryStates) {
@@ -109,6 +114,10 @@ class StateQueue {
return ContainerUtil.map(memoryStates, state1 -> new DfaInstructionState(instruction, state1));
}
private static List<DfaMemoryStateImpl> squash(List<DfaMemoryStateImpl> states) {
return states.stream().filter(left -> states.stream().noneMatch(right -> right != left && right.isSuperStateOf(left))).collect(Collectors.toList());
}
static List<DfaMemoryStateImpl> mergeGroup(List<DfaMemoryStateImpl> group) {
if (group.size() < 2) {
return group;
@@ -382,8 +382,10 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
* @return true if current state is a super-state of the supplied state.
*/
public boolean isSuperStateOf(DfaMemoryStateImpl that) {
if (!equalsSuperficially(that) ||
!equalsByUnknownVariables(that) ||
if (myEphemeral && !that.myEphemeral) return false;
if (myStack.size() != that.myStack.size()) return false;
if (StreamEx.zip(myStack, that.myStack, DfaMemoryStateImpl::isSuperValue).has(false)) return false;
if (!equalsByUnknownVariables(that) ||
!that.getDistinctClassPairs().containsAll(getDistinctClassPairs())) {
return false;
}
@@ -410,6 +412,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return true;
}
private static boolean isSuperValue(DfaValue superValue, DfaValue subValue) {
if (superValue == DfaUnknownValue.getInstance() || superValue == subValue) return true;
if (superValue instanceof DfaFactMapValue && subValue instanceof DfaFactMapValue) {
return ((DfaFactMapValue)superValue).getFacts().isSuperStateOf(((DfaFactMapValue)subValue).getFacts());
}
return false;
}
private static boolean canBeInRelation(@NotNull DfaValue dfaValue) {
DfaValue unwrapped = unwrap(dfaValue);
return unwrapped instanceof DfaVariableValue || unwrapped instanceof DfaConstValue;