private boolean applyRelation( @NotNull final DfaValue dfaLeft, @NotNull final DfaValue dfaRight, boolean isNegated) { if (isUnknownState(dfaLeft) || isUnknownState(dfaRight)) { return true; } // DfaConstValue || DfaVariableValue Integer c1Index = getOrCreateEqClassIndex(dfaLeft); Integer c2Index = getOrCreateEqClassIndex(dfaRight); if (c1Index == null || c2Index == null) { return true; } if (!isNegated) { // Equals if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return true; if (!uniteClasses(c1Index, c2Index)) return false; for (long encodedPair : myDistinctClasses.toArray()) { EqClass c1 = myEqClasses.get(low(encodedPair)); EqClass c2 = myEqClasses.get(high(encodedPair)); DfaConstValue const1 = (DfaConstValue) c1.findConstant(false); DfaConstValue const2 = (DfaConstValue) c2.findConstant(false); if (const1 != null && const2 != null && !preserveConstantDistinction(const1.getValue(), const2.getValue())) { myDistinctClasses.remove(encodedPair); } } myCachedDistinctClassPairs = null; myCachedNonTrivialEqClasses = null; myCachedHash = null; } else { // Not Equals if (c1Index.equals(c2Index) || areCompatibleConstants(c1Index, c2Index)) return false; if (isNull(dfaLeft) && isPrimitive(dfaRight) || isNull(dfaRight) && isPrimitive(dfaLeft)) return true; makeClassesDistinct(c1Index, c2Index); myCachedDistinctClassPairs = null; myCachedHash = null; } return true; }
private boolean uniteClasses(int c1Index, int c2Index) { EqClass c1 = myEqClasses.get(c1Index); EqClass c2 = myEqClasses.get(c2Index); Set<DfaVariableValue> vars = ContainerUtil.newTroveSet(); Set<DfaVariableValue> negatedVars = ContainerUtil.newTroveSet(); int[] cs = new int[c1.size() + c2.size()]; c1.set(0, cs, 0, c1.size()); c2.set(0, cs, c1.size(), c2.size()); int nConst = 0; for (int c : cs) { DfaValue dfaValue = unwrap(myFactory.getValue(c)); if (dfaValue instanceof DfaConstValue) nConst++; if (dfaValue instanceof DfaVariableValue) { DfaVariableValue variableValue = (DfaVariableValue) dfaValue; if (variableValue.isNegated()) { negatedVars.add(variableValue.createNegated()); } else { vars.add(variableValue); } } if (nConst > 1) return false; } if (ContainerUtil.intersects(vars, negatedVars)) return false; TLongArrayList c2Pairs = new TLongArrayList(); long[] distincts = myDistinctClasses.toArray(); for (long distinct : distincts) { int pc1 = low(distinct); int pc2 = high(distinct); boolean addedToC1 = false; if (pc1 == c1Index || pc2 == c1Index) { addedToC1 = true; } if (pc1 == c2Index || pc2 == c2Index) { if (addedToC1) return false; c2Pairs.add(distinct); } } EqClass newClass = new EqClass(c1); myEqClasses.set(c1Index, newClass); for (int i = 0; i < c2.size(); i++) { int c = c2.get(i); newClass.add(c); removeFromMap(c, c2Index); addToMap(c, c1Index); } for (int i = 0; i < c2Pairs.size(); i++) { long c = c2Pairs.get(i); myDistinctClasses.remove(c); myDistinctClasses.add(createPair(c1Index, low(c) == c2Index ? high(c) : low(c))); } myEqClasses.set(c2Index, null); return true; }