Search in sources :

Example 1 with Local

use of com.googlecode.dex2jar.ir.expr.Local 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 Local

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

the class FixVar method transform.

@Override
public void transform(IrMethod irMethod) {
    int i = 0;
    for (LocalVar var : irMethod.vars) {
        if (var.reg.trim().vt != VT.LOCAL) {
            if (var.reg.trim().vt == VT.CONSTANT) {
                Local n = new Local(i++);
                Value old = var.reg.trim();
                irMethod.stmts.insertBefore(var.start, Stmts.nAssign(n, old));
                var.reg = n;
                irMethod.locals.add(n);
            } else {
            // throw new DexExcpeption("not support");
            }
        }
    }
}
Also used : Value(com.googlecode.dex2jar.ir.expr.Value) Local(com.googlecode.dex2jar.ir.expr.Local) LocalVar(com.googlecode.dex2jar.ir.LocalVar)

Example 3 with Local

use of com.googlecode.dex2jar.ir.expr.Local 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 4 with Local

use of com.googlecode.dex2jar.ir.expr.Local 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 5 with Local

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

the class AggTransformer method simpleMergeLocals.

/**
     * if a local is only used in one place, and the value is isLocationInsensitive,
     * remove the local and replace it with its value
     * <pre>
     *     a=b+c
     *     d=a+e
     * </pre>
     * to
     * <pre>
     *     d=(b+c)+e
     * </pre>
     */
private boolean simpleMergeLocals(IrMethod method, boolean changed, Set<Stmt> locationSensitiveStmts) {
    if (method.locals.size() == 0) {
        return false;
    }
    final int[] readCounts = Cfg.countLocalReads(method);
    Set<Local> useInPhi = collectLocalUsedInPhi(method);
    final Map<Local, Value> toReplace = new HashMap<>();
    for (Iterator<Stmt> it = method.stmts.iterator(); it.hasNext(); ) {
        Stmt p = it.next();
        if (p.st == Stmt.ST.ASSIGN && p.getOp1().vt == Value.VT.LOCAL) {
            Local local = (Local) p.getOp1();
            if (useInPhi.contains(local)) {
                continue;
            }
            if (readCounts[local._ls_index] < 2) {
                Value op2 = p.getOp2();
                if (isLocationInsensitive(op2)) {
                    method.locals.remove(local);
                    toReplace.put(local, op2);
                    it.remove();
                    changed = true;
                } else {
                    locationSensitiveStmts.add(p);
                }
            }
        }
    }
    Cfg.TravelCallBack tcb = new Cfg.TravelCallBack() {

        @Override
        public Value onAssign(Local v, AssignStmt as) {
            return v;
        }

        @Override
        public Value onUse(Local v) {
            Value v2 = toReplace.get(v);
            if (v2 != null) {
                return v2;
            }
            return v;
        }
    };
    modReplace(toReplace, tcb);
    Cfg.travelMod(method.stmts, tcb, false);
    return changed;
}
Also used : AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Value(com.googlecode.dex2jar.ir.expr.Value) Local(com.googlecode.dex2jar.ir.expr.Local) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt)

Aggregations

Local (com.googlecode.dex2jar.ir.expr.Local)86 Test (org.junit.Test)44 LabelStmt (com.googlecode.dex2jar.ir.stmt.LabelStmt)28 Stmt (com.googlecode.dex2jar.ir.stmt.Stmt)23 Value (com.googlecode.dex2jar.ir.expr.Value)19 AssignStmt (com.googlecode.dex2jar.ir.stmt.AssignStmt)15 ArrayList (java.util.ArrayList)8 IrMethod (com.googlecode.dex2jar.ir.IrMethod)6 Exprs.nLocal (com.googlecode.dex2jar.ir.expr.Exprs.nLocal)6 UnopStmt (com.googlecode.dex2jar.ir.stmt.UnopStmt)6 JumpStmt (com.googlecode.dex2jar.ir.stmt.JumpStmt)5 ConstTransformer (com.googlecode.dex2jar.ir.ts.ConstTransformer)5 Exprs.nString (com.googlecode.dex2jar.ir.expr.Exprs.nString)4 StmtList (com.googlecode.dex2jar.ir.stmt.StmtList)4 Trap (com.googlecode.dex2jar.ir.Trap)3 Exprs.nArrayValue (com.googlecode.dex2jar.ir.expr.Exprs.nArrayValue)3 AnalyzeValue (com.googlecode.dex2jar.ir.ts.an.AnalyzeValue)3 List (java.util.List)3 DexLabel (com.googlecode.d2j.DexLabel)2 Op (com.googlecode.d2j.reader.Op)2