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();
}
}
}
}
}
}
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");
}
}
}
}
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;
}
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;
}
}
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;
}
Aggregations