class AnalysisInfo extends java.util.BitSet {
    private static final long serialVersionUID = -9200043127757823764L;

    public AnalysisInfo() {
      super(used);
    }

    public AnalysisInfo(AnalysisInfo other) {
      super(used);
      or(other);
    }

    public int get(Value key) {
      if (!valueToIndex.containsKey(key)) {
        return BOTTOM;
      }
      int index = valueToIndex.get(key);
      return (get(index) ? 2 : 0) + (get(index + 1) ? 1 : 0);
    }

    public void put(Value key, int val) {
      int index;
      if (!valueToIndex.containsKey(key)) {
        index = used;
        used += 2;
        valueToIndex.put(key, index);
      } else {
        index = valueToIndex.get(key);
      }
      set(index, (val & 2) == 2);
      set(index + 1, (val & 1) == 1);
    }
  }

  protected final static int BOTTOM = 0;
  protected final static int NULL = 1;
  protected final static int NON_NULL = 2;
  protected final static int TOP = 3;

  protected final HashMap<Value, Integer> valueToIndex = new HashMap<Value, Integer>();
  protected int used = 0;

  /**
   * Creates a new analysis for the given graph/
   *
   * @param graph
   *          any unit graph
   */
  public NullnessAnalysis(UnitGraph graph) {
    super(graph);

    doAnalysis();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void flowThrough(AnalysisInfo in, Unit u, List<AnalysisInfo> fallOut, List<AnalysisInfo> branchOuts) {
    AnalysisInfo out = new AnalysisInfo(in);
    AnalysisInfo outBranch = new AnalysisInfo(in);

    Stmt s = (Stmt) u;

    // in case of an if statement, we need to compute the branch-flow;
    // e.g. for a statement "if(x!=null) goto s" we have x==null for the fallOut and
    // x!=null for the branchOut
    // or for an instanceof expression
    if (s instanceof JIfStmt) {
      handleIfStmt((JIfStmt) s, in, out, outBranch);
    } else if (s instanceof MonitorStmt) {
      // in case of a monitor statement, we know that if it succeeds, we have a non-null value
      out.put(((MonitorStmt) s).getOp(), NON_NULL);
    }

    // if we have an array ref, set the base to non-null
    if (s.containsArrayRef()) {
      handleArrayRef(s.getArrayRef(), out);
    }
    // for field refs, set the receiver object to non-null, if there is one
    if (s.containsFieldRef()) {
      handleFieldRef(s.getFieldRef(), out);
    }
    // for invoke expr, set the receiver object to non-null, if there is one
    if (s.containsInvokeExpr()) {
      handleInvokeExpr(s.getInvokeExpr(), out);
    }

    // if we have a definition (assignment) statement to a ref-like type, handle it,
    // i.e. assign it TOP, except in the following special cases:
    // x=null, assign NULL
    // x=@this or x= new... assign NON_NULL
    // x=y, copy the info for y (for locals x,y)
    if (s instanceof DefinitionStmt) {
      DefinitionStmt defStmt = (DefinitionStmt) s;
      if (defStmt.getLeftOp().getType() instanceof RefLikeType) {
        handleRefTypeAssignment(defStmt, out);
      }
    }

    // now copy the computed info to all successors
    for (AnalysisInfo next : fallOut) {
      copy(out, next);
    }
    for (AnalysisInfo next : branchOuts) {
      copy(outBranch, next);
    }
  }

  /**
   * This can be overwritten by subclasses to mark a certain value as constantly non-null.
   *
   * @param v
   *          any value
   * @return true if it is known that this value (e.g. a method return value) is never null
   */
  protected boolean isAlwaysNonNull(Value v) {
    return false;
  }

  private void handleIfStmt(JIfStmt ifStmt, AnalysisInfo in, AnalysisInfo out, AnalysisInfo outBranch) {<FILL_FUNCTION_BODY>

    Value condition = ifStmt.getCondition();
    if (condition instanceof JInstanceOfExpr) {
      // a instanceof X ; if this succeeds, a is not null
      handleInstanceOfExpression((JInstanceOfExpr) condition, in, out, outBranch);
    } else if (condition instanceof JEqExpr || condition instanceof JNeExpr) {
      // a==b or a!=b
      handleEqualityOrNonEqualityCheck((AbstractBinopExpr) condition, in, out, outBranch);
    }
  
<methods>public void <init>(soot.toolkits.graph.UnitGraph) <variables>private static final org.slf4j.Logger logger