void doWeave(
      SootMethod method,
      LocalGeneratorEx lg,
      AdviceApplication adviceappl,
      Residue residue,
      WeavingContext wc) {
    AdviceInliner.v().addShadowMethod(method);
    ShadowPoints shadowpoints = adviceappl.shadowmatch.sp;
    AbstractAdviceDecl advicedecl = adviceappl.advice;

    Body b = method.getActiveBody();
    Chain units = b.getUnits().getNonPatchingChain();

    // end of shadow
    Stmt endshadow = shadowpoints.getEnd();

    NopStmt nop2 = Jimple.v().newNopStmt();
    GotoStmt goto1 = Jimple.v().newGotoStmt(nop2);
    if (advicedecl instanceof CflowSetup) {
      Tagger.tagStmt(goto1, InstructionKindTag.CFLOW_EXIT);
    } else if (advicedecl instanceof PerCflowSetup) {
      Tagger.tagStmt(goto1, InstructionKindTag.PERCFLOW_EXIT);
    } else if (advicedecl instanceof DeclareSoft) {
      Tagger.tagStmt(goto1, InstructionKindTag.EXCEPTION_SOFTENER);
    } else if (advicedecl instanceof DeclareMessage) {
      Tagger.tagStmt(goto1, InstructionKindTag.DECLARE_MESSAGE);
    } else {
      Tagger.tagStmt(goto1, InstructionKindTag.AFTER_THROWING_HANDLER);
    }
    Tagger.tagStmt(goto1, new InstructionSourceTag(advicedecl.sourceId));
    Tagger.tagStmt(goto1, new InstructionShadowTag(adviceappl.shadowmatch.shadowId));
    units.insertBefore(nop2, endshadow);
    units.insertBefore(goto1, nop2);

    // have ...
    //    goto1:      goto nop2;
    //    nop2:       nop;
    //    endshadow:  nop;

    RefType catchType = getCatchType();
    Local exception = lg.generateLocal(catchType, "exception");
    bindException(wc, advicedecl, exception);

    CaughtExceptionRef exceptRef = Jimple.v().newCaughtExceptionRef();
    IdentityStmt idStmt = Jimple.v().newIdentityStmt(exception, exceptRef);
    units.insertAfter(idStmt, goto1);

    ThrowStmt throwStmt = Jimple.v().newThrowStmt(exception);
    throwStmt.addTag(new ThrowCreatedByCompilerTag());

    if (advicedecl instanceof CflowSetup) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.CFLOW_EXIT);
    } else if (advicedecl instanceof PerCflowSetup) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.PERCFLOW_EXIT);
    } else if (advicedecl instanceof DeclareSoft) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.EXCEPTION_SOFTENER);
    } else if (advicedecl instanceof DeclareMessage) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.DECLARE_MESSAGE);
    } else {
      Tagger.tagStmt(throwStmt, InstructionKindTag.AFTER_THROWING_HANDLER);
    }
    Tagger.tagStmt(throwStmt, new InstructionSourceTag(advicedecl.sourceId));
    Tagger.tagStmt(throwStmt, new InstructionShadowTag(adviceappl.shadowmatch.shadowId));

    // store shadow/source tag for this residue in weaving context
    if (advicedecl instanceof CflowSetup) {
      wc.setKindTag(InstructionKindTag.CFLOW_TEST);
    }
    if (advicedecl instanceof PerCflowSetup) {
      wc.setKindTag(InstructionKindTag.CFLOW_TEST);
    }
    wc.setShadowTag(new InstructionShadowTag(adviceappl.shadowmatch.shadowId));
    wc.setSourceTag(new InstructionSourceTag(adviceappl.advice.sourceId));

    Stmt endresidue = residue.codeGen(method, lg, units, idStmt, throwStmt, true, wc);

    // have ...
    //    java.lang.Exception exception;
    //
    //    goto1:      goto nop2;
    //    idStmt:     exception := @caughtexception
    //    nop2:       nop;
    //    endshadow:  nop;

    units.insertAfter(throwStmt, endresidue);

    Chain invokestmts = advicedecl.makeAdviceExecutionStmts(adviceappl, lg, wc);

    for (Iterator stmtlist = invokestmts.iterator(); stmtlist.hasNext(); ) {
      Stmt nextstmt = (Stmt) stmtlist.next();
      units.insertBefore(nextstmt, throwStmt);
    }

    if (method.getName().equals("<clinit>"))
    // have to handle case of ExceptionInInitialzerError
    { //  if (exception instanceof java.lang.ExceptionInIntializerError)
      //     throw (exception);
      debug("Adding extra check in clinit");

      Local isInitError = lg.generateLocal(soot.BooleanType.v(), "isInitError");

      Stmt assignbool =
          Jimple.v()
              .newAssignStmt(
                  isInitError,
                  Jimple.v()
                      .newInstanceOfExpr(
                          exception, RefType.v("java.lang.ExceptionInInitializerError")));

      Stmt ifstmt =
          Jimple.v().newIfStmt(Jimple.v().newNeExpr(isInitError, IntConstant.v(0)), throwStmt);

      //	     ThrowStmt throwInitError = Jimple.v().newThrowStmt(exception);

      //	     units.insertAfter(throwInitError, idStmt);
      units.insertAfter(ifstmt, idStmt);
      units.insertAfter(assignbool, idStmt);
    }

    Stmt beginshadow = shadowpoints.getBegin();
    Stmt begincode = (Stmt) units.getSuccOf(beginshadow);

    // have ...
    //    java.lang.Exception exception;
    //    <AspectType> theAspect;
    //
    //    beginshadow:   nop
    //    begincode:     <some statement>
    //       ....        <stuff in between>
    //    goto1:         goto nop2;
    //    idStmt:        exception := @caughtexception;
    //    assignStmt:    theAspect = new AspectOf();
    //             .... invoke statements ....
    //    throwStmt:     throw exception;
    //    nop2:          nop;
    //    endshadow:     nop;

    Chain traps = b.getTraps();
    Trap t = traps.size() > 0 ? (Trap) traps.getFirst() : null;

    // assume no exception ranges overlap with this one; make sure
    // we go after any that would be enclosed within this one.
    while (t != null
        && (units.follows(t.getBeginUnit(), begincode)
            || (t.getBeginUnit() == begincode && units.follows(idStmt, t.getEndUnit()))))
      t = (Trap) traps.getSuccOf(t);

    Trap newt = Jimple.v().newTrap(catchType.getSootClass(), begincode, idStmt, idStmt);

    if (t == null) traps.addLast(newt);
    else traps.insertBefore(newt, t);

    //  added
    //     catch java.lang.Throwable
    //         from begincode upto idStmt handlewith idStmt

  } // method doWeave
  /**
   * This method pushes all newExpr down to be the stmt directly before every invoke of the init
   * only if they are in the types list
   */
  public void internalTransform(Body b, String phaseName, Map options) {
    JimpleBody body = (JimpleBody) b;

    if (Options.v().verbose())
      G.v().out.println("[" + body.getMethod().getName() + "] Folding Jimple constructors...");

    Chain units = body.getUnits();
    List<Unit> stmtList = new ArrayList<Unit>();
    stmtList.addAll(units);

    Iterator<Unit> it = stmtList.iterator();
    Iterator<Unit> nextStmtIt = stmtList.iterator();
    // start ahead one
    nextStmtIt.next();

    SmartLocalDefs localDefs = SmartLocalDefsPool.v().getSmartLocalDefsFor(body);
    UnitGraph graph = localDefs.getGraph();
    LocalUses localUses = new SimpleLocalUses(graph, localDefs);

    /* fold in NewExpr's with specialinvoke's */
    while (it.hasNext()) {
      Stmt s = (Stmt) it.next();

      if (!(s instanceof AssignStmt)) continue;

      /* this should be generalized to ArrayRefs */
      // only deal with stmts that are an local = newExpr
      Value lhs = ((AssignStmt) s).getLeftOp();
      if (!(lhs instanceof Local)) continue;

      Value rhs = ((AssignStmt) s).getRightOp();
      if (!(rhs instanceof NewExpr)) continue;

      // check if very next statement is invoke -->
      // this indicates there is no control flow between
      // new and invoke and should do nothing
      if (nextStmtIt.hasNext()) {
        Stmt next = (Stmt) nextStmtIt.next();
        if (next instanceof InvokeStmt) {
          InvokeStmt invoke = (InvokeStmt) next;

          if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) {
            SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke.getInvokeExpr();
            if (invokeExpr.getBase() == lhs) {
              break;
            }
          }
        }
      }

      // check if new is in the types list - only process these
      if (!types.contains(((NewExpr) rhs).getType())) continue;

      List lu = localUses.getUsesOf(s);
      Iterator luIter = lu.iterator();
      boolean MadeNewInvokeExpr = false;

      while (luIter.hasNext()) {
        Unit use = ((UnitValueBoxPair) (luIter.next())).unit;
        if (!(use instanceof InvokeStmt)) continue;
        InvokeStmt is = (InvokeStmt) use;
        if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr)
            || lhs != ((SpecialInvokeExpr) is.getInvokeExpr()).getBase()) continue;

        // make a new one here
        AssignStmt constructStmt =
            Jimple.v()
                .newAssignStmt(((DefinitionStmt) s).getLeftOp(), ((DefinitionStmt) s).getRightOp());
        constructStmt.setRightOp(Jimple.v().newNewExpr(((NewExpr) rhs).getBaseType()));
        MadeNewInvokeExpr = true;

        // redirect jumps
        use.redirectJumpsToThisTo(constructStmt);
        // insert new one here
        units.insertBefore(constructStmt, use);

        constructStmt.addTag(s.getTag("SourceLnPosTag"));
      }
      if (MadeNewInvokeExpr) {
        units.remove(s);
      }
    }
  }