merge LiveAnalyze to use BaseLiveAnalyze

--HG--
branch : 0.0.9.x
This commit is contained in:
Panxiaobo 2012-11-07 23:50:04 +08:00
parent 12873f296f
commit 72b5089d54
2 changed files with 50 additions and 179 deletions

View File

@ -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

View File

@ -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);
}
}
}