mirror of
https://github.com/pxb1988/dex2jar.git
synced 2024-11-23 13:19:46 +00:00
merge LiveAnalyze to use BaseLiveAnalyze
--HG-- branch : 0.0.9.x
This commit is contained in:
parent
12873f296f
commit
72b5089d54
@ -18,32 +18,17 @@ package com.googlecode.dex2jar.ir.ts;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.googlecode.dex2jar.ir.IrMethod;
|
||||
import com.googlecode.dex2jar.ir.Local;
|
||||
import com.googlecode.dex2jar.ir.Value;
|
||||
import com.googlecode.dex2jar.ir.Value.E1Expr;
|
||||
import com.googlecode.dex2jar.ir.Value.E2Expr;
|
||||
import com.googlecode.dex2jar.ir.Value.EnExpr;
|
||||
import com.googlecode.dex2jar.ir.Value.VT;
|
||||
import com.googlecode.dex2jar.ir.ValueBox;
|
||||
import com.googlecode.dex2jar.ir.stmt.AssignStmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.EnStmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.ST;
|
||||
import com.googlecode.dex2jar.ir.ts.Cfg.FrameVisitor;
|
||||
|
||||
public class LiveAnalyze {
|
||||
public static class Phi {
|
||||
public class LiveAnalyze extends BaseLiveAnalyze {
|
||||
public static class LivePhi extends Phi {
|
||||
public Local local;
|
||||
public Set<Phi> sets = new HashSet<Phi>(3);
|
||||
public Phi tag;
|
||||
public boolean used;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -57,155 +42,41 @@ public class LiveAnalyze {
|
||||
}
|
||||
}
|
||||
|
||||
private static void doAddUsed(Phi r, Set<Phi> regs) {
|
||||
if (r.used) {
|
||||
if (!regs.contains(r)) {
|
||||
regs.add(r);
|
||||
for (Phi p : r.sets) {
|
||||
p.used = true;
|
||||
doAddUsed(p, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Phi trim(Phi phi) {
|
||||
private static LivePhi trim(LivePhi phi) {
|
||||
while (phi.tag != null) {
|
||||
phi = phi.tag;
|
||||
phi = (LivePhi) phi.tag;
|
||||
}
|
||||
return phi;
|
||||
}
|
||||
|
||||
protected int localSize;
|
||||
protected IrMethod method;
|
||||
|
||||
public LiveAnalyze(IrMethod method) {
|
||||
super();
|
||||
this.method = method;
|
||||
this.localSize = method.locals.size();
|
||||
super(method);
|
||||
|
||||
}
|
||||
|
||||
public List<Phi> analyze() {
|
||||
init();
|
||||
return analyze0();
|
||||
@Override
|
||||
protected void onUseLocal(Phi phi, Local local) {
|
||||
LivePhi phi2 = (LivePhi) phi;
|
||||
phi2.local = local;
|
||||
}
|
||||
|
||||
protected List<Phi> analyze0() {
|
||||
protected Phi newPhi() {
|
||||
return new LivePhi();
|
||||
}
|
||||
|
||||
final List<Phi> phis = new ArrayList<Phi>();
|
||||
@Override
|
||||
protected void analyzePhi() {
|
||||
Set<Phi> used = super.markUsed();
|
||||
|
||||
Cfg.createCfgForLiveAnalyze(method);
|
||||
Cfg.Forward(method, new FrameVisitor<Phi[]>() {
|
||||
|
||||
@Override
|
||||
public Phi[] exec(Stmt stmt) {
|
||||
Phi[] frame = (Phi[]) stmt._ls_forward_frame;
|
||||
if (frame == null) {
|
||||
frame = new Phi[localSize];
|
||||
stmt._ls_forward_frame = frame;
|
||||
}
|
||||
Phi[] result = frame;
|
||||
switch (stmt.et) {
|
||||
case E0:
|
||||
break;
|
||||
case E1:
|
||||
use(((E1Stmt) stmt).op, result);
|
||||
break;
|
||||
case E2:
|
||||
E2Stmt e2 = (E2Stmt) stmt;
|
||||
if ((e2.st == ST.ASSIGN || e2.st == ST.IDENTITY) && (((AssignStmt) stmt).op1.value.vt == VT.LOCAL)) {
|
||||
Local local = (Local) ((AssignStmt) stmt).op1.value;
|
||||
use(e2.op2, result);
|
||||
result = new Phi[localSize];
|
||||
System.arraycopy(frame, 0, result, 0, localSize);
|
||||
Phi phi = new Phi();
|
||||
phis.add(phi);
|
||||
result[local._ls_index] = phi;
|
||||
} else {
|
||||
use(e2.op1, result);
|
||||
use(e2.op2, result);
|
||||
}
|
||||
break;
|
||||
case En:
|
||||
EnStmt en = (EnStmt) stmt;
|
||||
for (ValueBox vb : en.ops) {
|
||||
use(vb, result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(Phi[] frame, Stmt dist) {
|
||||
Phi[] distFrame = (Phi[]) dist._ls_forward_frame;
|
||||
if (distFrame == null) {
|
||||
distFrame = new Phi[localSize];
|
||||
dist._ls_forward_frame = distFrame;
|
||||
}
|
||||
|
||||
for (int i = 0; i < localSize; i++) {
|
||||
Phi srcPhi = frame[i];
|
||||
if (srcPhi != null) {
|
||||
Phi distPhi = distFrame[i];
|
||||
if (distPhi == null) {
|
||||
if (!dist._cfg_visited) {
|
||||
distPhi = new Phi();
|
||||
phis.add(distPhi);
|
||||
distFrame[i] = distPhi;
|
||||
distPhi.sets.add(srcPhi);
|
||||
}
|
||||
} else {
|
||||
distPhi.sets.add(srcPhi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void use(ValueBox op, Phi[] frame) {
|
||||
if (op == null) {
|
||||
return;
|
||||
}
|
||||
Value v = op.value;
|
||||
switch (v.et) {
|
||||
case E0:
|
||||
if (v.vt == VT.LOCAL) {
|
||||
Local local = (Local) v;
|
||||
frame[local._ls_index].used = true;
|
||||
frame[local._ls_index].local = local;
|
||||
}
|
||||
break;
|
||||
case E1:
|
||||
use(((E1Expr) v).op, frame);
|
||||
break;
|
||||
case E2:
|
||||
E2Expr e2 = (E2Expr) v;
|
||||
use(e2.op1, frame);
|
||||
use(e2.op2, frame);
|
||||
break;
|
||||
case En:
|
||||
EnExpr en = (EnExpr) v;
|
||||
for (ValueBox vb : en.ops) {
|
||||
use(vb, frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Set<Phi> used = new HashSet<Phi>(phis.size() / 2);
|
||||
for (Phi reg : phis) {
|
||||
doAddUsed(reg, used);
|
||||
}
|
||||
for (Phi reg : used) {
|
||||
Phi a = trim(reg);
|
||||
for (Phi x : used) {
|
||||
LivePhi reg = (LivePhi) x;
|
||||
LivePhi a = trim(reg);
|
||||
if (a != reg && reg.local != null) {
|
||||
a.local = reg.local;
|
||||
}
|
||||
if (reg.sets.size() > 0) {
|
||||
for (Phi r : reg.sets) {
|
||||
Phi b = trim(r);
|
||||
if (reg.parents.size() > 0) {
|
||||
for (Phi r : reg.parents) {
|
||||
LivePhi b = trim((LivePhi) r);
|
||||
if (a != b) {
|
||||
b.tag = a;
|
||||
if (b.local != null) {
|
||||
@ -223,7 +94,7 @@ public class LiveAnalyze {
|
||||
Phi r = frame[i];
|
||||
if (r != null) {
|
||||
if (r.used) {
|
||||
frame[i] = trim(r);
|
||||
frame[i] = trim((LivePhi) r);
|
||||
} else {
|
||||
frame[i] = null;
|
||||
}
|
||||
@ -233,9 +104,10 @@ public class LiveAnalyze {
|
||||
}
|
||||
|
||||
phis.clear();
|
||||
for (Phi r : used) {
|
||||
for (Phi x : used) {
|
||||
LivePhi r = (LivePhi) x;
|
||||
if (r.used && r.tag == null) {
|
||||
r.sets.clear();
|
||||
r.parents.clear();
|
||||
phis.add(r);
|
||||
}
|
||||
}
|
||||
@ -243,21 +115,16 @@ public class LiveAnalyze {
|
||||
|
||||
// reduce the size of nPhis
|
||||
List<Phi> nPhis = new ArrayList<Phi>(phis);
|
||||
|
||||
phis.clear();
|
||||
Collections.sort(nPhis, new Comparator<Phi>() {
|
||||
@Override
|
||||
public int compare(Phi o1, Phi o2) {
|
||||
return o1.local._ls_index - o2.local._ls_index;
|
||||
LivePhi a1 = (LivePhi) o1;
|
||||
LivePhi a2 = (LivePhi) o2;
|
||||
return a1.local._ls_index - a2.local._ls_index;
|
||||
}
|
||||
});
|
||||
return nPhis;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
int index = 0;
|
||||
for (Local local : method.locals) {
|
||||
local._ls_index = index++;
|
||||
}
|
||||
phis.addAll(nPhis);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,10 +44,11 @@ import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.Stmt.ST;
|
||||
import com.googlecode.dex2jar.ir.stmt.TableSwitchStmt;
|
||||
import com.googlecode.dex2jar.ir.stmt.UnopStmt;
|
||||
import com.googlecode.dex2jar.ir.ts.BaseLiveAnalyze.Phi;
|
||||
import com.googlecode.dex2jar.ir.ts.Cfg;
|
||||
import com.googlecode.dex2jar.ir.ts.Cfg.StmtVisitor;
|
||||
import com.googlecode.dex2jar.ir.ts.LiveAnalyze;
|
||||
import com.googlecode.dex2jar.ir.ts.LiveAnalyze.Phi;
|
||||
import com.googlecode.dex2jar.ir.ts.LiveAnalyze.LivePhi;
|
||||
import com.googlecode.dex2jar.ir.ts.LocalType;
|
||||
|
||||
public class IrMethod2AsmMethod implements Opcodes {
|
||||
@ -89,7 +90,8 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
|
||||
// 1. live local analyze
|
||||
LiveAnalyze la = new LiveAnalyze(ir);
|
||||
List<Phi> phis = la.analyze();
|
||||
la.analyze();
|
||||
List<Phi> phis = la.phis;
|
||||
if (V3.DEBUG) {
|
||||
for (Local local : ir.locals) {
|
||||
if (local._ls_index >= 0) {
|
||||
@ -165,21 +167,22 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
}
|
||||
|
||||
private void markPhiNeverReuse(List<Phi> phis, Local local) {
|
||||
Phi nPhi = null;
|
||||
for (Phi phi : phis) {
|
||||
LivePhi nPhi = null;
|
||||
for (Phi x : phis) {
|
||||
LivePhi phi = (LivePhi) x;
|
||||
if (phi.local == local) {
|
||||
nPhi = phi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nPhi == null) {
|
||||
nPhi = new Phi();
|
||||
nPhi = new LivePhi();
|
||||
nPhi.local = local;
|
||||
}
|
||||
for (Phi phi : phis) {
|
||||
if (phi != nPhi) {
|
||||
phi.sets.add(nPhi);
|
||||
nPhi.sets.add(phi);
|
||||
phi.parents.add(nPhi);
|
||||
nPhi.parents.add(phi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +190,8 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
private int findNextColor(Phi v, int n, int max, int[] maps) {
|
||||
BitSet bs = new BitSet(max);
|
||||
bs.set(0, max);
|
||||
for (Phi one : v.sets) {
|
||||
for (Phi t : v.parents) {
|
||||
LivePhi one = (LivePhi) t;
|
||||
int x = maps[one.local._ls_index];
|
||||
if (x >= 0) {
|
||||
bs.clear(x);
|
||||
@ -217,19 +221,19 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
Collections.sort(phis, new Comparator<Phi>() {
|
||||
@Override
|
||||
public int compare(Phi o1, Phi o2) {
|
||||
int r = o2.sets.size() - o1.sets.size();
|
||||
int r = o2.parents.size() - o1.parents.size();
|
||||
return r == 0 ? sizeOf(o2) - sizeOf(o1) : r;
|
||||
}
|
||||
});
|
||||
Phi first = phis.get(0);
|
||||
int size = sizeOf(first);
|
||||
for (Phi p : first.sets) {
|
||||
for (Phi p : first.parents) {
|
||||
size += sizeOf(p);
|
||||
}
|
||||
|
||||
BitSet toColor = new BitSet(phis.size());
|
||||
for (int i = 0; i < phis.size(); i++) {
|
||||
Phi p = phis.get(i);
|
||||
LivePhi p = (LivePhi) phis.get(i);
|
||||
if (maps[p.local._ls_index] < 0) {
|
||||
toColor.set(i);
|
||||
}
|
||||
@ -245,7 +249,7 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
if (x < 0) {
|
||||
return true;
|
||||
}
|
||||
Phi phi = phis.get(x);
|
||||
LivePhi phi = (LivePhi) phis.get(x);
|
||||
for (int i = findNextColor(phi, 0, size, maps); i >= 0; i = findNextColor(phi, i + 1, size, maps)) {
|
||||
maps[phi.local._ls_index] = i;
|
||||
if (doColor(x + 1, toColor, phis, size, maps)) {
|
||||
@ -257,7 +261,7 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
}
|
||||
|
||||
private static int sizeOf(Phi p) {
|
||||
return LocalType.typeOf(p.local).getSize();
|
||||
return LocalType.typeOf(((LivePhi) p).local).getSize();
|
||||
}
|
||||
|
||||
private void createGraph(IrMethod ir, int localSize) {
|
||||
@ -281,8 +285,8 @@ public class IrMethod2AsmMethod implements Opcodes {
|
||||
for (int j = i + 1; j < tmp.size(); j++) {
|
||||
Phi b = tmp.get(j);
|
||||
if (a != b) {
|
||||
a.sets.add(b);
|
||||
b.sets.add(a);
|
||||
a.parents.add(b);
|
||||
b.parents.add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user