Search in sources :

Example 1 with Stmt

use of com.googlecode.dex2jar.ir.stmt.Stmt 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 Stmt

use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.

the class Ir2JRegAssignTransformer method genGraph.

private Reg[] genGraph(IrMethod method, final Reg[] regs) {
    Reg[] args;
    if (method.isStatic) {
        args = new Reg[method.args.length];
    } else {
        args = new Reg[method.args.length + 1];
    }
    Set<Stmt> tos = new HashSet<>();
    for (Stmt stmt : method.stmts) {
        if (stmt.st == ST.ASSIGN || stmt.st == ST.IDENTITY) {
            if (stmt.getOp1().vt == VT.LOCAL) {
                Local left = (Local) stmt.getOp1();
                Value op2 = stmt.getOp2();
                int idx = left._ls_index;
                Reg leftReg = regs[idx];
                // a new local can't effect next value live in next frame
                Cfg.collectTos(stmt, tos);
                for (Stmt next : tos) {
                    SimpleLiveValue[] frame = (SimpleLiveValue[]) next.frame;
                    if (frame == null) {
                        continue;
                    }
                    for (int i = 0; i < frame.length; i++) {
                        if (i == idx) {
                            continue;
                        }
                        SimpleLiveValue v = frame[i];
                        if (v != null && v.used) {
                            Reg rightReg = regs[i];
                            leftReg.excludes.add(rightReg);
                            rightReg.excludes.add(leftReg);
                        }
                    }
                }
                tos.clear();
                // Preferred same reg can save load-store
                if (op2.vt == VT.LOCAL) {
                    Reg rightReg = regs[((Local) op2)._ls_index];
                    leftReg.prefers.add(rightReg);
                    rightReg.prefers.add(leftReg);
                }
                // record @this @parameter_x
                if (op2.vt == VT.THIS_REF) {
                    args[0] = leftReg;
                } else if (op2.vt == VT.PARAMETER_REF) {
                    RefExpr refExpr = (RefExpr) op2;
                    if (method.isStatic) {
                        args[refExpr.parameterIndex] = leftReg;
                    } else {
                        args[refExpr.parameterIndex + 1] = leftReg;
                    }
                }
            }
        }
    }
    // remove the link between itself
    for (Reg reg : regs) {
        reg.excludes.remove(reg);
        reg.prefers.remove(reg);
    }
    return args;
}
Also used : SimpleLiveValue(com.googlecode.dex2jar.ir.ts.an.SimpleLiveValue) Value(com.googlecode.dex2jar.ir.expr.Value) SimpleLiveValue(com.googlecode.dex2jar.ir.ts.an.SimpleLiveValue) Local(com.googlecode.dex2jar.ir.expr.Local) RefExpr(com.googlecode.dex2jar.ir.expr.RefExpr) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt)

Example 3 with Stmt

use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.

the class Ir2JRegAssignTransformer method transform.

@Override
public void transform(IrMethod method) {
    if (method.locals.size() == 0) {
        return;
    }
    SimpleLiveAnalyze sa = new SimpleLiveAnalyze(method, true);
    sa.analyze();
    // init regs
    int maxLocalSize = sa.getLocalSize();
    final Reg[] regs = new Reg[maxLocalSize];
    for (Local local : method.locals) {
        Reg reg = new Reg();
        char type = local.valueType.charAt(0);
        if (type == '[') {
            type = 'L';
        }
        reg.type = type;
        local.tag = reg;
        regs[local._ls_index] = reg;
    }
    // gen graph
    Reg[] args = genGraph(method, regs);
    // fix up the graph, make sure @this is not share index with others
    if (!method.isStatic) {
        Reg atThis = args[0];
        for (Reg reg : regs) {
            if (reg == atThis) {
                continue;
            }
            reg.excludes.add(atThis);
            atThis.excludes.add(reg);
        }
    }
    {
        // assgin @this, @parameter_x from index 0
        int i = 0;
        int index = 0;
        if (!method.isStatic) {
            args[i++].reg = index++;
        }
        for (int j = 0; j < method.args.length; j++) {
            Reg reg = args[i++];
            String type = method.args[j];
            if (reg == null) {
                index++;
            } else {
                reg.reg = index++;
            }
            if ("J".equals(type) || "D".equals(type)) {
                index++;
            }
        }
    }
    Map<Character, List<Reg>> groups = groupAndCleanUpByType(regs);
    // type each group
    BitSet excludeColor = new BitSet();
    BitSet suggestColor = new BitSet();
    BitSet globalExcludes = new BitSet();
    BitSet usedInOneType = new BitSet();
    for (Map.Entry<Character, List<Reg>> e : groups.entrySet()) {
        List<Reg> assigns = e.getValue();
        Collections.sort(assigns, OrderRegAssignByPreferredSizeDesc);
        char type = e.getKey();
        boolean doubleOrLong = type == 'J' || type == 'D';
        for (Reg as : assigns) {
            if (as.reg < 0) {
                // need color
                initExcludeColor(excludeColor, as);
                excludeParameters(excludeColor, args, type);
                // exclude index used by other types
                excludeColor.or(globalExcludes);
                initSuggestColor(suggestColor, as);
                // first find a preferred color
                for (int i = suggestColor.nextSetBit(0); i >= 0; i = suggestColor.nextSetBit(i + 1)) {
                    if (doubleOrLong) {
                        // need 2
                        if (!excludeColor.get(i) && !excludeColor.get(i + 1)) {
                            as.reg = i;
                            break;
                        }
                    } else {
                        if (!excludeColor.get(i)) {
                            as.reg = i;
                            break;
                        }
                    }
                }
                if (as.reg < 0) {
                    if (doubleOrLong) {
                        int reg = -1;
                        do {
                            reg++;
                            reg = excludeColor.nextClearBit(reg);
                        } while (excludeColor.get(reg + 1));
                        as.reg = reg;
                    } else {
                        int reg = excludeColor.nextClearBit(0);
                        as.reg = reg;
                    }
                }
            }
            usedInOneType.set(as.reg);
            if (doubleOrLong) {
                usedInOneType.set(as.reg + 1);
            }
        }
        globalExcludes.or(usedInOneType);
        usedInOneType.clear();
    }
    for (Local local : method.locals) {
        Reg as = (Reg) local.tag;
        local._ls_index = as.reg;
        local.tag = null;
    }
    for (Stmt stmt : method.stmts) {
        stmt.frame = null;
    }
}
Also used : Local(com.googlecode.dex2jar.ir.expr.Local) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) SimpleLiveAnalyze(com.googlecode.dex2jar.ir.ts.an.SimpleLiveAnalyze)

