Search in sources :

Example 1 with PhiExpr

use of com.googlecode.dex2jar.ir.expr.PhiExpr in project dex2jar by pxb1988.

the class DeadCodeTransformer method transform.

@Override
public void transform(IrMethod method) {
    Cfg.createCFG(method);
    Cfg.dfsVisit(method, null);
    if (method.traps != null) {
        for (Iterator<Trap> it = method.traps.iterator(); it.hasNext(); ) {
            Trap t = it.next();
            boolean allNotThrow = true;
            for (Stmt p = t.start; p != t.end; p = p.getNext()) {
                if (p.visited && Cfg.isThrow(p)) {
                    allNotThrow = false;
                    break;
                }
            }
            if (allNotThrow) {
                it.remove();
                continue;
            }
            boolean allNotVisited = true;
            boolean allVisited = true;
            for (LabelStmt labelStmt : t.handlers) {
                if (labelStmt.visited) {
                    allNotVisited = false;
                } else {
                    allVisited = false;
                }
            }
            if (allNotVisited) {
                it.remove();
            } else {
                // keep start and end
                t.start.visited = true;
                t.end.visited = true;
                if (!allVisited) {
                    // part visited
                    List<String> types = new ArrayList<>(t.handlers.length);
                    List<LabelStmt> labelStmts = new ArrayList<>(t.handlers.length);
                    for (int i = 0; i < t.handlers.length; i++) {
                        labelStmts.add(t.handlers[i]);
                        types.add(t.types[i]);
                    }
                    t.handlers = labelStmts.toArray(new LabelStmt[labelStmts.size()]);
                    t.types = types.toArray(new String[types.size()]);
                }
            }
        }
    }
    Set<Local> definedLocals = new HashSet<>();
    for (Iterator<Stmt> it = method.stmts.iterator(); it.hasNext(); ) {
        Stmt p = it.next();
        if (!p.visited) {
            it.remove();
            continue;
        }
        if (p.st == Stmt.ST.ASSIGN || p.st == Stmt.ST.IDENTITY) {
            if (p.getOp1().vt == Value.VT.LOCAL) {
                definedLocals.add((Local) p.getOp1());
            }
        }
    }
    if (method.phiLabels != null) {
        for (Iterator<LabelStmt> it = method.phiLabels.iterator(); it.hasNext(); ) {
            LabelStmt labelStmt = it.next();
            if (!labelStmt.visited) {
                it.remove();
                continue;
            }
            if (labelStmt.phis != null) {
                for (AssignStmt phi : labelStmt.phis) {
                    definedLocals.add((Local) phi.getOp1());
                }
            }
        }
    }
    method.locals.clear();
    method.locals.addAll(definedLocals);
    Set<Value> tmp = new HashSet<>();
    if (method.phiLabels != null) {
        for (Iterator<LabelStmt> it = method.phiLabels.iterator(); it.hasNext(); ) {
            LabelStmt labelStmt = it.next();
            if (labelStmt.phis != null) {
                for (AssignStmt phi : labelStmt.phis) {
                    PhiExpr phiExpr = (PhiExpr) phi.getOp2();
                    boolean needRebuild = false;
                    for (Value v : phiExpr.getOps()) {
                        if (!definedLocals.contains(v)) {
                            needRebuild = true;
                            break;
                        }
                    }
                    if (needRebuild) {
                        for (Value v : phiExpr.getOps()) {
                            if (definedLocals.contains(v)) {
                                tmp.add(v);
                            }
                        }
                        phiExpr.setOps(tmp.toArray(new Value[tmp.size()]));
                        tmp.clear();
                    }
                }
            }
        }
    }
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Local(com.googlecode.dex2jar.ir.expr.Local) Trap(com.googlecode.dex2jar.ir.Trap) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) PhiExpr(com.googlecode.dex2jar.ir.expr.PhiExpr) Value(com.googlecode.dex2jar.ir.expr.Value)

Example 2 with PhiExpr

use of com.googlecode.dex2jar.ir.expr.PhiExpr in project dex2jar by pxb1988.

the class UnSSATransformer method fixPhi.

