예제 #1
0
  @Override
  public boolean isNotNull(DfaValue dfaVar) {
    if (dfaVar instanceof DfaConstValue) return ((DfaConstValue) dfaVar).getValue() != null;
    if (dfaVar instanceof DfaBoxedValue) return true;
    if (dfaVar instanceof DfaTypeValue) return ((DfaTypeValue) dfaVar).isNotNull();
    if (dfaVar instanceof DfaVariableValue) {
      if (getVariableState((DfaVariableValue) dfaVar).isNotNull()) return true;

      DfaConstValue constantValue = getConstantValue((DfaVariableValue) dfaVar);
      if (constantValue != null && constantValue.getValue() != null) return true;
    }

    DfaConstValue dfaNull = myFactory.getConstFactory().getNull();
    int c1Index = getEqClassIndex(dfaVar);
    int c2Index = getEqClassIndex(dfaNull);
    if (c1Index < 0 || c2Index < 0) {
      return false;
    }

    long[] pairs = myDistinctClasses.toArray();
    for (long pair : pairs) {
      if (c1Index == low(pair) && c2Index == high(pair)
          || c1Index == high(pair) && c2Index == low(pair)) {
        return true;
      }
    }

    return false;
  }
예제 #2
0
  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;
  }
예제 #3
0
  LinkedHashSet<UnorderedPair<EqClass>> getDistinctClassPairs() {
    if (myCachedDistinctClassPairs != null) return myCachedDistinctClassPairs;

    LinkedHashSet<UnorderedPair<EqClass>> result = ContainerUtil.newLinkedHashSet();
    for (long encodedPair : myDistinctClasses.toArray()) {
      result.add(
          new UnorderedPair<>(
              myEqClasses.get(low(encodedPair)), myEqClasses.get(high(encodedPair))));
    }
    return myCachedDistinctClassPairs = result;
  }
예제 #4
0
  @SuppressWarnings("HardCodedStringLiteral")
  public String toString() {
    StringBuilder result = new StringBuilder();
    result.append('<');
    if (myEphemeral) {
      result.append("ephemeral, ");
    }

    for (EqClass set : getNonTrivialEqClasses()) {
      result.append(set);
    }

    if (!myDistinctClasses.isEmpty()) {
      result.append("\n  distincts: ");
      List<String> distincts = new ArrayList<>();
      for (UnorderedPair<EqClass> pair : getDistinctClassPairs()) {
        distincts.add("{" + pair.first + ", " + pair.second + "}");
      }
      Collections.sort(distincts);
      result.append(StringUtil.join(distincts, " "));
    }

    if (!myStack.isEmpty()) {
      result.append("\n  stack: ").append(StringUtil.join(myStack, ","));
    }
    if (!myVariableStates.isEmpty()) {
      result.append("\n  vars: ");
      for (Map.Entry<DfaVariableValue, DfaVariableState> entry : myVariableStates.entrySet()) {
        result
            .append("[")
            .append(entry.getKey())
            .append("->")
            .append(entry.getValue())
            .append("] ");
      }
    }
    if (!myUnknownVariables.isEmpty()) {
      result.append("\n  unknowns: ").append(new HashSet<>(myUnknownVariables));
    }
    result.append('>');
    return result.toString();
  }
예제 #5
0
 private void makeClassesDistinct(int c1Index, int c2Index) {
   myDistinctClasses.add(createPair(c1Index, c2Index));
 }
예제 #6
0
  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;
  }
예제 #7
0
  void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) {
    DfaVariableValue varNegated = varPlain.getNegatedValue();

    final int idPlain = varPlain.getID();
    final int idNegated = varNegated == null ? -1 : varNegated.getID();

    int[] classes = myIdToEqClassesIndices.get(idPlain);
    int[] negatedClasses = myIdToEqClassesIndices.get(idNegated);
    int[] result =
        ArrayUtil.mergeArrays(
            ObjectUtils.notNull(classes, ArrayUtil.EMPTY_INT_ARRAY),
            ObjectUtils.notNull(negatedClasses, ArrayUtil.EMPTY_INT_ARRAY));

    int interruptCount = 0;

    for (int varClassIndex : result) {
      EqClass varClass = myEqClasses.get(varClassIndex);
      if ((++interruptCount & 0xf) == 0) {
        ProgressManager.checkCanceled();
      }

      varClass = new EqClass(varClass);
      myEqClasses.set(varClassIndex, varClass);
      for (int id : varClass.toNativeArray()) {
        int idUnwrapped;
        if (id == idPlain
            || id == idNegated
            || (idUnwrapped = unwrap(myFactory.getValue(id)).getID()) == idPlain
            || idUnwrapped == idNegated) {
          varClass.removeValue(id);
        }
      }

      if (varClass.isEmpty()) {
        myEqClasses.set(varClassIndex, null);

        for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) {
          long pair = iterator.next();
          if (low(pair) == varClassIndex || high(pair) == varClassIndex) {
            iterator.remove();
          }
        }
      } else if (varClass.containsConstantsOnly()) {
        for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) {
          long pair = iterator.next();
          if (low(pair) == varClassIndex && myEqClasses.get(high(pair)).containsConstantsOnly()
              || high(pair) == varClassIndex
                  && myEqClasses.get(low(pair)).containsConstantsOnly()) {
            iterator.remove();
          }
        }
      }
    }

    removeAllFromMap(idPlain);
    removeAllFromMap(idNegated);
    myVariableStates.remove(varPlain);
    if (varNegated != null) {
      myVariableStates.remove(varNegated);
    }
    if (markUnknown) {
      myUnknownVariables.add(varPlain);
    }
    myCachedNonTrivialEqClasses = null;
    myCachedDistinctClassPairs = null;
    myCachedHash = null;
  }