Example 4 with Stmt

use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.

the class NewTransformer method replaceX.

void replaceX(IrMethod method) {
    final Map<Local, TObject> init = new HashMap<>();
    for (Stmt p : method.stmts) {
        if (p.st == ASSIGN && p.getOp1().vt == LOCAL && p.getOp2().vt == NEW) {
            // the stmt is a new assign stmt
            Local local = (Local) p.getOp1();
            init.put(local, new TObject(local, (AssignStmt) p));
        }
    }
    if (init.size() > 0) {
        final int size = Cfg.reIndexLocal(method);
        makeSureUsedBeforeConstructor(method, init, size);
        if (init.size() > 0) {
            replace0(method, init, size);
        }
        for (Stmt stmt : method.stmts) {
            stmt.frame = null;
        }
    }
}
Also used : AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt)

Example 5 with Stmt

use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.

the class NewTransformer method replace0.

void replace0(IrMethod method, Map<Local, TObject> init, int size) {
    Set<Local> toDelete = new HashSet<>();
    Local[] locals = new Local[size];
    for (Local local : method.locals) {
        locals[local._ls_index] = local;
    }
    // find all locals to delete
    for (TObject obj : init.values()) {
        Vx[] frame = (Vx[]) obj.invokeStmt.frame;
        for (int i = 0; i < frame.length; i++) {
            Vx s = frame[i];
            if (s != null && s.obj == obj) {
                toDelete.add(locals[i]);
            }
        }
    }
    // delete the locals
    for (Iterator<Stmt> it = method.stmts.iterator(); it.hasNext(); ) {
        Stmt p = it.next();
        if (p.st == ASSIGN && p.getOp1().vt == LOCAL) {
            if (toDelete.contains((Local) p.getOp1())) {
                it.remove();
            }
        }
    }
    // add the locals back
    for (TObject obj : init.values()) {
        Vx[] frame = (Vx[]) obj.invokeStmt.frame;
        for (int i = 0; i < frame.length; i++) {
            Vx s = frame[i];
            if (s != null && s.obj == obj) {
                Local b = locals[i];
                if (b != obj.local) {
                    method.stmts.insertAfter(obj.invokeStmt, Stmts.nAssign(b, obj.local));
                }
            }
        }
        InvokeExpr ie = findInvokeExpr(obj.invokeStmt, null);
        Value[] orgOps = ie.getOps();
        Value[] nOps = new Value[orgOps.length - 1];
        System.arraycopy(orgOps, 1, nOps, 0, nOps.length);
        InvokeExpr invokeNew = Exprs.nInvokeNew(nOps, ie.args, ie.owner);
        method.stmts.replace(obj.invokeStmt, Stmts.nAssign(obj.local, invokeNew));
    }
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt)

Aggregations

Stmt (com.googlecode.dex2jar.ir.stmt.Stmt)41 LabelStmt (com.googlecode.dex2jar.ir.stmt.LabelStmt)31 Local (com.googlecode.dex2jar.ir.expr.Local)23 AssignStmt (com.googlecode.dex2jar.ir.stmt.AssignStmt)22 Test (org.junit.Test)10 Value (com.googlecode.dex2jar.ir.expr.Value)8 ArrayList (java.util.ArrayList)7 JumpStmt (com.googlecode.dex2jar.ir.stmt.JumpStmt)4 Cfg (com.googlecode.dex2jar.ir.ts.Cfg)4 Trap (com.googlecode.dex2jar.ir.Trap)3 StmtList (com.googlecode.dex2jar.ir.stmt.StmtList)3 List (java.util.List)3 StmtTraveler (com.googlecode.dex2jar.ir.StmtTraveler)2 Constant (com.googlecode.dex2jar.ir.expr.Constant)2 PhiExpr (com.googlecode.dex2jar.ir.expr.PhiExpr)2 E2Stmt (com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt)2 HashSet (java.util.HashSet)2 IR2JConverter (com.googlecode.d2j.converter.IR2JConverter)1 DexFileNode (com.googlecode.d2j.node.DexFileNode)1 DexMethodNode (com.googlecode.d2j.node.DexMethodNode)1