/**
     * there is somewhere both a and its possible x is both live, insert a=x, will change the meaning for example
     * 
     * <pre>
     *                      L0:
     *                      a = phi(b, ... )
     *                      b = 234;
     *                      if a>0 goto L0: // a, b both live here
     *                      ...
     * </pre>
     * 
     * after insert a=b before the if stmt, the programe change to
     * 
     * <pre>
     *                      L0:
     *                      // a = phi(b, ... )
     *                      b = 234;
     *                      a = b
     *                      if a>0 goto L0:
     *                      ...
     * </pre>
     * 
     * the solution is by introduce a new local x
     * 
     * <pre>
     *                      L0:
     *                      x = phi(b, ... )
     *                      a = x
     *                      b = 234;
     *                      if a>0 goto L0: // a, b both live here
     *                      ...
     * </pre>
     * 
     * insert x = b is ok now
     * 
     * <pre>
     *                      L0:
     *                      // x = phi(b, ... )
     *                      a = x
     *                      b = 234;
     *                      x = b
     *                      if a>0 goto L0: // a, b both live here
     *                      ...
     * </pre>
     * 
     * @param phiLabels
     */
private void fixPhi(IrMethod method, Collection<LabelStmt> phiLabels) {
    for (LabelStmt labelStmt : phiLabels) {
        List<AssignStmt> phis = (List<AssignStmt>) labelStmt.phis;
        for (AssignStmt phi : phis) {
            Local a = (Local) phi.getOp1();
            PhiExpr b = (PhiExpr) phi.getOp2();
            boolean introduceNewLocal = false;
            RegAssign aReg = (RegAssign) a.tag;
            for (Value op : b.getOps()) {
                RegAssign bReg = (RegAssign) ((Local) op).tag;
                if (aReg.excludes.contains(bReg)) {
                    introduceNewLocal = true;
                    break;
                }
            }
            if (introduceNewLocal) {
                Local newLocal = (Local) a.clone();
                if (DEBUG) {
                    newLocal.debugName = "x" + method.locals.size();
                }
                phi.op1 = newLocal;
                RegAssign newRegAssign = new RegAssign();
                newLocal.tag = newRegAssign;
                method.locals.add(newLocal);
                Stmt newAssigStmt = Stmts.nAssign(a, newLocal);
                Stmt next = labelStmt.getNext();
                if (next != null && next.st == ST.IDENTITY && next.getOp2().vt == VT.EXCEPTION_REF) {
                    // it's a handler, insert after the exception ref
                    method.stmts.insertAfter(next, newAssigStmt);
                } else {
                    method.stmts.insertAfter(labelStmt, newAssigStmt);
                }
                LiveV[] frame = (LiveV[]) labelStmt.frame;
                if (DEBUG) {
                    LiveV[] copy = frame.clone();
                    LiveV n = new LiveV();
                    n.local = a;
                    n.used = true;
                    copy[a._ls_index] = new LiveV();
                    newAssigStmt.frame = copy;
                }
                LiveV thePhi = frame[a._ls_index];
                thePhi.local = newLocal;
                for (LiveV v : frame) {
                    if (v != null && v.used) {
                        RegAssign s = (RegAssign) v.local.tag;
                        s.excludes.add(newRegAssign);
                        newRegAssign.excludes.add(s);
                    }
                }
            }
        }
    }
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) PhiExpr(com.googlecode.dex2jar.ir.expr.PhiExpr) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Value(com.googlecode.dex2jar.ir.expr.Value) AnalyzeValue(com.googlecode.dex2jar.ir.ts.an.AnalyzeValue) Local(com.googlecode.dex2jar.ir.expr.Local) StmtList(com.googlecode.dex2jar.ir.stmt.StmtList) ArrayList(java.util.ArrayList) List(java.util.List) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) JumpStmt(com.googlecode.dex2jar.ir.stmt.JumpStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt)

Aggregations

Local (com.googlecode.dex2jar.ir.expr.Local)2 PhiExpr (com.googlecode.dex2jar.ir.expr.PhiExpr)2 Value (com.googlecode.dex2jar.ir.expr.Value)2 AssignStmt (com.googlecode.dex2jar.ir.stmt.AssignStmt)2 LabelStmt (com.googlecode.dex2jar.ir.stmt.LabelStmt)2 Stmt (com.googlecode.dex2jar.ir.stmt.Stmt)2 Trap (com.googlecode.dex2jar.ir.Trap)1 JumpStmt (com.googlecode.dex2jar.ir.stmt.JumpStmt)1 StmtList (com.googlecode.dex2jar.ir.stmt.StmtList)1 AnalyzeValue (com.googlecode.dex2jar.ir.ts.an.AnalyzeValue)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1