private void visitNode(
      Set<Object> gray,
      Object obj,
      LinkedList<Object> changedUnits,
      HashSet<Object> changedUnitsSet) {

    gray.add(obj);
    changedUnits.addLast(obj);
    changedUnitsSet.add(obj);
    nodes.add(obj);
    valueBefore.add(newInitialFlow());
    valueAfter.add(newInitialFlow());
    Iterator succsIt = graph.getSuccsOf(obj).iterator();
    if (g.getSuccsOf(obj).size() > 0) {
      while (succsIt.hasNext()) {
        Object succ = succsIt.next();
        if (!gray.contains(succ)) {

          visitNode(gray, succ, changedUnits, changedUnitsSet);
        }
      }
    }
  }
  protected void doAnalysis() {
    LinkedList<Object> changedUnits = new LinkedList<Object>();
    HashSet<Object> changedUnitsSet = new HashSet<Object>();

    int numNodes = graph.size();
    int numComputations = 0;

    // Set initial values and nodes to visit.

    createWorkList(changedUnits, changedUnitsSet);

    // testWorkList(changedUnits);

    // Set initial values for entry points
    {
      Iterator it = graph.getHeads().iterator();

      while (it.hasNext()) {
        Object s = it.next();

        // unitToBeforeFlow.put(s, entryInitialFlow());
        nodes.add(s);
        valueBefore.add(entryInitialFlow());
      }
    }

    // Perform fixed point flow analysis
    {
      Object previousAfterFlow = newInitialFlow();

      while (!changedUnits.isEmpty()) {
        Object beforeFlow;
        Object afterFlow;

        Object s = changedUnits.removeFirst();
        Tag tag = (Tag) ((JPegStmt) s).getTags().get(0);
        // System.out.println("===unit is: "+tag+" "+s);
        changedUnitsSet.remove(s);

        // copy(unitToAfterFlow.get(s), previousAfterFlow);
        // add for debug april 6
        int pos = nodes.indexOf(s);
        copy(valueAfter.elementAt(pos), previousAfterFlow);
        // end add for debug april
        // Compute and store beforeFlow
        {
          List preds = graph.getPredsOf(s);

          // beforeFlow = unitToBeforeFlow.get(s);

          beforeFlow = valueBefore.elementAt(pos);

          if (preds.size() == 1) {
            // copy(unitToAfterFlow.get(preds.get(0)), beforeFlow);
            copy(valueAfter.elementAt(nodes.indexOf(preds.get(0))), beforeFlow);
          } else if (preds.size() != 0) {
            Iterator predIt = preds.iterator();
            Object obj = predIt.next();

            // copy(unitToAfterFlow.get(obj), beforeFlow);
            copy(valueAfter.elementAt(nodes.indexOf(obj)), beforeFlow);

            while (predIt.hasNext()) {
              JPegStmt stmt = (JPegStmt) predIt.next();
              if (stmt.equals(obj)) {
                // System.out.println("!!!same object!!!");
                continue;
              }
              Tag tag1 = (Tag) stmt.getTags().get(0);
              // System.out.println("pred: "+tag1+" "+stmt);

              // Object otherBranchFlow = unitToAfterFlow.get(stmt);
              if (nodes.indexOf(stmt) >= 0) // RLH
              {
                Object otherBranchFlow = valueAfter.elementAt(nodes.indexOf(stmt));

                merge(beforeFlow, otherBranchFlow, beforeFlow);
              }
            }
          }
        }

        // Compute afterFlow and store it.
        {
          // afterFlow = unitToAfterFlow.get(s);
          afterFlow = valueAfter.elementAt(nodes.indexOf(s));
          flowThrough(beforeFlow, s, afterFlow);

          // unitToAfterFlow.put(s, afterFlow);
          valueAfter.set(nodes.indexOf(s), afterFlow);
          // System.out.println("update afterFlow nodes: "+s);
          // System.out.println("afterFlow: "+afterFlow);
          // ((MonitorSet)unitToAfterFlow.get(s)).test();

          numComputations++;
        }

        // Update queue appropriately

        if (!afterFlow.equals(previousAfterFlow)) {

          Iterator succIt = graph.getSuccsOf(s).iterator();

          while (succIt.hasNext()) {
            Object succ = succIt.next();

            if (!changedUnitsSet.contains(succ)) {
              changedUnits.addLast(succ);
              changedUnitsSet.add(succ);
              /*if (succ instanceof JPegStmt){
              Tag tag1 = (Tag)((JPegStmt)succ).getTags().get(0);

              System.out.println("add to worklist: "+tag1+" "+succ);
              }
              else
              System.out.println("add to worklist: "+succ);
              */
            }
          }
        }
      }
    }

    // G.v().out.println(graph.getBody().getMethod().getSignature() + " numNodes: " + numNodes +
    //    " numComputations: " + numComputations + " avg: " + Main.truncatedOf((double)
    // numComputations / numNodes, 2));

    Timers.v().totalFlowNodes += numNodes;
    Timers.v().totalFlowComputations += numComputations;
  }