mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
immutable DfaVariableState, for faster copying and less memory usage
This commit is contained in:
+66
-46
@@ -45,12 +45,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
private final Stack<DfaValue> myStack = new Stack<DfaValue>();
|
||||
private TIntStack myOffsetStack = new TIntStack(1);
|
||||
private final TLongHashSet myDistinctClasses = new TLongHashSet();
|
||||
private final THashMap<DfaVariableValue,DfaVariableState> myVariableStates = new THashMap<DfaVariableValue, DfaVariableState>();
|
||||
private final THashMap<DfaVariableValue,DfaVariableState> myVariableStates = ContainerUtil.newTroveMap();
|
||||
private THashMap<DfaVariableValue,DfaVariableState> myDefaultVariableStates; // shared between all states
|
||||
private final THashSet<DfaVariableValue> myUnknownVariables = new THashSet<DfaVariableValue>();
|
||||
private boolean myEphemeral;
|
||||
|
||||
public DfaMemoryStateImpl(final DfaValueFactory factory) {
|
||||
myFactory = factory;
|
||||
myDefaultVariableStates = ContainerUtil.newTroveMap();
|
||||
}
|
||||
|
||||
public DfaValueFactory getFactory() {
|
||||
@@ -65,6 +67,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
public DfaMemoryStateImpl createCopy() {
|
||||
DfaMemoryStateImpl newState = createNew();
|
||||
|
||||
newState.myDefaultVariableStates = myDefaultVariableStates;
|
||||
newState.myEphemeral = myEphemeral;
|
||||
newState.myStack.addAll(myStack);
|
||||
newState.myDistinctClasses.addAll(myDistinctClasses.toArray());
|
||||
@@ -76,9 +79,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
newState.myEqClasses.add(aClass != null ? new EqClass(aClass) : null);
|
||||
}
|
||||
|
||||
for (DfaVariableValue dfaVariableValue : myVariableStates.keySet()) {
|
||||
newState.myVariableStates.put(dfaVariableValue, myVariableStates.get(dfaVariableValue).clone());
|
||||
}
|
||||
newState.myVariableStates.putAll(myVariableStates);
|
||||
return newState;
|
||||
}
|
||||
|
||||
@@ -98,19 +99,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
if (myDistinctClasses.size() != that.myDistinctClasses.size()) return false;
|
||||
if (!getNonTrivialEqClasses().equals(that.getNonTrivialEqClasses())) return false;
|
||||
if (!getDistinctClassPairs().equals(that.getDistinctClassPairs())) return false;
|
||||
|
||||
for (DfaVariableValue var : myVariableStates.keySet()) {
|
||||
DfaVariableState thatState = that.myVariableStates.get(var);
|
||||
if (!myVariableStates.get(var).equals(thatState != null ? thatState : createVariableState(var))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (DfaVariableValue var : that.myVariableStates.keySet()) {
|
||||
if (!myVariableStates.containsKey(var) && !that.myVariableStates.get(var).equals(createVariableState(var))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!myVariableStates.equals(that.myVariableStates)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -142,7 +131,11 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ((getNonTrivialEqClasses().hashCode() * 31 + getDistinctClassPairs().hashCode()) * 31 + myStack.hashCode()) * 31 + myUnknownVariables.hashCode();
|
||||
return (((getNonTrivialEqClasses().hashCode() * 31 +
|
||||
getDistinctClassPairs().hashCode()) * 31 +
|
||||
myStack.hashCode()) * 31 +
|
||||
myUnknownVariables.hashCode()) * 31 +
|
||||
myVariableStates.hashCode();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
@@ -218,15 +211,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
if (var == value) return;
|
||||
|
||||
flushVariable(var);
|
||||
DfaVariableState varState = getVariableState(var);
|
||||
if (value instanceof DfaUnknownValue) {
|
||||
varState.setNullable(false);
|
||||
setVariableState(var, getVariableState(var).withNullable(false));
|
||||
return;
|
||||
}
|
||||
|
||||
varState.setValue(value);
|
||||
setVariableState(var, getVariableState(var).withValue(value));
|
||||
if (value instanceof DfaTypeValue) {
|
||||
varState.setNullable(((DfaTypeValue)value).isNullable());
|
||||
setVariableState(var, getVariableState(var).withNullable(((DfaTypeValue)value).isNullable()));
|
||||
DfaRelationValue dfaInstanceof = myFactory.getRelationFactory().createRelation(var, value, JavaTokenType.INSTANCEOF_KEYWORD, false);
|
||||
if (((DfaTypeValue)value).isNotNull()) {
|
||||
applyCondition(dfaInstanceof);
|
||||
@@ -240,15 +232,15 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
applyCondition(dfaEqual);
|
||||
|
||||
if (value instanceof DfaVariableValue) {
|
||||
myVariableStates.put(var, varState = getVariableState((DfaVariableValue)value).clone());
|
||||
setVariableState(var, getVariableState((DfaVariableValue)value));
|
||||
}
|
||||
else if (value instanceof DfaBoxedValue) {
|
||||
varState.setNullable(false);
|
||||
setVariableState(var, getVariableState(var).withNullable(false));
|
||||
applyCondition(compareToNull(var, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (varState.isNotNull()) {
|
||||
if (getVariableState(var).isNotNull()) {
|
||||
applyCondition(compareToNull(var, true));
|
||||
}
|
||||
}
|
||||
@@ -448,7 +440,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
public boolean isNull(DfaValue dfaValue) {
|
||||
if (dfaValue instanceof DfaTypeValue && ((DfaTypeValue)dfaValue).isNotNull()) return false;
|
||||
|
||||
if (dfaValue instanceof DfaConstValue) return ((DfaConstValue)dfaValue).getConstant() == null;
|
||||
if (dfaValue instanceof DfaConstValue) return ((DfaConstValue)dfaValue).getValue() == null;
|
||||
|
||||
if (dfaValue instanceof DfaVariableValue) {
|
||||
int c1Index = getEqClassIndex(dfaValue);
|
||||
@@ -509,7 +501,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
DfaVariableValue dfaVar = (DfaVariableValue)left;
|
||||
DfaTypeValue dfaType = (DfaTypeValue)dfaCond.getRightOperand();
|
||||
|
||||
return isNull(dfaVar) || getVariableState(dfaVar).setInstanceofValue(dfaType);
|
||||
if (isUnknownState(dfaVar) || isNull(dfaVar)) return true;
|
||||
DfaVariableState newState = getVariableState(dfaVar).withInstanceofValue(dfaType);
|
||||
if (newState != null) {
|
||||
setVariableState(dfaVar, newState);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static DfaValue unwrap(DfaValue value) {
|
||||
@@ -561,12 +559,25 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
|
||||
if (dfaRight instanceof DfaTypeValue) {
|
||||
if (dfaLeft instanceof DfaVariableValue) {
|
||||
DfaVariableState varState = getVariableState((DfaVariableValue)dfaLeft);
|
||||
DfaVariableValue dfaVar = (DfaVariableValue)dfaLeft;
|
||||
if (isUnknownState(dfaVar)) return true;
|
||||
|
||||
if (isNegated) {
|
||||
return varState.addNotInstanceofValue((DfaTypeValue)dfaRight) || applyCondition(compareToNull(dfaVar, false));
|
||||
DfaVariableState newState = getVariableState(dfaVar).withNotInstanceofValue((DfaTypeValue)dfaRight);
|
||||
if (newState != null) {
|
||||
setVariableState(dfaVar, newState);
|
||||
return true;
|
||||
}
|
||||
return applyCondition(compareToNull(dfaVar, false));
|
||||
}
|
||||
return applyCondition(compareToNull(dfaVar, true)) && varState.setInstanceofValue((DfaTypeValue)dfaRight);
|
||||
if (applyCondition(compareToNull(dfaVar, true))) {
|
||||
DfaVariableState newState = getVariableState(dfaVar).withInstanceofValue((DfaTypeValue)dfaRight);
|
||||
if (newState != null) {
|
||||
setVariableState(dfaVar, newState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -593,7 +604,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
if (isNotNull(dfaVar)) {
|
||||
return true;
|
||||
}
|
||||
getVariableState(dfaVar).setNullable(true);
|
||||
if (!isUnknownState(dfaVar)) {
|
||||
setVariableState(dfaVar, getVariableState(dfaVar).withNullability(Nullness.NULLABLE));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -734,17 +747,33 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return myFactory.getRelationFactory().createRelation(dfaVar, dfaNull, JavaTokenType.EQEQ, negated);
|
||||
}
|
||||
|
||||
void setVariableState(DfaVariableValue dfaVar, DfaVariableState state) {
|
||||
assert !myUnknownVariables.contains(dfaVar);
|
||||
if (state.equals(myDefaultVariableStates.get(dfaVar))) {
|
||||
myVariableStates.remove(dfaVar);
|
||||
} else {
|
||||
myVariableStates.put(dfaVar, state);
|
||||
}
|
||||
}
|
||||
|
||||
public DfaVariableState getVariableState(DfaVariableValue dfaVar) {
|
||||
DfaVariableState state = myVariableStates.get(dfaVar);
|
||||
|
||||
if (state == null) {
|
||||
state = createVariableState(dfaVar);
|
||||
state = myDefaultVariableStates.get(dfaVar);
|
||||
if (state == null) {
|
||||
state = createVariableState(dfaVar);
|
||||
DfaTypeValue initialType = dfaVar.getTypeValue();
|
||||
if (initialType != null) {
|
||||
state = state.withInstanceofValue(initialType);
|
||||
assert state != null;
|
||||
}
|
||||
myDefaultVariableStates.put(dfaVar, state);
|
||||
}
|
||||
|
||||
if (isUnknownState(dfaVar)) {
|
||||
state.setNullable(false);
|
||||
return state;
|
||||
return state.withNullable(false);
|
||||
}
|
||||
|
||||
myVariableStates.put(dfaVar, state);
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -760,16 +789,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
|
||||
@Override
|
||||
public void flushFields(DfaVariableValue[] fields) {
|
||||
Set<DfaVariableValue> allVars = new HashSet<DfaVariableValue>(myVariableStates.keySet());
|
||||
Collections.addAll(allVars, fields);
|
||||
|
||||
Set<DfaVariableValue> dependencies = new HashSet<DfaVariableValue>();
|
||||
for (DfaVariableValue variableValue : allVars) {
|
||||
dependencies.addAll(myFactory.getVarFactory().getAllQualifiedBy(variableValue));
|
||||
}
|
||||
allVars.addAll(dependencies);
|
||||
|
||||
for (DfaVariableValue value : allVars) {
|
||||
for (DfaVariableValue value : myFactory.getVarFactory().getAllVariables()) {
|
||||
if (myVariableStates.containsKey(value) || getEqClassIndex(value) >= 0) {
|
||||
if (value.isFlushableByCalls()) {
|
||||
doFlush(value, true);
|
||||
|
||||
Reference in New Issue
Block a user