use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class FillArrayTransformer method makeSureArrayUsedAfterAllElementAssigned0.
private void makeSureArrayUsedAfterAllElementAssigned0(IrMethod method, final Map<Local, ArrayObject> arraySizes) {
int i = 0;
for (Local local : arraySizes.keySet()) {
local._ls_index = i++;
}
final int size = i;
final List<ArrayObjectValue> values = new ArrayList<>();
Cfg.dfs(method.stmts, new Cfg.FrameVisitor<ArrayObjectValue[]>() {
@Override
public ArrayObjectValue[] merge(ArrayObjectValue[] srcFrame, ArrayObjectValue[] distFrame, Stmt src, Stmt dist) {
if (distFrame == null) {
distFrame = new ArrayObjectValue[size];
for (int i = 0; i < size; i++) {
ArrayObjectValue arc = srcFrame[i];
if (arc != null) {
ArrayObjectValue aov = new ArrayObjectValue(arc.local);
values.add(aov);
aov.array = arc.array;
aov.parent = arc;
aov.pos = (BitSet) arc.pos.clone();
distFrame[i] = aov;
}
}
} else {
for (int i = 0; i < size; i++) {
ArrayObjectValue arc = srcFrame[i];
ArrayObjectValue aov = distFrame[i];
if (arc != null && aov != null) {
if (aov.otherParent == null) {
aov.otherParent = new HashSet<>();
}
aov.otherParent.add(arc);
}
}
}
return distFrame;
}
@Override
public ArrayObjectValue[] initFirstFrame(Stmt first) {
return new ArrayObjectValue[size];
}
ArrayObjectValue[] tmp = initFirstFrame(null);
Stmt currentStmt;
@Override
public ArrayObjectValue[] exec(ArrayObjectValue[] frame, Stmt stmt) {
currentStmt = stmt;
System.arraycopy(frame, 0, tmp, 0, size);
if (stmt.st == Stmt.ST.FILL_ARRAY_DATA) {
if (stmt.getOp1().vt == Value.VT.LOCAL) {
Local local = (Local) stmt.getOp1();
if (local._ls_index >= 0) {
ArrayObjectValue av = tmp[local._ls_index];
Constant cst = (Constant) stmt.getOp2();
int endPos = Array.getLength(cst.value);
av.pos.set(0, endPos);
}
} else {
use(stmt.getOp1());
}
} else if (stmt.st == Stmt.ST.ASSIGN && stmt.getOp1().vt == Value.VT.ARRAY) {
use(stmt.getOp2());
ArrayExpr ae = (ArrayExpr) stmt.getOp1();
if (ae.getOp1().vt == Value.VT.LOCAL) {
Local local = (Local) ae.getOp1();
if (local._ls_index >= 0) {
int index = ((Number) ((Constant) ae.getOp2()).value).intValue();
ArrayObjectValue av = tmp[local._ls_index];
av.pos.set(index);
} else {
use(ae);
}
} else {
use(ae);
}
} else if (stmt.st == Stmt.ST.ASSIGN && stmt.getOp1().vt == Value.VT.LOCAL) {
Local local = (Local) stmt.getOp1();
use(stmt.getOp2());
if (local._ls_index >= 0) {
ArrayObjectValue aov = new ArrayObjectValue(local);
aov.array = arraySizes.get(local);
aov.pos = new BitSet();
values.add(aov);
tmp[local._ls_index] = aov;
}
} else {
switch(stmt.et) {
case E0:
break;
case E1:
use(stmt.getOp());
break;
case E2:
use(stmt.getOp1());
use(stmt.getOp2());
break;
case En:
throw new RuntimeException();
}
}
return tmp;
}
private void use(Value v) {
switch(v.et) {
case E0:
if (v.vt == Value.VT.LOCAL) {
Local local = (Local) v;
if (local._ls_index >= 0) {
ArrayObjectValue aov = tmp[local._ls_index];
aov.array.used.add(currentStmt);
aov.used = true;
}
}
break;
case E1:
use(v.getOp());
break;
case E2:
use(v.getOp1());
use(v.getOp2());
break;
case En:
for (Value op : v.getOps()) {
use(op);
}
break;
}
}
});
Set<ArrayObjectValue> used = markUsed(values);
// check if ArrayObjectValue have different parent assignment
for (ArrayObjectValue avo : used) {
if (avo.array.used.size() > 1) {
arraySizes.remove(avo.local);
} else {
if (avo.parent != null && avo.otherParent != null) {
// BitSet bs = avo.pos;
BitSet p = avo.parent.pos;
for (ArrayObjectValue ps : avo.otherParent) {
if (!p.equals(ps.pos)) {
arraySizes.remove(avo.local);
break;
}
}
}
}
}
// check for un full init array
for (Iterator<Map.Entry<Local, ArrayObject>> it = arraySizes.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<Local, ArrayObject> e = it.next();
Local local = e.getKey();
ArrayObject arrayObject = e.getValue();
for (Stmt use : arrayObject.used) {
ArrayObjectValue[] frame = (ArrayObjectValue[]) use.frame;
ArrayObjectValue aov = frame[local._ls_index];
BitSet pos = aov.pos;
if (pos.nextClearBit(0) < arrayObject.size || pos.nextSetBit(arrayObject.size) >= 0) {
it.remove();
break;
}
}
}
// clean up
for (Stmt stmt : method.stmts) {
stmt.frame = null;
}
}
use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class FillArrayTransformer method searchForArrayObject.
private Map<Local, ArrayObject> searchForArrayObject(IrMethod method) {
final Map<Local, ArrayObject> arraySizes = new HashMap<>();
if (method.locals.size() == 0) {
return arraySizes;
}
Cfg.createCFG(method);
Cfg.dfsVisit(method, new Cfg.DfsVisitor() {
@Override
public void onVisit(Stmt p) {
if (p.st == Stmt.ST.ASSIGN) {
if (p.getOp2().vt == Value.VT.NEW_ARRAY && p.getOp1().vt == Value.VT.LOCAL) {
TypeExpr ae = (TypeExpr) p.getOp2();
if (ae.getOp().vt == Value.VT.CONSTANT) {
int size = ((Number) ((Constant) ae.getOp()).value).intValue();
// }
if (size >= 0) {
arraySizes.put((Local) p.getOp1(), new ArrayObject(size, ae.type, (AssignStmt) p));
}
}
} else if (p.getOp1().vt == Value.VT.ARRAY) {
ArrayExpr ae = (ArrayExpr) p.getOp1();
if (ae.getOp1().vt == Value.VT.LOCAL) {
Local local = (Local) ae.getOp1();
ArrayObject arrayObject = arraySizes.get(local);
if (arrayObject != null) {
if (ae.getOp2().vt == Value.VT.CONSTANT) {
arrayObject.putItem.add(p);
} else {
arraySizes.remove(local);
}
}
}
}
} else if (p.st == Stmt.ST.FILL_ARRAY_DATA) {
if (p.getOp1().vt == Value.VT.LOCAL) {
Local local = (Local) p.getOp1();
ArrayObject arrayObject = arraySizes.get(local);
if (arrayObject != null) {
arrayObject.putItem.add(p);
}
}
}
}
});
if (arraySizes.size() > 0) {
Set<Local> set = new HashSet<Local>();
if (method.phiLabels != null) {
for (LabelStmt labelStmt : method.phiLabels) {
if (labelStmt.phis != null) {
for (AssignStmt as : labelStmt.phis) {
set.add((Local) as.getOp1());
for (Value v : as.getOp2().getOps()) {
set.add((Local) v);
}
}
}
}
}
if (set.size() > 0) {
for (Local local : set) {
arraySizes.remove(local);
}
}
}
return arraySizes;
}
use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class UnSSATransformer method transform.
@Override
public void transform(IrMethod method) {
if (method.phiLabels == null || method.phiLabels.size() == 0) {
return;
}
// 1. Live analyze the method,
// a. remove Phi,
// b. record parameter reference
LiveA liveA = new LiveA(method);
liveA.analyze();
genRegGraph(method, liveA);
// 2. insert x=y
fixPhi(method, method.phiLabels);
insertAssignPath(method, method.phiLabels);
// 4. clean up
for (Local local : method.locals) {
local.tag = null;
}
for (Stmt stmt : method.stmts) {
stmt.frame = null;
}
for (LabelStmt labelStmt : method.phiLabels) {
labelStmt.phis = null;
}
method.phiLabels = null;
}
use of com.googlecode.dex2jar.ir.stmt.Stmt 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);
}
}
}
}
}
}
use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class UnSSATransformer method genRegGraph.
private void genRegGraph(IrMethod method, LiveA liveA) {
for (Local local : method.locals) {
local.tag = new RegAssign();
}
Set<Stmt> tos = new HashSet<>();
for (Stmt stmt : method.stmts) {
if ((stmt.st == ST.ASSIGN || stmt.st == ST.IDENTITY) && stmt.getOp1().vt == VT.LOCAL) {
Local localAssignTo = (Local) stmt.getOp1();
RegAssign regAssignTo = (RegAssign) localAssignTo.tag;
Set<Integer> excludeIdx = new HashSet<>();
Cfg.collectTos(stmt, tos);
for (Stmt target : tos) {
LiveV[] frame = (LiveV[]) target.frame;
if (frame == null) {
continue;
}
// exclude thisReg and phiReg
excludeIdx.clear();
excludeIdx.add(localAssignTo._ls_index);
if (target.st == ST.LABEL) {
LabelStmt label = (LabelStmt) target;
if (label.phis != null) {
for (AssignStmt phiAssignStmt : (List<AssignStmt>) label.phis) {
Local phiLocal = (Local) phiAssignStmt.getOp1();
excludeIdx.add(phiLocal._ls_index);
}
}
}
for (int i = 0; i < frame.length; i++) {
if (excludeIdx.contains(i)) {
continue;
}
LiveV v = frame[i];
if (v != null && v.used) {
RegAssign b = (RegAssign) v.local.tag;
regAssignTo.excludes.add(b);
b.excludes.add(regAssignTo);
}
}
}
tos.clear();
} else if (stmt.st == ST.LABEL) {
//
LabelStmt label = (LabelStmt) stmt;
if (label.phis != null) {
for (AssignStmt phiAssignStmt : (List<AssignStmt>) label.phis) {
Local phiLocal = (Local) phiAssignStmt.getOp1();
RegAssign a = (RegAssign) phiLocal.tag;
LiveV[] frame = (LiveV[]) stmt.frame;
for (LiveV v : frame) {
if (v != null && v.used) {
RegAssign b = (RegAssign) v.local.tag;
a.excludes.add(b);
b.excludes.add(a);
}
}
}
}
}
}
if (DEBUG) {
System.out.println(liveA.toString());
}
}
Aggregations