@Override
    public void visitJavaScriptInvoke(JavaScriptInvoke invk) {
      // check whether this instruction corresponds to a function expression/declaration
      if (isFunctionConstructorInvoke(invk)) {
        int defn = invk.getDef();

        // the name of the function
        String fnName = symtab.getStringValue(invk.getUse(1));
        IClass fnClass =
            cha.lookupClass(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, fnName));
        if (fnClass == null) {
          System.err.println(
              "cannot find " + fnName + " at " + ((AstMethod) method).getSourcePosition());
          return;
        }
        IMethod fn = fnClass.getMethod(AstMethodReference.fnSelector);
        FuncVertex callee = factory.makeFuncVertex(fnClass);

        // look at all uses
        for (Iterator<SSAInstruction> uses = du.getUses(defn); uses.hasNext(); ) {
          SSAInstruction use = uses.next();

          // check whether this is a local call
          if (use instanceof JavaScriptInvoke && ((JavaScriptInvoke) use).getFunction() == defn) {
            JavaScriptInvoke use_invk = (JavaScriptInvoke) use;

            // yes, so add edges from arguments to parameters...
            for (int i = 2; i < use_invk.getNumberOfParameters(); ++i)
              flowgraph.addEdge(
                  factory.makeVarVertex(caller, use_invk.getUse(i)),
                  factory.makeParamVertex(callee, i - 1));

            // ...and from return to result
            flowgraph.addEdge(
                factory.makeRetVertex(callee), factory.makeVarVertex(caller, use.getDef()));

            // note: local calls are never qualified, so there is no flow into the receiver vertex
          } else {
            // no, it's a more complicated use, so add flows from/to unknown
            for (int i = 1; i < fn.getNumberOfParameters(); ++i)
              flowgraph.addEdge(factory.makeUnknownVertex(), factory.makeParamVertex(callee, i));
            flowgraph.addEdge(factory.makeRetVertex(callee), factory.makeUnknownVertex());
          }
        }
      } else {
        // this is a genuine function call; find out where the function came from
        SSAInstruction def = du.getDef(invk.getFunction());

        // if it's not a local call, add flows from/to unknown
        if (!(def instanceof JavaScriptInvoke)
            || !isFunctionConstructorInvoke((JavaScriptInvoke) def)) {
          for (int i = 1; i < invk.getNumberOfParameters(); ++i)
            flowgraph.addEdge(
                factory.makeVarVertex(caller, invk.getUse(i)), factory.makeUnknownVertex());
          flowgraph.addEdge(
              factory.makeUnknownVertex(), factory.makeVarVertex(caller, invk.getDef()));
        }
      }
    }
 public LocalCallSSAVisitor(IMethod method, SymbolTable symtab, DefUse du, FlowGraph flowgraph) {
   super(method, symtab, du);
   this.flowgraph = flowgraph;
   this.factory = flowgraph.getVertexFactory();
   this.caller = this.factory.makeFuncVertex(method.getDeclaringClass());
 }