/// <summary>
    /// Bind the caller with the callee and simplify the resulting pointsToGraph
    /// by removing the load nodes that has been resolved (captured objects)
    /// </summary>
    /// <param name="callerPTG"></param>
    /// <param name="calleePTG"></param>
    /// <param name="vr"></param>
    /// <returns></returns>
    private void bindCallerWithCalleePTG(PTGraph callerPTG, PTGraph calleePTG,  Variable vr)
    {



      // Compute Edges
      Edges Inew = new Edges();
      foreach (Edge ie in calleePTG.I)
      {
        foreach (IPTAnalysisNode nu1 in RelatedExtended(ie.Src))
        {
          foreach (IPTAnalysisNode nu2 in RelatedExtended(ie.Dst))
          {
            Inew.AddIEdge(nu1, ie.Field, nu2);
          }
        }
      }
      // Compute Edges
      Edges Onew = new Edges();
      foreach (Edge oe in calleePTG.O)
      {
        foreach (IPTAnalysisNode nu1 in RelatedExtended(oe.Src))
        {
          if (!nu1.IsNull)
            Onew.AddOEdge(nu1, oe.Field, oe.Dst);
        }
      }


      // Compute Escape
      Nodes eNew = new Nodes();
      foreach (IPTAnalysisNode n in calleePTG.E)
      {
        eNew.AddRange(RelatedExtended(n));
      }

      callerPTG.I.AddEdges(Inew);
      callerPTG.O.AddEdges(Onew);
      callerPTG.E.AddRange(eNew);

      /// Assign vr = related(retValue) 


      Nodes argNodes = Nodes.Empty;
      if (callerThisRef != null)
      {
        // argNodes.Add(callerPTG.GetAddress(callerThisRef));
        argNodes.AddRange(callerPTG.GetLocations(callerThisRef));
      }
      if (calleePTG.Method.Parameters != null)
      {
        for (int i = 0; i < calleePTG.Method.Parameters.Count; i++)
        {
          Parameter p = calleePTG.Method.Parameters[i];
          PNode pn = calleePTG.ParameterMap[p];
          if (!pn.IsByValue)
          {
            if (arguments[i] is Variable)
            {
              Variable vArg = (Variable)arguments[i];
              bindRefOrOutParameter(callerPTG, calleePTG, arguments[i] as Variable, p);
            }
          }
          if (arguments[i] is Variable)
          {
            Variable vArg = (Variable)arguments[i];
            // PTAnalysisNode addrArg = callerPTG.GetAddress(vArg);
            // argNodes.Add(addrArg);
            argNodes.AddRange(callerPTG.GetLocations(vArg));
          }

        }
      }


      if (vr != null)
      {
        if (!vr.Type.IsPrimitive && calleePTG.RetValue != null)
        {
          callerPTG.AddVariable(vr, callerPTG.MethodLabel);

          Nodes relatedValues2 = Nodes.Empty;
          // PTAnalysisNode addrRetValue = calleePTG.GetAddress(calleePTG.RetValue);
          // foreach (PTAnalysisNode n2 in calleePTG.Values(addrRetValue))
          foreach (IPTAnalysisNode n2 in calleePTG.Values(calleePTG.GetLocations(calleePTG.RetValue)))
          {
            relatedValues2.AddRange(RelatedExtended(n2));
          }
          callerPTG.Assign(vr, relatedValues2, calleePTG.MethodLabel);

        }
        else
        {
          callerPTG.ForgetVariable(vr);
        }
      }

      // Now we can remove the load nodes that don't escape
      Set<LNode> lNodes = callerPTG.LoadNodes;
      // B = Nodes forward reachable from from Escaping, Parameters, callee Arguments and Global nodes
      Nodes B = callerPTG.ReachableFromParametersReturnAndGlobalsAnd(argNodes);

      foreach (LNode ln in lNodes)
      {
        Set<Edge> IToRemove = new Set<Edge>();
        Set<Edge> OToRemove = new Set<Edge>();
        // If the LoadNode is not reachable or it is captured 
        if (!B.Contains(ln) || (Related(ln).Count > 0))
        // if (!B.Contains(ln) || (ln.IsParameterValueLNode && (Related(ln).Count > 0 || !Related(ln).Contains(ln))))
        //if (!B.Contains(ln) /*&& (ln is LAddrFieldNode  */
        //    /*&& ln.Label.Method.Equals(callerPTG.Method)*/)
        {
          foreach (Edge ie in callerPTG.I.EdgesFromSrc(ln))
            IToRemove.Add(ie);
          foreach (Edge ie in callerPTG.I.EdgesFromDst(ln))
            IToRemove.Add(ie);
          foreach (Edge oe in callerPTG.O.EdgesFromDst(ln))
            OToRemove.Add(oe);
          foreach (Edge oe in callerPTG.O.EdgesFromSrc(ln))
            OToRemove.Add(oe);
          removedLoadNodes.Add(ln);
        }
        callerPTG.I.RemoveEdges(IToRemove);
        callerPTG.O.RemoveEdges(OToRemove);
      }


    }