private int regionToDot(Region r, StringBuilder str, Map<Region, Integer> cache) { if (cache.containsKey(r)) { // use same region again return cache.get(r); } else { Triple<Region, Region, Region> triple = delegate.getIfThenElse(r); // create node with label String predName = regionMap.inverse().get(triple.getFirst()); nodeCounter += 1; // one more node is created int predNum = nodeCounter; str.append(predNum).append(" [label=\"").append(predName).append("\"];\n"); // create arrow for true branch Region trueBranch = triple.getSecond(); int trueTarget = regionToDot(trueBranch, str, cache); str.append(predNum).append(" -> ").append(trueTarget).append(" [style=filled];\n"); // create arrow for false branch Region falseBranch = triple.getThird(); int falseTarget = regionToDot(falseBranch, str, cache); str.append(predNum).append(" -> ").append(falseTarget).append(" [style=dotted];\n"); cache.put(r, predNum); return predNum; } }
private void dumpRegion(Region r, Appendable out) throws IOException { if (regionMap.containsValue(r)) { out.append(regionMap.inverse().get(r)); } else if (r.isFalse()) { out.append("FALSE"); } else if (r.isTrue()) { out.append("TRUE"); } else { Triple<Region, Region, Region> triple = delegate.getIfThenElse(r); String predName = regionMap.inverse().get(triple.getFirst()); Region trueBranch = triple.getSecond(); Region falseBranch = triple.getThird(); if (trueBranch.isFalse()) { assert !falseBranch.isFalse(); // only falseBranch is present out.append("!").append(predName).append(" & "); dumpRegion(falseBranch, out); } else if (falseBranch.isFalse()) { // only trueBranch is present out.append(predName).append(" & "); dumpRegion(trueBranch, out); } else { // both branches present out.append("((").append(predName).append(" & "); dumpRegion(trueBranch, out); out.append(") | (").append("!").append(predName).append(" & "); dumpRegion(falseBranch, out); out.append("))"); } } }
@Override public Object getHashCodeForState(AbstractState pElementKey, Precision pPrecisionKey) { PredicateAbstractState element = (PredicateAbstractState) pElementKey; PredicatePrecision precision = (PredicatePrecision) pPrecisionKey; /* Normally a getHashCodeForState is just the pair of state and precision. For PredicateAnalysis, we need to refine the RelevantPredicatesComputer (in some cases), thus the reduce-operator changes and we should clear the cache completely after such a refinement. Instead of doing this, we use the RelevantPredicatesComputer as (third) part of the cache-key, such that after refining the RelevantPredicatesComputer, each new access results in a cache-miss. The benefit is that we keep existing ARGs for statistics or other usage. The drawback is the memory-usage through some cached states, that will never be visited again, because the reduce-operator has changed. */ // TODO is Object-equality for RelevantPredicatesComputer enough or should we implement // RelevantPredicatesComputer.equals()? return Triple.of( element.getAbstractionFormula().asRegion(), precision, cpa.getRelevantPredicatesComputer()); }