IDEA-81509. DFA optimization

This commit is contained in:
Maxim Shafirov
2012-02-22 17:14:16 +04:00
parent 7e851eac69
commit c8b1906e4e
3 changed files with 30 additions and 9 deletions
@@ -60,4 +60,6 @@ public interface DfaMemoryState {
boolean isNotNull(DfaVariableValue dfaVar);
void flushVariableOutOfScope(DfaVariableValue variable);
void fieldReferenced();
}
@@ -51,7 +51,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
private Stack<DfaValue> myStack;
private TIntStack myOffsetStack;
private TLongHashSet myDistinctClasses;
private Map<DfaVariableValue,DfaVariableState> myVariableStates;
private THashMap<DfaVariableValue,DfaVariableState> myVariableStates;
private boolean myHasDirtyFields = true;
public DfaMemoryStateImpl(final DfaValueFactory factory) {
myFactory = factory;
@@ -80,6 +81,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
newState.myStateSize = myStateSize;
newState.myVariableStates = new THashMap<DfaVariableValue, DfaVariableState>();
newState.myOffsetStack = new TIntStack(myOffsetStack);
newState.myHasDirtyFields = myHasDirtyFields;
for (int i = 0; i < myEqClasses.size(); i++) {
SortedIntSet aClass = myEqClasses.get(i);
@@ -110,6 +112,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
if (!myStack.equals(that.myStack)) return false;
if (!myOffsetStack.equals(that.myOffsetStack)) return false;
if (!myVariableStates.equals(that.myVariableStates)) return false;
if (myHasDirtyFields != that.myHasDirtyFields) return false;
int[] permutation = getPermutationToSortedState();
int[] thatPermutation = that.getPermutationToSortedState();
@@ -461,6 +464,11 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
myDistinctClasses.add(createPair(c1Index, c2Index));
}
@Override
public void fieldReferenced() {
myHasDirtyFields = true;
}
public boolean isNull(DfaValue dfaValue) {
if (dfaValue instanceof DfaNotNullValue) return false;
@@ -674,6 +682,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
public void flushFields(DataFlowRunner runner) {
if (!myHasDirtyFields) return;
myHasDirtyFields = false;
DfaVariableValue[] fields = runner.getFields();
for (DfaVariableValue field : fields) {
boolean resetNullability = isNotNull(field);
@@ -690,17 +701,19 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
doFlash(variable);
doFlash((DfaVariableValue)variable.createNegated());
}
@Override
public void flushVariableOutOfScope(DfaVariableValue variable) {
doFlash(variable);
doFlash((DfaVariableValue)variable.createNegated());
}
private void doFlash(DfaVariableValue variable) {
final int id = variable.getID();
private void doFlash(DfaVariableValue varPlain) {
DfaVariableValue varNegated = (DfaVariableValue)varPlain.createNegated();
final int idPlain = varPlain.getID();
final int idNegated = varNegated.getID();
int size = myEqClasses.size();
int interruptCount = 0;
for (int varClassIndex = 0; varClassIndex < size; varClassIndex++) {
@@ -713,9 +726,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
int cl = varClass.get(i);
DfaValue value = myFactory.getValue(cl);
if (value != null && id == value.getID() ||
value instanceof DfaBoxedValue && ((DfaBoxedValue)value).getWrappedValue().getID() == id ||
value instanceof DfaUnboxedValue && ((DfaUnboxedValue)value).getVariable().getID() == id) {
if (mine(idPlain, value) || mine(idNegated, value)) {
varClass.remove(i);
break;
}
@@ -733,6 +744,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
}
myVariableStates.remove(variable);
myVariableStates.remove(varPlain);
myVariableStates.remove(varNegated);
}
private static boolean mine(int id, DfaValue value) {
return value != null && id == value.getID() ||
value instanceof DfaBoxedValue && ((DfaBoxedValue)value).getWrappedValue().getID() == id ||
value instanceof DfaUnboxedValue && ((DfaUnboxedValue)value).getVariable().getID() == id;
}
}
@@ -119,6 +119,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
@Override
public DfaInstructionState[] visitFieldReference(FieldReferenceInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
memState.fieldReferenced();
final DfaValue qualifier = memState.pop();
if (instruction.getExpression().isPhysical() && !memState.applyNotNull(qualifier)) {
onInstructionProducesNPE(instruction, runner);