public void addParamBinding(Unit csUnit, SootMethod callee, SootMethod caller) {
    Pair<Unit, SootMethod> csKey = new Pair<Unit, SootMethod>(csUnit, callee);
    Map<RdValue, Set<Integer>> binding = callSite2binding.get(csKey);

    if (binding == null) {
      if (csUnit instanceof InvokeStmt) {
        binding = new HashMap<RdValue, Set<Integer>>();
        callSite2binding.put(csKey, binding);

        InvokeStmt invStmt = (InvokeStmt) csUnit;
        InvokeExpr invExpr = invStmt.getInvokeExpr();

        List /*ValueBox*/ argList = invExpr.getArgs();
        for (int i = 0; i < argList.size(); i++) {
          Value argValue = (Value) argList.get(i);
          // FIXME: argValue must be MutableRef ? by longwen 2012/2/22
          if (true || isMutableRefParam(argValue)) {
            Set<Integer> paramIndices = binding.get(argValue);
            if (paramIndices == null) {
              paramIndices = new HashSet<Integer>();
            }

            // for parameter bindings at call sites, we just
            // store the parameter indices. Using these indices,
            // we can get the formal parameters in the method body
            // when necessary (i.e., the analysis goes into the method)
            paramIndices.add(new Integer(i));

            // FIXME:  by longwen 2012/2/22
            binding.put(new RdValue(argValue, caller), paramIndices);
          }
        }
      } else {
        throw new RuntimeException(
            "The call site unit must be an instance of InvokeStmt:" + csUnit.toString());
      }
    } else {
      /*
       * there should be at most one binding for a call graph edge.
       */
      Debug.P(
          "WARNING: more than one binding exists for the call edge: "
              + csUnit
              + " --> "
              + callee.getSignature());
    }
  }
  /**
   * Return the entry node of method p
   *
   * @param p, the method of which the unique entry is returned
   * @return
   */
  public RdProgramPoint getEntry(SootMethod p) {
    UnitGraph graph = m2g.get(p);
    // if the method has not yet been indexed
    if (graph == null) {
      graph = buildAndIndexCFG(p);
    }

    List<Unit> heads = graph.getHeads();

    RdProgramPoint entryPoint = null;
    if (heads.size() == 1) {
      entryPoint = new RdProgramPoint(heads.get(0), p, true);
    } else {
      Debug.P("WARNING: the number of entry nodes of method: " + p + " is not 1!");
    }

    return entryPoint;
  }
  /**
   * Return the exit node of method p
   *
   * @param p, the method of which the unique exit is returned
   * @return
   */
  public RdProgramPoint getExit(SootMethod p) {
    UnitGraph graph = m2g.get(p);
    // if the method has not yet been indexed
    if (graph == null) {
      graph = buildAndIndexCFG(p);
    }

    List<Unit> tails = graph.getTails();

    RdProgramPoint exitPoint = null;
    if (tails.size() == 1) {
      exitPoint = new RdProgramPoint(tails.get(0), p, false);
    } else {
      Debug.P("WARNING: the number of exit nodes of method: " + p + " is not 1!");
    }

    return exitPoint;
  }